From ae2eaf22dedb520fc73fb7f776923cec360d8f9e Mon Sep 17 00:00:00 2001 From: Daniele Martinoli Date: Tue, 26 Nov 2024 21:07:44 +0100 Subject: [PATCH] renamed auth condition and types Signed-off-by: Daniele Martinoli --- .../api/v1alpha1/featurestore_types.go | 18 +- .../api/v1alpha1/zz_generated.deepcopy.go | 14 +- .../crd/bases/feast.dev_featurestores.yaml | 8 +- ...v1alpha1_featurestore_kubernetes_auth.yaml | 2 +- infra/feast-operator/dist/install.yaml | 8 +- .../internal/controller/auth/auth.go | 220 ------------------ .../internal/controller/authz/authz.go | 220 ++++++++++++++++++ .../auth_types.go => authz/authz_types.go} | 10 +- .../controller/featurestore_controller.go | 6 +- .../featurestore_controller_ephemeral_test.go | 18 +- ...restore_controller_kubernetes_auth_test.go | 32 +-- ...eaturestore_controller_objectstore_test.go | 8 +- .../featurestore_controller_pvc_test.go | 18 +- .../featurestore_controller_test.go | 42 ++-- .../controller/services/repo_config.go | 8 +- .../controller/services/repo_config_test.go | 34 +-- .../controller/services/services_types.go | 6 +- .../internal/controller/services/util.go | 4 +- .../test/api/featurestore_types_test.go | 6 +- 19 files changed, 341 insertions(+), 341 deletions(-) delete mode 100644 infra/feast-operator/internal/controller/auth/auth.go create mode 100644 infra/feast-operator/internal/controller/authz/authz.go rename infra/feast-operator/internal/controller/{auth/auth_types.go => authz/authz_types.go} (73%) diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 405b9a739f..a53ad035d4 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -28,12 +28,12 @@ const ( FailedPhase = "Failed" // Feast condition types: - ClientReadyType = "Client" - OfflineStoreReadyType = "OfflineStore" - OnlineStoreReadyType = "OnlineStore" - RegistryReadyType = "Registry" - ReadyType = "FeatureStore" - KubernetesAuthReadyType = "KubernetesAuth" + ClientReadyType = "Client" + OfflineStoreReadyType = "OfflineStore" + OnlineStoreReadyType = "OnlineStore" + RegistryReadyType = "Registry" + ReadyType = "FeatureStore" + AuthorizationReadyType = "AuthorizationReadyType" // Feast condition reasons: ReadyReason = "Ready" @@ -62,7 +62,7 @@ type FeatureStoreSpec struct { // FeastProject is the Feast project id. This can be any alphanumeric string with underscores, but it cannot start with an underscore. Required. FeastProject string `json:"feastProject"` Services *FeatureStoreServices `json:"services,omitempty"` - AuthConfig *AuthConfig `json:"auth,omitempty"` + AuthzConfig *AuthzConfig `json:"authz,omitempty"` } // FeatureStoreServices defines the desired feast service deployments. ephemeral registry is deployed by default. @@ -209,8 +209,8 @@ type OptionalConfigs struct { Resources *corev1.ResourceRequirements `json:"resources,omitempty"` } -// AuthConfig defines the authorization settings for the deployed Feast services. -type AuthConfig struct { +// AuthzConfig defines the authorization settings for the deployed Feast services. +type AuthzConfig struct { KubernetesAuth *KubernetesAuth `json:"kubernetes,omitempty"` } diff --git a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go index 2359b22a69..b8bd092279 100644 --- a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -27,7 +27,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AuthConfig) DeepCopyInto(out *AuthConfig) { +func (in *AuthzConfig) DeepCopyInto(out *AuthzConfig) { *out = *in if in.KubernetesAuth != nil { in, out := &in.KubernetesAuth, &out.KubernetesAuth @@ -36,12 +36,12 @@ func (in *AuthConfig) DeepCopyInto(out *AuthConfig) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthConfig. -func (in *AuthConfig) DeepCopy() *AuthConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthzConfig. +func (in *AuthzConfig) DeepCopy() *AuthzConfig { if in == nil { return nil } - out := new(AuthConfig) + out := new(AuthzConfig) in.DeepCopyInto(out) return out } @@ -178,9 +178,9 @@ func (in *FeatureStoreSpec) DeepCopyInto(out *FeatureStoreSpec) { *out = new(FeatureStoreServices) (*in).DeepCopyInto(*out) } - if in.AuthConfig != nil { - in, out := &in.AuthConfig, &out.AuthConfig - *out = new(AuthConfig) + if in.AuthzConfig != nil { + in, out := &in.AuthzConfig, &out.AuthzConfig + *out = new(AuthzConfig) (*in).DeepCopyInto(*out) } } 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 bbcf28b773..00f561baf1 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -48,8 +48,8 @@ spec: spec: description: FeatureStoreSpec defines the desired state of FeatureStore properties: - auth: - description: AuthConfig defines the authorization settings for the + authz: + description: AuthzConfig defines the authorization settings for the deployed Feast services. properties: kubernetes: @@ -966,8 +966,8 @@ spec: description: Shows the currently applied feast configuration, including any pertinent defaults properties: - auth: - description: AuthConfig defines the authorization settings for + authz: + description: AuthzConfig defines the authorization settings for the deployed Feast services. properties: kubernetes: diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml index 17b40e51ee..ed95b41cf4 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml @@ -18,7 +18,7 @@ spec: persistence: file: path: /data/registry.db - auth: + authz: kubernetes: roles: - reader diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index 6581e4d3a1..a649942d3d 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -56,8 +56,8 @@ spec: spec: description: FeatureStoreSpec defines the desired state of FeatureStore properties: - auth: - description: AuthConfig defines the authorization settings for the + authz: + description: AuthzConfig defines the authorization settings for the deployed Feast services. properties: kubernetes: @@ -974,8 +974,8 @@ spec: description: Shows the currently applied feast configuration, including any pertinent defaults properties: - auth: - description: AuthConfig defines the authorization settings for + authz: + description: AuthzConfig defines the authorization settings for the deployed Feast services. properties: kubernetes: diff --git a/infra/feast-operator/internal/controller/auth/auth.go b/infra/feast-operator/internal/controller/auth/auth.go deleted file mode 100644 index 9db7d7a9c9..0000000000 --- a/infra/feast-operator/internal/controller/auth/auth.go +++ /dev/null @@ -1,220 +0,0 @@ -package auth - -import ( - "context" - "slices" - - feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" - "github.com/feast-dev/feast/infra/feast-operator/internal/controller/services" - rbacv1 "k8s.io/api/rbac/v1" - apimeta "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -// Deploy the feast authorization -func (auth *FeastAuth) Deploy() error { - authConfig := auth.Handler.FeatureStore.Status.Applied.AuthConfig - if authConfig != nil { - if authConfig.KubernetesAuth != nil { - if err := auth.deployKubernetesAuth(authConfig.KubernetesAuth); err != nil { - return err - } - } else { - auth.removeOrphanedRoles() - _ = auth.Handler.DeleteOwnedFeastObj(auth.initFeastRole()) - _ = auth.Handler.DeleteOwnedFeastObj(auth.initFeastRoleBinding()) - } - } - return nil -} - -func (auth *FeastAuth) deployKubernetesAuth(kubernetesAuth *feastdevv1alpha1.KubernetesAuth) error { - auth.removeOrphanedRoles() - - if err := auth.createFeastRole(); err != nil { - return auth.setFeastKubernetesAuthCondition(err) - } - if err := auth.createFeastRoleBinding(); err != nil { - return auth.setFeastKubernetesAuthCondition(err) - } - - for _, roleName := range kubernetesAuth.Roles { - if err := auth.createAuthRole(roleName); err != nil { - return auth.setFeastKubernetesAuthCondition(err) - } - } - return auth.setFeastKubernetesAuthCondition(nil) -} - -func (auth *FeastAuth) removeOrphanedRoles() { - roleList := &rbacv1.RoleList{} - err := auth.Handler.Client.List(context.TODO(), roleList, &client.ListOptions{ - Namespace: auth.Handler.FeatureStore.Namespace, - LabelSelector: labels.SelectorFromSet(auth.getLabels()), - }) - if err != nil { - return - } - - desiredRoles := []string{} - if auth.Handler.FeatureStore.Status.Applied.AuthConfig.KubernetesAuth != nil { - desiredRoles = auth.Handler.FeatureStore.Status.Applied.AuthConfig.KubernetesAuth.Roles - } - for _, role := range roleList.Items { - roleName := role.Name - if roleName != auth.getFeastRoleName() && !slices.Contains(desiredRoles, roleName) { - _ = auth.Handler.DeleteOwnedFeastObj(auth.initAuthRole(roleName)) - } - } -} - -func (auth *FeastAuth) createFeastRole() error { - logger := log.FromContext(auth.Handler.Context) - role := auth.initFeastRole() - if op, err := controllerutil.CreateOrUpdate(auth.Handler.Context, auth.Handler.Client, role, controllerutil.MutateFn(func() error { - return auth.setFeastRole(role) - })); err != nil { - return err - } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { - logger.Info("Successfully reconciled", "Role", role.Name, "operation", op) - } - - return nil -} - -func (auth *FeastAuth) initFeastRole() *rbacv1.Role { - role := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{Name: auth.getFeastRoleName(), Namespace: auth.Handler.FeatureStore.Namespace}, - } - role.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("Role")) - return role -} - -func (auth *FeastAuth) setFeastRole(role *rbacv1.Role) error { - role.Labels = auth.getLabels() - role.Rules = []rbacv1.PolicyRule{ - { - APIGroups: []string{rbacv1.GroupName}, - Resources: []string{"roles", "rolebindings"}, - Verbs: []string{"get", "list", "watch"}, - }, - } - - return controllerutil.SetControllerReference(auth.Handler.FeatureStore, role, auth.Handler.Scheme) -} - -func (auth *FeastAuth) createFeastRoleBinding() error { - logger := log.FromContext(auth.Handler.Context) - roleBinding := auth.initFeastRoleBinding() - if op, err := controllerutil.CreateOrUpdate(auth.Handler.Context, auth.Handler.Client, roleBinding, controllerutil.MutateFn(func() error { - return auth.setFeastRoleBinding(roleBinding) - })); err != nil { - return err - } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { - logger.Info("Successfully reconciled", "RoleBinding", roleBinding.Name, "operation", op) - } - - return nil -} - -func (auth *FeastAuth) initFeastRoleBinding() *rbacv1.RoleBinding { - roleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{Name: auth.getFeastRoleName(), Namespace: auth.Handler.FeatureStore.Namespace}, - } - roleBinding.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("RoleBinding")) - return roleBinding -} - -func (auth *FeastAuth) setFeastRoleBinding(roleBinding *rbacv1.RoleBinding) error { - roleBinding.Labels = auth.getLabels() - roleBinding.Subjects = []rbacv1.Subject{} - if auth.Handler.FeatureStore.Status.Applied.Services.OfflineStore != nil { - roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ - Kind: rbacv1.ServiceAccountKind, - Name: services.GetFeastServiceName(auth.Handler.FeatureStore, services.OfflineFeastType), - Namespace: auth.Handler.FeatureStore.Namespace, - }) - } - if auth.Handler.FeatureStore.Status.Applied.Services.OnlineStore != nil { - roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ - Kind: rbacv1.ServiceAccountKind, - Name: services.GetFeastServiceName(auth.Handler.FeatureStore, services.OnlineFeastType), - Namespace: auth.Handler.FeatureStore.Namespace, - }) - } - if services.IsLocalRegistry(auth.Handler.FeatureStore) { - roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ - Kind: rbacv1.ServiceAccountKind, - Name: services.GetFeastServiceName(auth.Handler.FeatureStore, services.RegistryFeastType), - Namespace: auth.Handler.FeatureStore.Namespace, - }) - } - roleBinding.RoleRef = rbacv1.RoleRef{ - APIGroup: rbacv1.GroupName, - Kind: "Role", - Name: auth.getFeastRoleName(), - } - - return controllerutil.SetControllerReference(auth.Handler.FeatureStore, roleBinding, auth.Handler.Scheme) -} - -func (auth *FeastAuth) createAuthRole(roleName string) error { - logger := log.FromContext(auth.Handler.Context) - role := auth.initAuthRole(roleName) - if op, err := controllerutil.CreateOrUpdate(auth.Handler.Context, auth.Handler.Client, role, controllerutil.MutateFn(func() error { - return auth.setAuthRole(role) - })); err != nil { - return err - } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { - logger.Info("Successfully reconciled", "Role", role.Name, "operation", op) - } - - return nil -} - -func (auth *FeastAuth) initAuthRole(roleName string) *rbacv1.Role { - role := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{Name: roleName, Namespace: auth.Handler.FeatureStore.Namespace}, - } - role.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("Role")) - return role -} - -func (auth *FeastAuth) setAuthRole(role *rbacv1.Role) error { - role.Labels = auth.getLabels() - role.Rules = []rbacv1.PolicyRule{} - - return controllerutil.SetControllerReference(auth.Handler.FeatureStore, role, auth.Handler.Scheme) -} - -func (auth *FeastAuth) getLabels() map[string]string { - return map[string]string{ - services.NameLabelKey: auth.Handler.FeatureStore.Name, - } -} - -func (auth *FeastAuth) setFeastKubernetesAuthCondition(err error) error { - if err != nil { - logger := log.FromContext(auth.Handler.Context) - cond := feastKubernetesAuthConditions[metav1.ConditionFalse] - cond.Message = "Error: " + err.Error() - apimeta.SetStatusCondition(&auth.Handler.FeatureStore.Status.Conditions, cond) - logger.Error(err, "Error deploying the Kubernetes authorization") - return err - } else { - apimeta.SetStatusCondition(&auth.Handler.FeatureStore.Status.Conditions, feastKubernetesAuthConditions[metav1.ConditionTrue]) - } - return nil -} - -func (auth *FeastAuth) getFeastRoleName() string { - return GetFeastRoleName(auth.Handler.FeatureStore) -} - -func GetFeastRoleName(featureStore *feastdevv1alpha1.FeatureStore) string { - return services.GetFeastName(featureStore) -} diff --git a/infra/feast-operator/internal/controller/authz/authz.go b/infra/feast-operator/internal/controller/authz/authz.go new file mode 100644 index 0000000000..28d5cc1ca9 --- /dev/null +++ b/infra/feast-operator/internal/controller/authz/authz.go @@ -0,0 +1,220 @@ +package authz + +import ( + "context" + "slices" + + feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/services" + rbacv1 "k8s.io/api/rbac/v1" + apimeta "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +// Deploy the feast authorization +func (authz *FeastAuthorization) Deploy() error { + authzConfig := authz.Handler.FeatureStore.Status.Applied.AuthzConfig + if authzConfig != nil { + if authzConfig.KubernetesAuth != nil { + if err := authz.deployKubernetesAuth(authzConfig.KubernetesAuth); err != nil { + return err + } + } else { + authz.removeOrphanedRoles() + _ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRole()) + _ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRoleBinding()) + } + } + return nil +} + +func (authz *FeastAuthorization) deployKubernetesAuth(kubernetesAuth *feastdevv1alpha1.KubernetesAuth) error { + authz.removeOrphanedRoles() + + if err := authz.createFeastRole(); err != nil { + return authz.setFeastKubernetesAuthCondition(err) + } + if err := authz.createFeastRoleBinding(); err != nil { + return authz.setFeastKubernetesAuthCondition(err) + } + + for _, roleName := range kubernetesAuth.Roles { + if err := authz.createAuthRole(roleName); err != nil { + return authz.setFeastKubernetesAuthCondition(err) + } + } + return authz.setFeastKubernetesAuthCondition(nil) +} + +func (authz *FeastAuthorization) removeOrphanedRoles() { + roleList := &rbacv1.RoleList{} + err := authz.Handler.Client.List(context.TODO(), roleList, &client.ListOptions{ + Namespace: authz.Handler.FeatureStore.Namespace, + LabelSelector: labels.SelectorFromSet(authz.getLabels()), + }) + if err != nil { + return + } + + desiredRoles := []string{} + if authz.Handler.FeatureStore.Status.Applied.AuthzConfig.KubernetesAuth != nil { + desiredRoles = authz.Handler.FeatureStore.Status.Applied.AuthzConfig.KubernetesAuth.Roles + } + for _, role := range roleList.Items { + roleName := role.Name + if roleName != authz.getFeastRoleName() && !slices.Contains(desiredRoles, roleName) { + _ = authz.Handler.DeleteOwnedFeastObj(authz.initAuthRole(roleName)) + } + } +} + +func (authz *FeastAuthorization) createFeastRole() error { + logger := log.FromContext(authz.Handler.Context) + role := authz.initFeastRole() + if op, err := controllerutil.CreateOrUpdate(authz.Handler.Context, authz.Handler.Client, role, controllerutil.MutateFn(func() error { + return authz.setFeastRole(role) + })); err != nil { + return err + } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { + logger.Info("Successfully reconciled", "Role", role.Name, "operation", op) + } + + return nil +} + +func (authz *FeastAuthorization) initFeastRole() *rbacv1.Role { + role := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: authz.getFeastRoleName(), Namespace: authz.Handler.FeatureStore.Namespace}, + } + role.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("Role")) + return role +} + +func (authz *FeastAuthorization) setFeastRole(role *rbacv1.Role) error { + role.Labels = authz.getLabels() + role.Rules = []rbacv1.PolicyRule{ + { + APIGroups: []string{rbacv1.GroupName}, + Resources: []string{"roles", "rolebindings"}, + Verbs: []string{"get", "list", "watch"}, + }, + } + + return controllerutil.SetControllerReference(authz.Handler.FeatureStore, role, authz.Handler.Scheme) +} + +func (authz *FeastAuthorization) createFeastRoleBinding() error { + logger := log.FromContext(authz.Handler.Context) + roleBinding := authz.initFeastRoleBinding() + if op, err := controllerutil.CreateOrUpdate(authz.Handler.Context, authz.Handler.Client, roleBinding, controllerutil.MutateFn(func() error { + return authz.setFeastRoleBinding(roleBinding) + })); err != nil { + return err + } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { + logger.Info("Successfully reconciled", "RoleBinding", roleBinding.Name, "operation", op) + } + + return nil +} + +func (authz *FeastAuthorization) initFeastRoleBinding() *rbacv1.RoleBinding { + roleBinding := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{Name: authz.getFeastRoleName(), Namespace: authz.Handler.FeatureStore.Namespace}, + } + roleBinding.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("RoleBinding")) + return roleBinding +} + +func (authz *FeastAuthorization) setFeastRoleBinding(roleBinding *rbacv1.RoleBinding) error { + roleBinding.Labels = authz.getLabels() + roleBinding.Subjects = []rbacv1.Subject{} + if authz.Handler.FeatureStore.Status.Applied.Services.OfflineStore != nil { + roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ + Kind: rbacv1.ServiceAccountKind, + Name: services.GetFeastServiceName(authz.Handler.FeatureStore, services.OfflineFeastType), + Namespace: authz.Handler.FeatureStore.Namespace, + }) + } + if authz.Handler.FeatureStore.Status.Applied.Services.OnlineStore != nil { + roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ + Kind: rbacv1.ServiceAccountKind, + Name: services.GetFeastServiceName(authz.Handler.FeatureStore, services.OnlineFeastType), + Namespace: authz.Handler.FeatureStore.Namespace, + }) + } + if services.IsLocalRegistry(authz.Handler.FeatureStore) { + roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ + Kind: rbacv1.ServiceAccountKind, + Name: services.GetFeastServiceName(authz.Handler.FeatureStore, services.RegistryFeastType), + Namespace: authz.Handler.FeatureStore.Namespace, + }) + } + roleBinding.RoleRef = rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, + Kind: "Role", + Name: authz.getFeastRoleName(), + } + + return controllerutil.SetControllerReference(authz.Handler.FeatureStore, roleBinding, authz.Handler.Scheme) +} + +func (authz *FeastAuthorization) createAuthRole(roleName string) error { + logger := log.FromContext(authz.Handler.Context) + role := authz.initAuthRole(roleName) + if op, err := controllerutil.CreateOrUpdate(authz.Handler.Context, authz.Handler.Client, role, controllerutil.MutateFn(func() error { + return authz.setAuthRole(role) + })); err != nil { + return err + } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { + logger.Info("Successfully reconciled", "Role", role.Name, "operation", op) + } + + return nil +} + +func (authz *FeastAuthorization) initAuthRole(roleName string) *rbacv1.Role { + role := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: roleName, Namespace: authz.Handler.FeatureStore.Namespace}, + } + role.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("Role")) + return role +} + +func (authz *FeastAuthorization) setAuthRole(role *rbacv1.Role) error { + role.Labels = authz.getLabels() + role.Rules = []rbacv1.PolicyRule{} + + return controllerutil.SetControllerReference(authz.Handler.FeatureStore, role, authz.Handler.Scheme) +} + +func (authz *FeastAuthorization) getLabels() map[string]string { + return map[string]string{ + services.NameLabelKey: authz.Handler.FeatureStore.Name, + } +} + +func (authz *FeastAuthorization) setFeastKubernetesAuthCondition(err error) error { + if err != nil { + logger := log.FromContext(authz.Handler.Context) + cond := feastKubernetesAuthConditions[metav1.ConditionFalse] + cond.Message = "Error: " + err.Error() + apimeta.SetStatusCondition(&authz.Handler.FeatureStore.Status.Conditions, cond) + logger.Error(err, "Error deploying the Kubernetes authorization") + return err + } else { + apimeta.SetStatusCondition(&authz.Handler.FeatureStore.Status.Conditions, feastKubernetesAuthConditions[metav1.ConditionTrue]) + } + return nil +} + +func (authz *FeastAuthorization) getFeastRoleName() string { + return GetFeastRoleName(authz.Handler.FeatureStore) +} + +func GetFeastRoleName(featureStore *feastdevv1alpha1.FeatureStore) string { + return services.GetFeastName(featureStore) +} diff --git a/infra/feast-operator/internal/controller/auth/auth_types.go b/infra/feast-operator/internal/controller/authz/authz_types.go similarity index 73% rename from infra/feast-operator/internal/controller/auth/auth_types.go rename to infra/feast-operator/internal/controller/authz/authz_types.go index d3ee408682..5e8b167345 100644 --- a/infra/feast-operator/internal/controller/auth/auth_types.go +++ b/infra/feast-operator/internal/controller/authz/authz_types.go @@ -1,4 +1,4 @@ -package auth +package authz import ( feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" @@ -6,21 +6,21 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// FeastAuth is an interface for configuring feast authorization -type FeastAuth struct { +// FeastAuthorization is an interface for configuring feast authorization +type FeastAuthorization struct { Handler handler.FeastHandler } var ( feastKubernetesAuthConditions = map[metav1.ConditionStatus]metav1.Condition{ metav1.ConditionTrue: { - Type: feastdevv1alpha1.KubernetesAuthReadyType, + Type: feastdevv1alpha1.AuthorizationReadyType, Status: metav1.ConditionTrue, Reason: feastdevv1alpha1.ReadyReason, Message: feastdevv1alpha1.KubernetesAuthReadyMessage, }, metav1.ConditionFalse: { - Type: feastdevv1alpha1.KubernetesAuthReadyType, + Type: feastdevv1alpha1.AuthorizationReadyType, Status: metav1.ConditionFalse, Reason: feastdevv1alpha1.KubernetesAuthFailedReason, }, diff --git a/infra/feast-operator/internal/controller/featurestore_controller.go b/infra/feast-operator/internal/controller/featurestore_controller.go index 60ccfbc852..1871eb0e5b 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller.go +++ b/infra/feast-operator/internal/controller/featurestore_controller.go @@ -36,7 +36,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" - "github.com/feast-dev/feast/infra/feast-operator/internal/controller/auth" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/authz" feasthandler "github.com/feast-dev/feast/infra/feast-operator/internal/controller/handler" "github.com/feast-dev/feast/infra/feast-operator/internal/controller/services" ) @@ -110,7 +110,7 @@ func (r *FeatureStoreReconciler) deployFeast(ctx context.Context, cr *feastdevv1 Message: feastdevv1alpha1.ReadyMessage, } - auth := auth.FeastAuth{ + authz := authz.FeastAuthorization{ Handler: feasthandler.FeastHandler{ Client: r.Client, Context: ctx, @@ -118,7 +118,7 @@ func (r *FeatureStoreReconciler) deployFeast(ctx context.Context, cr *feastdevv1 Scheme: r.Scheme, }, } - if err = auth.Deploy(); err != nil { + if err = authz.Deploy(); err != nil { condition = metav1.Condition{ Type: feastdevv1alpha1.ReadyType, Status: metav1.ConditionFalse, diff --git a/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go b/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go index 8eadac773b..6bf67b1d8e 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go @@ -127,7 +127,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) - Expect(resource.Status.Applied.AuthConfig).To(Equal(&feastdevv1alpha1.AuthConfig{})) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(&feastdevv1alpha1.AuthzConfig{})) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) @@ -165,7 +165,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -294,7 +294,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { RegistryType: services.RegistryFileConfigType, Path: registryPath, }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfig).To(Equal(testConfig)) @@ -331,8 +331,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { OfflineStore: services.OfflineStoreConfig{ Type: services.OfflineDuckDbConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigOffline).To(Equal(offlineConfig)) @@ -373,8 +373,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Path: onlineStorePath, Type: services.OnlineSqliteConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigOnline).To(Equal(onlineConfig)) Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(3)) @@ -400,8 +400,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Path: fmt.Sprintf("http://feast-%s-online.default.svc.cluster.local:80", resourceName), Type: services.OnlineRemoteConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigClient).To(Equal(clientConfig)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go b/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go index 8d2edf7a08..90c24be4de 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go @@ -39,14 +39,14 @@ import ( "github.com/feast-dev/feast/infra/feast-operator/api/feastversion" feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" - "github.com/feast-dev/feast/infra/feast-operator/internal/controller/auth" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/authz" "github.com/feast-dev/feast/infra/feast-operator/internal/controller/handler" "github.com/feast-dev/feast/infra/feast-operator/internal/controller/services" ) var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Context("When deploying a resource with all ephemeral services and Kubernetes authorization", func() { - const resourceName = "kubernetes-auth" + const resourceName = "kubernetes-authorization" var pullPolicy = corev1.PullAlways ctx := context.Background() @@ -63,7 +63,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { err := k8sClient.Get(ctx, typeNamespacedName, featurestore) if err != nil && errors.IsNotFound(err) { resource := createFeatureStoreResource(resourceName, image, pullPolicy, &[]corev1.EnvVar{}) - resource.Spec.AuthConfig = &feastdevv1alpha1.AuthConfig{KubernetesAuth: &feastdevv1alpha1.KubernetesAuth{ + resource.Spec.AuthzConfig = &feastdevv1alpha1.AuthzConfig{KubernetesAuth: &feastdevv1alpha1.KubernetesAuth{ Roles: roles, }} @@ -107,12 +107,12 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) - expectedAuthConfig := &feastdevv1alpha1.AuthConfig{ + expectedAuthzConfig := &feastdevv1alpha1.AuthzConfig{ KubernetesAuth: &feastdevv1alpha1.KubernetesAuth{ Roles: roles, }, } - Expect(resource.Status.Applied.AuthConfig).To(Equal(expectedAuthConfig)) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(expectedAuthzConfig)) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) @@ -150,11 +150,11 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).ToNot(BeNil()) Expect(cond.Status).To(Equal(metav1.ConditionTrue)) Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) - Expect(cond.Type).To(Equal(feastdevv1alpha1.KubernetesAuthReadyType)) + Expect(cond.Type).To(Equal(feastdevv1alpha1.AuthorizationReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.KubernetesAuthReadyMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -244,7 +244,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { // check Feast Role feastRole := &rbacv1.Role{} err = k8sClient.Get(ctx, types.NamespacedName{ - Name: auth.GetFeastRoleName(resource), + Name: authz.GetFeastRoleName(resource), Namespace: resource.Namespace, }, feastRole) @@ -264,7 +264,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { // check RoleBinding roleBinding := &rbacv1.RoleBinding{} err = k8sClient.Get(ctx, types.NamespacedName{ - Name: auth.GetFeastRoleName(resource), + Name: authz.GetFeastRoleName(resource), Namespace: resource.Namespace, }, roleBinding) @@ -297,7 +297,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { By("Updating the user roled and reconciling") resourceNew := resource.DeepCopy() rolesNew := roles[1:] - resourceNew.Spec.AuthConfig.KubernetesAuth.Roles = rolesNew + resourceNew.Spec.AuthzConfig.KubernetesAuth.Roles = rolesNew err = k8sClient.Update(ctx, resourceNew) Expect(err).NotTo(HaveOccurred()) _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{ @@ -335,7 +335,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { By("Clearing the kubernetes authorizatino and reconciling") resourceNew = resource.DeepCopy() - resourceNew.Spec.AuthConfig = &feastdevv1alpha1.AuthConfig{} + resourceNew.Spec.AuthzConfig = &feastdevv1alpha1.AuthzConfig{} err = k8sClient.Update(ctx, resourceNew) Expect(err).NotTo(HaveOccurred()) _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{ @@ -362,7 +362,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { // check no RoleBinding roleBinding = &rbacv1.RoleBinding{} err = k8sClient.Get(ctx, types.NamespacedName{ - Name: auth.GetFeastRoleName(resource), + Name: authz.GetFeastRoleName(resource), Namespace: resource.Namespace, }, roleBinding) @@ -444,7 +444,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Path: services.DefaultRegistryEphemeralPath, S3AdditionalKwargs: nil, }, - AuthConfig: services.AuthConfig{ + AuthzConfig: services.AuthzConfig{ Type: services.KubernetesAuthType, }, } @@ -483,7 +483,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Type: services.OfflineDaskConfigType, }, Registry: regRemote, - AuthConfig: services.AuthConfig{ + AuthzConfig: services.AuthzConfig{ Type: services.KubernetesAuthType, }, } @@ -525,7 +525,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Type: services.OnlineSqliteConfigType, }, Registry: regRemote, - AuthConfig: services.AuthConfig{ + AuthzConfig: services.AuthzConfig{ Type: services.KubernetesAuthType, }, } @@ -556,7 +556,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { RegistryType: services.RegistryRemoteConfigType, Path: fmt.Sprintf("feast-%s-registry.default.svc.cluster.local:80", resourceName), }, - AuthConfig: services.AuthConfig{ + AuthzConfig: services.AuthzConfig{ Type: services.KubernetesAuthType, }, } diff --git a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go index 3cf38d2059..dce28f9911 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go @@ -122,7 +122,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) - Expect(resource.Status.Applied.AuthConfig).To(Equal(&feastdevv1alpha1.AuthConfig{})) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(&feastdevv1alpha1.AuthzConfig{})) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).To(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore).To(BeNil()) @@ -150,7 +150,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -321,7 +321,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Path: registryPath, S3AdditionalKwargs: &s3AdditionalKwargs, }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfig).To(Equal(testConfig)) @@ -365,7 +365,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { RegistryType: services.RegistryRemoteConfigType, Path: fmt.Sprintf("feast-%s-registry.default.svc.cluster.local:80", resourceName), }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfigClient).To(Equal(clientConfig)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go b/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go index 7f1a5c5634..2d1593d794 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go @@ -153,7 +153,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) - Expect(resource.Status.Applied.AuthConfig).To(Equal(&feastdevv1alpha1.AuthConfig{})) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(&feastdevv1alpha1.AuthzConfig{})) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) @@ -221,7 +221,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -464,7 +464,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { RegistryType: services.RegistryFileConfigType, Path: registryMountedPath, }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfig).To(Equal(testConfig)) @@ -502,8 +502,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { OfflineStore: services.OfflineStoreConfig{ Type: services.OfflineDuckDbConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigOffline).To(Equal(offlineConfig)) @@ -544,8 +544,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Path: onlineStoreMountedPath, Type: services.OnlineSqliteConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigOnline).To(Equal(onlineConfig)) Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(3)) @@ -571,8 +571,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Path: fmt.Sprintf("http://feast-%s-online.default.svc.cluster.local:80", resourceName), Type: services.OnlineRemoteConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigClient).To(Equal(clientConfig)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_test.go b/infra/feast-operator/internal/controller/featurestore_controller_test.go index 606bf73241..f591969f1d 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_test.go @@ -133,7 +133,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(resource.Status.ServiceHostnames.OnlineStore).To(BeEmpty()) Expect(resource.Status.ServiceHostnames.Registry).To(Equal(feast.GetFeastServiceName(services.RegistryFeastType) + "." + resource.Namespace + ".svc.cluster.local:80")) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) - Expect(resource.Status.Applied.AuthConfig).To(Equal(&feastdevv1alpha1.AuthConfig{})) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(&feastdevv1alpha1.AuthzConfig{})) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).To(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore).To(BeNil()) @@ -246,7 +246,7 @@ var _ = Describe("FeatureStore Controller", func() { RegistryType: services.RegistryFileConfigType, Path: services.DefaultRegistryEphemeralPath, }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfig).To(Equal(testConfig)) @@ -270,7 +270,7 @@ var _ = Describe("FeatureStore Controller", func() { RegistryType: services.RegistryRemoteConfigType, Path: "feast-test-resource-registry.default.svc.cluster.local:80", }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfigClient).To(Equal(clientConfig)) @@ -377,7 +377,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(cond.Reason).To(Equal(feastdevv1alpha1.FailedReason)) Expect(cond.Message).To(Equal("Error: Object " + resource.Namespace + "/" + name + " is already owned by another Service controller " + name)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -458,7 +458,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) - Expect(resource.Status.Applied.AuthConfig).To(Equal(&feastdevv1alpha1.AuthConfig{})) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(&feastdevv1alpha1.AuthzConfig{})) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) @@ -496,7 +496,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -632,7 +632,7 @@ var _ = Describe("FeatureStore Controller", func() { RegistryType: services.RegistryFileConfigType, Path: services.DefaultRegistryEphemeralPath, }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfig).To(Equal(testConfig)) @@ -670,8 +670,8 @@ var _ = Describe("FeatureStore Controller", func() { OfflineStore: services.OfflineStoreConfig{ Type: services.OfflineDaskConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigOffline).To(Equal(offlineConfig)) @@ -713,8 +713,8 @@ var _ = Describe("FeatureStore Controller", func() { Path: services.DefaultOnlineStoreEphemeralPath, Type: services.OnlineSqliteConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigOnline).To(Equal(onlineConfig)) Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(3)) @@ -740,8 +740,8 @@ var _ = Describe("FeatureStore Controller", func() { Path: "http://feast-services-online.default.svc.cluster.local:80", Type: services.OnlineRemoteConfigType, }, - Registry: regRemote, - AuthConfig: noAuthConfig(), + Registry: regRemote, + AuthzConfig: noAuthzConfig(), } Expect(repoConfigClient).To(Equal(clientConfig)) @@ -984,7 +984,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(err).To(HaveOccurred()) err = k8sClient.Get(ctx, nsName, resource) Expect(err).NotTo(HaveOccurred()) - Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType)).To(BeNil()) + Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType)).To(BeNil()) Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType)).To(BeNil()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.ReadyType)).To(BeFalse()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) @@ -1000,7 +1000,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(err).To(HaveOccurred()) err = k8sClient.Get(ctx, nsName, resource) Expect(err).NotTo(HaveOccurred()) - Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType)).To(BeNil()) + Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType)).To(BeNil()) Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType)).To(BeNil()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.ReadyType)).To(BeFalse()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) @@ -1018,7 +1018,7 @@ var _ = Describe("FeatureStore Controller", func() { err = k8sClient.Get(ctx, nsName, resource) Expect(err).NotTo(HaveOccurred()) - Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType)).To(BeNil()) + Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType)).To(BeNil()) Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType)).To(BeNil()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.ReadyType)).To(BeTrue()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType)).To(BeTrue()) @@ -1062,7 +1062,7 @@ var _ = Describe("FeatureStore Controller", func() { RegistryType: services.RegistryRemoteConfigType, Path: "feast-" + referencedRegistry.Name + "-registry.default.svc.cluster.local:80", }, - AuthConfig: noAuthConfig(), + AuthzConfig: noAuthzConfig(), } Expect(repoConfigClient).To(Equal(clientConfig)) @@ -1087,7 +1087,7 @@ var _ = Describe("FeatureStore Controller", func() { err = k8sClient.Get(ctx, nsName, resource) Expect(err).NotTo(HaveOccurred()) Expect(resource.Status.ServiceHostnames.Registry).To(BeEmpty()) - Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType)).To(BeNil()) + Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType)).To(BeNil()) Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType)).To(BeNil()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.ReadyType)).To(BeFalse()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType)).To(BeTrue()) @@ -1165,7 +1165,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(cond.Reason).To(Equal(feastdevv1alpha1.FailedReason)) Expect(cond.Message).To(Equal("Error: Object " + resource.Namespace + "/" + name + " is already owned by another Service controller " + name)) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.KubernetesAuthReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) @@ -1286,8 +1286,8 @@ func getFeatureStoreYamlEnvVar(envs []corev1.EnvVar) *corev1.EnvVar { return nil } -func noAuthConfig() services.AuthConfig { - return services.AuthConfig{ +func noAuthzConfig() services.AuthzConfig { + return services.AuthzConfig{ Type: services.NoAuthAuthType, } } diff --git a/infra/feast-operator/internal/controller/services/repo_config.go b/infra/feast-operator/internal/controller/services/repo_config.go index b9ed80039f..256a6265dd 100644 --- a/infra/feast-operator/internal/controller/services/repo_config.go +++ b/infra/feast-operator/internal/controller/services/repo_config.go @@ -140,13 +140,13 @@ func getClientRepoConfig(featureStore *feastdevv1alpha1.FeatureStore) RepoConfig } } - if status.Applied.AuthConfig.KubernetesAuth == nil { - clientRepoConfig.AuthConfig = AuthConfig{ + if status.Applied.AuthzConfig.KubernetesAuth == nil { + clientRepoConfig.AuthzConfig = AuthzConfig{ Type: NoAuthAuthType, } } else { - if status.Applied.AuthConfig.KubernetesAuth != nil { - clientRepoConfig.AuthConfig = AuthConfig{ + if status.Applied.AuthzConfig.KubernetesAuth != nil { + clientRepoConfig.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 f08b2dc0a1..8296563060 100644 --- a/infra/feast-operator/internal/controller/services/repo_config_test.go +++ b/infra/feast-operator/internal/controller/services/repo_config_test.go @@ -35,21 +35,21 @@ var _ = Describe("Repo Config", func() { var repoConfig RepoConfig repoConfig, err := getServiceRepoConfig(OfflineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) repoConfig, err = getServiceRepoConfig(OnlineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) repoConfig, err = getServiceRepoConfig(RegistryFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) expectedRegistryConfig := RegistryConfig{ @@ -74,21 +74,21 @@ var _ = Describe("Repo Config", func() { ApplyDefaultsToStatus(featureStore) repoConfig, err = getServiceRepoConfig(OfflineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) repoConfig, err = getServiceRepoConfig(OnlineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) repoConfig, err = getServiceRepoConfig(RegistryFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) expectedRegistryConfig = RegistryConfig{ @@ -112,21 +112,21 @@ var _ = Describe("Repo Config", func() { ApplyDefaultsToStatus(featureStore) repoConfig, err = getServiceRepoConfig(OfflineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) repoConfig, err = getServiceRepoConfig(OnlineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) repoConfig, err = getServiceRepoConfig(RegistryFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) Expect(repoConfig.Registry).To(Equal(emptyRegistryConfig())) @@ -161,7 +161,7 @@ var _ = Describe("Repo Config", func() { ApplyDefaultsToStatus(featureStore) repoConfig, err = getServiceRepoConfig(OfflineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) expectedOfflineConfig := OfflineStoreConfig{ Type: "duckdb", } @@ -171,7 +171,7 @@ var _ = Describe("Repo Config", func() { repoConfig, err = getServiceRepoConfig(OnlineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) expectedOnlineConfig := OnlineStoreConfig{ Type: "sqlite", @@ -182,7 +182,7 @@ var _ = Describe("Repo Config", func() { repoConfig, err = getServiceRepoConfig(RegistryFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(NoAuthAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) expectedRegistryConfig = RegistryConfig{ @@ -191,9 +191,9 @@ var _ = Describe("Repo Config", func() { } Expect(repoConfig.Registry).To(Equal(expectedRegistryConfig)) - By("Having kubernetes auth") + By("Having kubernetes authorization") featureStore = minimalFeatureStore() - featureStore.Spec.AuthConfig = &feastdevv1alpha1.AuthConfig{ + featureStore.Spec.AuthzConfig = &feastdevv1alpha1.AuthzConfig{ KubernetesAuth: &feastdevv1alpha1.KubernetesAuth{}, } featureStore.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ @@ -218,7 +218,7 @@ var _ = Describe("Repo Config", func() { ApplyDefaultsToStatus(featureStore) repoConfig, err = getServiceRepoConfig(OfflineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(KubernetesAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(KubernetesAuthType)) expectedOfflineConfig = OfflineStoreConfig{ Type: "dask", } @@ -228,7 +228,7 @@ var _ = Describe("Repo Config", func() { repoConfig, err = getServiceRepoConfig(OnlineFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(KubernetesAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(KubernetesAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) expectedOnlineConfig = OnlineStoreConfig{ Type: "sqlite", @@ -239,7 +239,7 @@ var _ = Describe("Repo Config", func() { repoConfig, err = getServiceRepoConfig(RegistryFeastType, featureStore) Expect(err).NotTo(HaveOccurred()) - Expect(repoConfig.AuthConfig.Type).To(Equal(KubernetesAuthType)) + Expect(repoConfig.AuthzConfig.Type).To(Equal(KubernetesAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig())) Expect(repoConfig.OnlineStore).To(Equal(emptyOnlineStoreConfig())) expectedRegistryConfig = RegistryConfig{ diff --git a/infra/feast-operator/internal/controller/services/services_types.go b/infra/feast-operator/internal/controller/services/services_types.go index 37b1732d96..6433f32a0b 100644 --- a/infra/feast-operator/internal/controller/services/services_types.go +++ b/infra/feast-operator/internal/controller/services/services_types.go @@ -166,7 +166,7 @@ type RepoConfig struct { OfflineStore OfflineStoreConfig `yaml:"offline_store,omitempty"` OnlineStore OnlineStoreConfig `yaml:"online_store,omitempty"` Registry RegistryConfig `yaml:"registry,omitempty"` - AuthConfig AuthConfig `yaml:"auth,omitempty"` + AuthzConfig AuthzConfig `yaml:"auth,omitempty"` EntityKeySerializationVersion int `yaml:"entity_key_serialization_version,omitempty"` } @@ -190,8 +190,8 @@ type RegistryConfig struct { S3AdditionalKwargs *map[string]string `json:"s3_additional_kwargs,omitempty"` } -// AuthConfig is the RBAC authorization configuration. -type AuthConfig struct { +// AuthzConfig is the RBAC authorization configuration. +type AuthzConfig struct { Type AuthType `yaml:"type,omitempty"` } diff --git a/infra/feast-operator/internal/controller/services/util.go b/infra/feast-operator/internal/controller/services/util.go index 34067250e9..b145858aea 100644 --- a/infra/feast-operator/internal/controller/services/util.go +++ b/infra/feast-operator/internal/controller/services/util.go @@ -46,8 +46,8 @@ func ApplyDefaultsToStatus(cr *feastdevv1alpha1.FeatureStore) { cr.Status.FeastVersion = feastversion.FeastVersion applied := cr.Spec.DeepCopy() - if applied.AuthConfig == nil { - applied.AuthConfig = &feastdevv1alpha1.AuthConfig{} + if applied.AuthzConfig == nil { + applied.AuthzConfig = &feastdevv1alpha1.AuthzConfig{} } if applied.Services == nil { diff --git a/infra/feast-operator/test/api/featurestore_types_test.go b/infra/feast-operator/test/api/featurestore_types_test.go index a1719b950e..27ea3d7943 100644 --- a/infra/feast-operator/test/api/featurestore_types_test.go +++ b/infra/feast-operator/test/api/featurestore_types_test.go @@ -377,11 +377,11 @@ var _ = Describe("FeatureStore API", func() { storage = resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.PvcConfig.Create.Resources.Requests.Storage().String() Expect(storage).To(Equal("500Mi")) }) - It("should set the default AuthConfig", func() { + It("should set the default AuthzConfig", func() { resource := featurestore services.ApplyDefaultsToStatus(resource) - Expect(resource.Status.Applied.AuthConfig).ToNot(BeNil()) - Expect(resource.Status.Applied.AuthConfig).To(Equal(&feastdevv1alpha1.AuthConfig{})) + Expect(resource.Status.Applied.AuthzConfig).ToNot(BeNil()) + Expect(resource.Status.Applied.AuthzConfig).To(Equal(&feastdevv1alpha1.AuthzConfig{})) }) }) })