From 0f6f3cd4af3922573b24836c9e25a8068241c96b Mon Sep 17 00:00:00 2001 From: Aniket Paluskar Date: Wed, 8 Apr 2026 20:30:02 +0530 Subject: [PATCH 1/2] feat: Provision minimal TokenReview RBAC for OIDC auth and add SSL error logging in token parser Signed-off-by: Aniket Paluskar --- .../feast-operator.clusterserviceversion.yaml | 2 +- .../internal/controller/authz/authz.go | 78 ++++++++++++++++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml b/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml index 318c01d0ce..59cb8c6709 100644 --- a/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml +++ b/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml @@ -50,7 +50,7 @@ metadata: } ] capabilities: Basic Install - createdAt: "2026-04-08T14:26:31Z" + createdAt: "2026-04-08T12:09:54Z" operators.operatorframework.io/builder: operator-sdk-v1.38.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 name: feast-operator.v0.62.0 diff --git a/infra/feast-operator/internal/controller/authz/authz.go b/infra/feast-operator/internal/controller/authz/authz.go index e9811c1c78..4864fe6796 100644 --- a/infra/feast-operator/internal/controller/authz/authz.go +++ b/infra/feast-operator/internal/controller/authz/authz.go @@ -18,6 +18,7 @@ import ( // Deploy the feast authorization func (authz *FeastAuthorization) Deploy() error { if authz.isKubernetesAuth() { + authz.cleanupOidcRbac() return authz.deployKubernetesAuth() } @@ -27,12 +28,14 @@ func (authz *FeastAuthorization) Deploy() error { apimeta.RemoveStatusCondition(&authz.Handler.FeatureStore.Status.Conditions, feastKubernetesAuthConditions[metav1.ConditionTrue].Type) if authz.isOidcAuth() { - if err := authz.createFeastClusterRole(); err != nil { + if err := authz.createOidcClusterRole(); err != nil { return err } - if err := authz.createFeastClusterRoleBinding(); err != nil { + if err := authz.createOidcClusterRoleBinding(); err != nil { return err } + } else { + authz.cleanupOidcRbac() } return nil @@ -327,6 +330,77 @@ func (authz *FeastAuthorization) setAuthRole(role *rbacv1.Role) error { return controllerutil.SetControllerReference(authz.Handler.FeatureStore, role, authz.Handler.Scheme) } +func (authz *FeastAuthorization) createOidcClusterRole() error { + logger := log.FromContext(authz.Handler.Context) + clusterRole := &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{Name: authz.getOidcClusterRoleName()}, + } + clusterRole.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRole")) + if op, err := controllerutil.CreateOrUpdate(authz.Handler.Context, authz.Handler.Client, clusterRole, controllerutil.MutateFn(func() error { + clusterRole.Labels = authz.getLabels() + clusterRole.Rules = []rbacv1.PolicyRule{ + { + APIGroups: []string{"authentication.k8s.io"}, + Resources: []string{"tokenreviews"}, + Verbs: []string{"create"}, + }, + } + return nil + })); err != nil { + return err + } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { + logger.Info("Successfully reconciled", "ClusterRole", clusterRole.Name, "operation", op) + } + return nil +} + +func (authz *FeastAuthorization) createOidcClusterRoleBinding() error { + logger := log.FromContext(authz.Handler.Context) + crb := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{Name: authz.getOidcClusterRoleBindingName()}, + } + crb.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRoleBinding")) + if op, err := controllerutil.CreateOrUpdate(authz.Handler.Context, authz.Handler.Client, crb, controllerutil.MutateFn(func() error { + crb.Labels = authz.getLabels() + crb.Subjects = []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: authz.getFeastServiceAccountName(), + Namespace: authz.Handler.FeatureStore.Namespace, + }, + } + crb.RoleRef = rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, + Kind: "ClusterRole", + Name: authz.getOidcClusterRoleName(), + } + return nil + })); err != nil { + return err + } else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { + logger.Info("Successfully reconciled", "ClusterRoleBinding", crb.Name, "operation", op) + } + return nil +} + +func (authz *FeastAuthorization) cleanupOidcRbac() { + cr := &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: authz.getOidcClusterRoleName()}} + cr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRole")) + _ = authz.Handler.Client.Delete(authz.Handler.Context, cr) + + crb := &rbacv1.ClusterRoleBinding{ObjectMeta: metav1.ObjectMeta{Name: authz.getOidcClusterRoleBindingName()}} + crb.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRoleBinding")) + _ = authz.Handler.Client.Delete(authz.Handler.Context, crb) +} + +func (authz *FeastAuthorization) getOidcClusterRoleName() string { + return "feast-oidc-token-review" +} + +func (authz *FeastAuthorization) getOidcClusterRoleBindingName() string { + return services.GetFeastName(authz.Handler.FeatureStore) + "-oidc-token-review" +} + func (authz *FeastAuthorization) getLabels() map[string]string { return map[string]string{ services.NameLabelKey: authz.Handler.FeatureStore.Name, From 8c8b79ddf63116e5c3aa71ba6d229f561021ae5e Mon Sep 17 00:00:00 2001 From: Aniket Paluskar Date: Wed, 8 Apr 2026 20:55:52 +0530 Subject: [PATCH 2/2] Avoid deleting shared OIDC ClusterRole during auth type transitions Signed-off-by: Aniket Paluskar --- infra/feast-operator/internal/controller/authz/authz.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/infra/feast-operator/internal/controller/authz/authz.go b/infra/feast-operator/internal/controller/authz/authz.go index 4864fe6796..888c7c0c69 100644 --- a/infra/feast-operator/internal/controller/authz/authz.go +++ b/infra/feast-operator/internal/controller/authz/authz.go @@ -384,10 +384,6 @@ func (authz *FeastAuthorization) createOidcClusterRoleBinding() error { } func (authz *FeastAuthorization) cleanupOidcRbac() { - cr := &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: authz.getOidcClusterRoleName()}} - cr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRole")) - _ = authz.Handler.Client.Delete(authz.Handler.Context, cr) - crb := &rbacv1.ClusterRoleBinding{ObjectMeta: metav1.ObjectMeta{Name: authz.getOidcClusterRoleBindingName()}} crb.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRoleBinding")) _ = authz.Handler.Client.Delete(authz.Handler.Context, crb)