From 4c0ad4a0fed1775a1768d23ec181d6a9947bb6a1 Mon Sep 17 00:00:00 2001 From: ntkathole Date: Thu, 13 Aug 2026 22:01:46 +0530 Subject: [PATCH] fix: Add noAuth option to FeatureStore CRD for explicit auth opt-out Signed-off-by: ntkathole --- .secrets.baseline | 18 ++++----- .../api/v1/featurestore_types.go | 7 +++- .../api/v1/zz_generated.deepcopy.go | 5 +++ .../api/v1alpha1/featurestore_types.go | 7 +++- .../api/v1alpha1/zz_generated.deepcopy.go | 5 +++ .../manifests/feast.dev_featurestores.yaml | 40 +++++++++++++++---- .../crd/bases/feast.dev_featurestores.yaml | 34 ++++++++++++---- infra/feast-operator/dist/install.yaml | 34 ++++++++++++---- infra/feast-operator/docs/api/markdown/ref.md | 3 ++ .../controller/services/repo_config.go | 6 ++- .../controller/services/repo_config_test.go | 18 +++++++++ .../test/api/featurestore_types_test.go | 2 +- 12 files changed, 142 insertions(+), 37 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 62d7fd33f37..4d0de3d2a5f 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -957,7 +957,7 @@ "filename": "infra/feast-operator/api/v1/featurestore_types.go", "hashed_secret": "44e17306b837162269a410204daaa5ecee4ec22c", "is_verified": false, - "line_number": 958 + "line_number": 963 } ], "infra/feast-operator/api/v1/zz_generated.deepcopy.go": [ @@ -966,21 +966,21 @@ "filename": "infra/feast-operator/api/v1/zz_generated.deepcopy.go", "hashed_secret": "f914fc9324de1bec1ad13dec94a8ea2ddb41fc87", "is_verified": false, - "line_number": 842 + "line_number": 847 }, { "type": "Secret Keyword", "filename": "infra/feast-operator/api/v1/zz_generated.deepcopy.go", "hashed_secret": "44e17306b837162269a410204daaa5ecee4ec22c", "is_verified": false, - "line_number": 903 + "line_number": 908 }, { "type": "Secret Keyword", "filename": "infra/feast-operator/api/v1/zz_generated.deepcopy.go", "hashed_secret": "c2028031c154bbe86fd69bef740855c74b927dcf", "is_verified": false, - "line_number": 1595 + "line_number": 1600 } ], "infra/feast-operator/api/v1alpha1/featurestore_types.go": [ @@ -989,7 +989,7 @@ "filename": "infra/feast-operator/api/v1alpha1/featurestore_types.go", "hashed_secret": "44e17306b837162269a410204daaa5ecee4ec22c", "is_verified": false, - "line_number": 663 + "line_number": 668 } ], "infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go": [ @@ -998,21 +998,21 @@ "filename": "infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go", "hashed_secret": "f914fc9324de1bec1ad13dec94a8ea2ddb41fc87", "is_verified": false, - "line_number": 615 + "line_number": 620 }, { "type": "Secret Keyword", "filename": "infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go", "hashed_secret": "44e17306b837162269a410204daaa5ecee4ec22c", "is_verified": false, - "line_number": 1123 + "line_number": 1128 }, { "type": "Secret Keyword", "filename": "infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go", "hashed_secret": "c2028031c154bbe86fd69bef740855c74b927dcf", "is_verified": false, - "line_number": 1128 + "line_number": 1133 } ], "infra/feast-operator/bundle/manifests/openlineage-secret_v1_secret.yaml": [ @@ -1564,5 +1564,5 @@ } ] }, - "generated_at": "2026-07-31T05:29:18Z" + "generated_at": "2026-08-13T16:31:14Z" } diff --git a/infra/feast-operator/api/v1/featurestore_types.go b/infra/feast-operator/api/v1/featurestore_types.go index 3372e74f63a..d83c005485b 100644 --- a/infra/feast-operator/api/v1/featurestore_types.go +++ b/infra/feast-operator/api/v1/featurestore_types.go @@ -889,10 +889,15 @@ type OptionalCtrConfigs struct { } // AuthzConfig defines the authorization settings for the deployed Feast services. -// +kubebuilder:validation:XValidation:rule="[has(self.kubernetes), has(self.oidc)].exists_one(c, c)",message="One selection required between kubernetes or oidc." +// +kubebuilder:validation:XValidation:rule="[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)",message="One selection required between kubernetes, oidc, or noAuth." type AuthzConfig struct { KubernetesAuthz *KubernetesAuthz `json:"kubernetes,omitempty"` OidcAuthz *OidcAuthz `json:"oidc,omitempty"` + // NoAuth explicitly disables authentication and authorization. + // When set to true, Feast services run without any auth checks. + // Use only for development or testing environments. + // +optional + NoAuth *bool `json:"noAuth,omitempty"` } // KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. diff --git a/infra/feast-operator/api/v1/zz_generated.deepcopy.go b/infra/feast-operator/api/v1/zz_generated.deepcopy.go index 3035ed066cf..96fcb9027f0 100644 --- a/infra/feast-operator/api/v1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1/zz_generated.deepcopy.go @@ -43,6 +43,11 @@ func (in *AuthzConfig) DeepCopyInto(out *AuthzConfig) { *out = new(OidcAuthz) (*in).DeepCopyInto(*out) } + if in.NoAuth != nil { + in, out := &in.NoAuth, &out.NoAuth + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthzConfig. diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 8ccde377e77..aabb2103598 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -621,10 +621,15 @@ type OptionalCtrConfigs struct { } // AuthzConfig defines the authorization settings for the deployed Feast services. -// +kubebuilder:validation:XValidation:rule="[has(self.kubernetes), has(self.oidc)].exists_one(c, c)",message="One selection required between kubernetes or oidc." +// +kubebuilder:validation:XValidation:rule="[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)",message="One selection required between kubernetes, oidc, or noAuth." type AuthzConfig struct { KubernetesAuthz *KubernetesAuthz `json:"kubernetes,omitempty"` OidcAuthz *OidcAuthz `json:"oidc,omitempty"` + // NoAuth explicitly disables authentication and authorization. + // When set to true, Feast services run without any auth checks. + // Use only for development or testing environments. + // +optional + NoAuth *bool `json:"noAuth,omitempty"` } // KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. diff --git a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go index 17ae4841966..2345d07533a 100644 --- a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -41,6 +41,11 @@ func (in *AuthzConfig) DeepCopyInto(out *AuthzConfig) { *out = new(OidcAuthz) **out = **in } + if in.NoAuth != nil { + in, out := &in.NoAuth, &out.NoAuth + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthzConfig. diff --git a/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml b/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml index 0ab08afef51..94dc71f7c9c 100644 --- a/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml +++ b/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml @@ -57,6 +57,11 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and authorization. + When set to true, Feast services run without any auth checks. + Use only for development or testing environments. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -109,8 +114,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' + - message: One selection required between kubernetes, oidc, or noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, + c)' batchEngine: description: BatchEngineConfig defines the batch compute engine configuration. properties: @@ -6366,6 +6372,11 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and + authorization. When set to true, Feast services run without + any auth checks. Use only for development or testing environments. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -6418,8 +6429,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + - message: One selection required between kubernetes, oidc, or + noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)' batchEngine: description: BatchEngineConfig defines the batch compute engine @@ -12883,6 +12895,11 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and authorization. + When set to true, Feast services run without any auth checks. + Use only for development or testing environments. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -12907,8 +12924,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' + - message: One selection required between kubernetes, oidc, or noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, + c)' cronJob: description: FeastCronJob defines a CronJob to execute against a Feature Store deployment. @@ -17392,6 +17410,11 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and + authorization. When set to true, Feast services run without + any auth checks. Use only for development or testing environments. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -17416,8 +17439,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + - message: One selection required between kubernetes, oidc, or + noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)' cronJob: description: FeastCronJob defines a CronJob to execute against diff --git a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml index 8184906e14d..23f76ddaa1d 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -57,6 +57,9 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -109,8 +112,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' + - message: One selection required between kubernetes, oidc, or noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, + c)' batchEngine: description: BatchEngineConfig defines the batch compute engine configuration. properties: @@ -6366,6 +6370,10 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and + authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -6418,8 +6426,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + - message: One selection required between kubernetes, oidc, or + noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)' batchEngine: description: BatchEngineConfig defines the batch compute engine @@ -12883,6 +12892,9 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -12907,8 +12919,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' + - message: One selection required between kubernetes, oidc, or noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, + c)' cronJob: description: FeastCronJob defines a CronJob to execute against a Feature Store deployment. @@ -17392,6 +17405,10 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and + authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -17416,8 +17433,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + - message: One selection required between kubernetes, oidc, or + noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)' cronJob: description: FeastCronJob defines a CronJob to execute against diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index be85a29a7b2..df2ccf1764c 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -65,6 +65,9 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -117,8 +120,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' + - message: One selection required between kubernetes, oidc, or noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, + c)' batchEngine: description: BatchEngineConfig defines the batch compute engine configuration. properties: @@ -6374,6 +6378,10 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and + authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -6426,8 +6434,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + - message: One selection required between kubernetes, oidc, or + noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)' batchEngine: description: BatchEngineConfig defines the batch compute engine @@ -12891,6 +12900,9 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -12915,8 +12927,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' + - message: One selection required between kubernetes, oidc, or noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, + c)' cronJob: description: FeastCronJob defines a CronJob to execute against a Feature Store deployment. @@ -17400,6 +17413,10 @@ spec: type: string type: array type: object + noAuth: + description: NoAuth explicitly disables authentication and + authorization. + type: boolean oidc: description: |- OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. @@ -17424,8 +17441,9 @@ spec: type: object type: object x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + - message: One selection required between kubernetes, oidc, or + noAuth. + rule: '[has(self.kubernetes), has(self.oidc), has(self.noAuth)].exists_one(c, c)' cronJob: description: FeastCronJob defines a CronJob to execute against diff --git a/infra/feast-operator/docs/api/markdown/ref.md b/infra/feast-operator/docs/api/markdown/ref.md index cb911ffae22..03ab37e92d1 100644 --- a/infra/feast-operator/docs/api/markdown/ref.md +++ b/infra/feast-operator/docs/api/markdown/ref.md @@ -26,6 +26,9 @@ _Appears in:_ | --- | --- | | `kubernetes` _[KubernetesAuthz](#kubernetesauthz)_ | | | `oidc` _[OidcAuthz](#oidcauthz)_ | | +| `noAuth` _boolean_ | NoAuth explicitly disables authentication and authorization. +When set to true, Feast services run without any auth checks. +Use only for development or testing environments. | #### AutoscalingConfig diff --git a/infra/feast-operator/internal/controller/services/repo_config.go b/infra/feast-operator/internal/controller/services/repo_config.go index b4a01b312b1..84255e03856 100644 --- a/infra/feast-operator/internal/controller/services/repo_config.go +++ b/infra/feast-operator/internal/controller/services/repo_config.go @@ -620,7 +620,11 @@ func getRepoConfig(featureStore *feastdevv1.FeatureStore) RepoConfig { status := featureStore.Status repoConfig := initRepoConfig(status.Applied.FeastProject) if status.Applied.AuthzConfig != nil { - if status.Applied.AuthzConfig.KubernetesAuthz != nil { + if status.Applied.AuthzConfig.NoAuth != nil && *status.Applied.AuthzConfig.NoAuth { + repoConfig.AuthzConfig = AuthzConfig{ + Type: NoAuthAuthType, + } + } else if status.Applied.AuthzConfig.KubernetesAuthz != nil { repoConfig.AuthzConfig = AuthzConfig{ Type: KubernetesAuthType, } diff --git a/infra/feast-operator/internal/controller/services/repo_config_test.go b/infra/feast-operator/internal/controller/services/repo_config_test.go index e87efdf7dec..3575f490aae 100644 --- a/infra/feast-operator/internal/controller/services/repo_config_test.go +++ b/infra/feast-operator/internal/controller/services/repo_config_test.go @@ -197,7 +197,25 @@ var _ = Describe("Repo Config", func() { Expect(repoConfig.OnlineStore).To(Equal(defaultOnlineStoreConfig(featureStore))) Expect(repoConfig.Registry).To(Equal(defaultRegistryConfig(featureStore))) + By("Having noAuth explicitly set") + featureStore = minimalFeatureStore() + featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ + NoAuth: boolPtr(true), + } + ApplyDefaultsToStatus(featureStore) + repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) + Expect(err).NotTo(HaveOccurred()) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) + By("Having oidc authorization with Secret") + featureStore = minimalFeatureStore() + featureStore.Spec.Services = &feastdevv1.FeatureStoreServices{ + OfflineStore: &feastdevv1.OfflineStore{}, + OnlineStore: &feastdevv1.OnlineStore{}, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{}, + }, + } featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ OidcAuthz: &feastdevv1.OidcAuthz{ SecretRef: &corev1.LocalObjectReference{ diff --git a/infra/feast-operator/test/api/featurestore_types_test.go b/infra/feast-operator/test/api/featurestore_types_test.go index 00312e0fabb..02e9f61b023 100644 --- a/infra/feast-operator/test/api/featurestore_types_test.go +++ b/infra/feast-operator/test/api/featurestore_types_test.go @@ -608,7 +608,7 @@ var _ = Describe("FeatureStore API", func() { Context("When configuring the AuthzConfig", func() { ctx, featurestore := initContext() It("should fail when both kubernetes and oidc settings are given", func() { - attemptInvalidCreationAndAsserts(ctx, authzConfigWithOidc(authzConfigWithKubernetes(featurestore)), "One selection required between kubernetes or oidc") + attemptInvalidCreationAndAsserts(ctx, authzConfigWithOidc(authzConfigWithKubernetes(featurestore)), "One selection required between kubernetes, oidc, or noAuth") }) })