Skip to content

Commit

Permalink
feat: OIDC authorization in Feast Operator (#4801)
Browse files Browse the repository at this point in the history
* Initial commit

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* no private image

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* removed nameLabelKey, using serices.NameLabelKey

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* improved CRD comments and using IsLocalRegistry

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* fixing generated code

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* renamed auth condition and types

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* more renamings

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* initial commit

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* oidc IT

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* with sample

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

* no private image

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>

---------

Signed-off-by: Daniele Martinoli <dmartino@redhat.com>
  • Loading branch information
dmartinol authored Dec 4, 2024
1 parent 8181e9d commit eb111d6
Show file tree
Hide file tree
Showing 16 changed files with 1,035 additions and 45 deletions.
8 changes: 8 additions & 0 deletions infra/feast-operator/api/v1alpha1/featurestore_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,10 @@ type OptionalConfigs 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."
type AuthzConfig struct {
KubernetesAuthz *KubernetesAuthz `json:"kubernetes,omitempty"`
OidcAuthz *OidcAuthz `json:"oidc,omitempty"`
}

// KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources.
Expand All @@ -296,6 +298,12 @@ type KubernetesAuthz struct {
Roles []string `json:"roles,omitempty"`
}

// OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
// https://auth0.com/docs/authenticate/protocols/openid-connect-protocol
type OidcAuthz struct {
SecretRef corev1.LocalObjectReference `json:"secretRef"`
}

// TlsConfigs configures server TLS for a feast service. in an openshift cluster, this is configured by default using service serving certificates.
// +kubebuilder:validation:XValidation:rule="(!has(self.disable) || !self.disable) ? has(self.secretRef) : true",message="`secretRef` required if `disable` is false."
type TlsConfigs struct {
Expand Down
21 changes: 21 additions & 0 deletions infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,31 @@ spec:
type: string
type: array
type: object
oidc:
description: |-
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.com/docs/authenticate/protocols/openid-connect-protocol
properties:
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?
type: string
type: object
x-kubernetes-map-type: atomic
required:
- secretRef
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)'
feastProject:
description: FeastProject is the Feast project id. This can be any
alphanumeric string with underscores, but it cannot start with an
Expand Down Expand Up @@ -1238,7 +1262,32 @@ spec:
type: string
type: array
type: object
oidc:
description: |-
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.com/docs/authenticate/protocols/openid-connect-protocol
properties:
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?
type: string
type: object
x-kubernetes-map-type: atomic
required:
- secretRef
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)'
feastProject:
description: FeastProject is the Feast project id. This can be
any alphanumeric string with underscores, but it cannot start
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apiVersion: feast.dev/v1alpha1
kind: FeatureStore
metadata:
name: sample-oidc-auth
spec:
feastProject: my_project
services:
onlineStore:
persistence:
file:
path: /data/online_store.db
offlineStore:
persistence:
file:
type: dask
registry:
local:
persistence:
file:
path: /data/registry.db
authz:
oidc:
secretRef:
name: oidc-secret
---
kind: Secret
apiVersion: v1
metadata:
name: oidc-secret
stringData:
client_id: client_id
auth_discovery_url: auth_discovery_url
client_secret: client_secret
username: username
password: password
49 changes: 49 additions & 0 deletions infra/feast-operator/dist/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,31 @@ spec:
type: string
type: array
type: object
oidc:
description: |-
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.com/docs/authenticate/protocols/openid-connect-protocol
properties:
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?
type: string
type: object
x-kubernetes-map-type: atomic
required:
- secretRef
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)'
feastProject:
description: FeastProject is the Feast project id. This can be any
alphanumeric string with underscores, but it cannot start with an
Expand Down Expand Up @@ -1246,7 +1270,32 @@ spec:
type: string
type: array
type: object
oidc:
description: |-
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.com/docs/authenticate/protocols/openid-connect-protocol
properties:
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?
type: string
type: object
x-kubernetes-map-type: atomic
required:
- secretRef
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)'
feastProject:
description: FeastProject is the Feast project id. This can be
any alphanumeric string with underscores, but it cannot start
Expand Down
14 changes: 6 additions & 8 deletions infra/feast-operator/internal/controller/authz/authz.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ import (
// Deploy the feast authorization
func (authz *FeastAuthorization) Deploy() error {
if authz.isKubernetesAuth() {
if err := authz.deployKubernetesAuth(); err != nil {
return err
}
} else {
authz.removeOrphanedRoles()
_ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRole())
_ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRoleBinding())
apimeta.RemoveStatusCondition(&authz.Handler.FeatureStore.Status.Conditions, feastKubernetesAuthConditions[metav1.ConditionTrue].Type)
return authz.deployKubernetesAuth()
}

authz.removeOrphanedRoles()
_ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRole())
_ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRoleBinding())
apimeta.RemoveStatusCondition(&authz.Handler.FeatureStore.Status.Conditions, feastKubernetesAuthConditions[metav1.ConditionTrue].Type)
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,9 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() {
Expect(err).To(HaveOccurred())
Expect(errors.IsNotFound(err)).To(BeTrue())

By("Clearing the kubernetes authorizatino and reconciling")
By("Clearing the kubernetes authorization and reconciling")
resourceNew = resource.DeepCopy()
resourceNew.Spec.AuthzConfig = &feastdevv1alpha1.AuthzConfig{}
resourceNew.Spec.AuthzConfig = nil
err = k8sClient.Update(ctx, resourceNew)
Expect(err).NotTo(HaveOccurred())
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
Expand Down
Loading

0 comments on commit eb111d6

Please sign in to comment.