From 153cb4549408dd21a82856a33e32a91837059087 Mon Sep 17 00:00:00 2001 From: Andrew Gouin Date: Wed, 18 Oct 2023 01:22:52 -0600 Subject: [PATCH] switch to role --- config/rbac/role.yaml | 6 ++- controllers/cosmosfullnode_controller.go | 10 ++--- internal/fullnode/rbac_builder.go | 40 ++++++++++--------- ...ole_control.go => role_binding_control.go} | 31 +++++++------- ...ole_binding_control.go => role_control.go} | 31 +++++++------- internal/fullnode/service_account_control.go | 2 +- local.Dockerfile | 1 + 7 files changed, 63 insertions(+), 58 deletions(-) rename internal/fullnode/{cluster_role_control.go => role_binding_control.go} (61%) rename internal/fullnode/{cluster_role_binding_control.go => role_control.go} (52%) diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index f77f269f..d114ff54 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -148,11 +148,13 @@ rules: - apiGroups: - rbac.authorization.k8s.io resources: - - clusterrolebindings - - clusterroles + - rolebindings + - roles verbs: + - bind - create - delete + - escalate - get - list - patch diff --git a/controllers/cosmosfullnode_controller.go b/controllers/cosmosfullnode_controller.go index ce4678a2..4c85e526 100644 --- a/controllers/cosmosfullnode_controller.go +++ b/controllers/cosmosfullnode_controller.go @@ -53,8 +53,8 @@ type CosmosFullNodeReconciler struct { serviceControl fullnode.ServiceControl statusClient *fullnode.StatusClient serviceAccountControl fullnode.ServiceAccountControl - clusterRoleControl fullnode.ClusterRoleControl - clusterRoleBindingControl fullnode.ClusterRoleBindingControl + clusterRoleControl fullnode.RoleControl + clusterRoleBindingControl fullnode.RoleBindingControl } // NewFullNode returns a valid CosmosFullNode controller. @@ -77,8 +77,8 @@ func NewFullNode( serviceControl: fullnode.NewServiceControl(client), statusClient: statusClient, serviceAccountControl: fullnode.NewServiceAccountControl(client), - clusterRoleControl: fullnode.NewClusterRoleControl(client), - clusterRoleBindingControl: fullnode.NewClusterRoleBindingControl(client), + clusterRoleControl: fullnode.NewRoleControl(client), + clusterRoleBindingControl: fullnode.NewRoleBindingControl(client), } } @@ -92,7 +92,7 @@ var ( //+kubebuilder:rbac:groups=cosmos.strange.love,resources=cosmosfullnodes/finalizers,verbs=update // Generate RBAC roles to watch and update resources. IMPORTANT!!!! All resource names must be lowercase or cluster role will not work. //+kubebuilder:rbac:groups="",resources=pods;persistentvolumeclaims;services;serviceaccounts;configmaps,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=clusterroles;clusterrolebindings,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles;rolebindings,verbs=get;list;watch;create;update;patch;delete;bind;escalate //+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch //+kubebuilder:rbac:groups="",resources=events,verbs=create;update;patch diff --git a/internal/fullnode/rbac_builder.go b/internal/fullnode/rbac_builder.go index 61fc5466..3a872339 100644 --- a/internal/fullnode/rbac_builder.go +++ b/internal/fullnode/rbac_builder.go @@ -13,8 +13,12 @@ func serviceAccountName(crd *cosmosv1.CosmosFullNode) string { return crd.Name + "-vc" } -func clusterRoleName(crd *cosmosv1.CosmosFullNode) string { - return crd.Name + "-cr" +func roleName(crd *cosmosv1.CosmosFullNode) string { + return crd.Namespace + "-" + crd.Name + "-cr" +} + +func roleBindingName(crd *cosmosv1.CosmosFullNode) string { + return crd.Namespace + "-" + crd.Name + "-crb" } // BuildServiceAccounts returns a list of service accounts given the crd. @@ -40,18 +44,18 @@ func BuildServiceAccounts(crd *cosmosv1.CosmosFullNode) []diff.Resource[*corev1. return diffSa } -// BuildClusterRoles returns a list of cluster roles given the crd. +// BuildRoles returns a list of role bindings given the crd. // -// Creates a single cluster role for the version check. -func BuildClusterRoles(crd *cosmosv1.CosmosFullNode) []diff.Resource[*rbacv1.ClusterRole] { - diffCr := make([]diff.Resource[*rbacv1.ClusterRole], 1) - cr := rbacv1.ClusterRole{ +// Creates a single role binding for the version check. +func BuildRoles(crd *cosmosv1.CosmosFullNode) []diff.Resource[*rbacv1.Role] { + diffCr := make([]diff.Resource[*rbacv1.Role], 1) + cr := rbacv1.Role{ TypeMeta: v1.TypeMeta{ - Kind: "ClusterRole", + Kind: "Role", APIVersion: "rbac.authorization.k8s.io/v1", }, ObjectMeta: v1.ObjectMeta{ - Name: clusterRoleName(crd), + Name: roleName(crd), Namespace: crd.Namespace, }, Rules: []rbacv1.PolicyRule{ @@ -75,18 +79,18 @@ func BuildClusterRoles(crd *cosmosv1.CosmosFullNode) []diff.Resource[*rbacv1.Clu return diffCr } -// BuildClusterRoles returns a list of cluster role bindings given the crd. +// BuildRoles returns a list of role binding bindings given the crd. // -// Creates a single cluster role binding for the version check. -func BuildClusterRoleBindings(crd *cosmosv1.CosmosFullNode) []diff.Resource[*rbacv1.ClusterRoleBinding] { - diffCrb := make([]diff.Resource[*rbacv1.ClusterRoleBinding], 1) - crb := rbacv1.ClusterRoleBinding{ +// Creates a single role binding binding for the version check. +func BuildRoleBindings(crd *cosmosv1.CosmosFullNode) []diff.Resource[*rbacv1.RoleBinding] { + diffCrb := make([]diff.Resource[*rbacv1.RoleBinding], 1) + crb := rbacv1.RoleBinding{ TypeMeta: v1.TypeMeta{ - Kind: "ClusterRoleBinding", + Kind: "RoleBinding", APIVersion: "rbac.authorization.k8s.io/v1", }, ObjectMeta: v1.ObjectMeta{ - Name: crd.Name + "-crb", + Name: roleBindingName(crd), Namespace: crd.Namespace, }, Subjects: []rbacv1.Subject{ @@ -97,8 +101,8 @@ func BuildClusterRoleBindings(crd *cosmosv1.CosmosFullNode) []diff.Resource[*rba }, }, RoleRef: rbacv1.RoleRef{ - Kind: "ClusterRole", - Name: clusterRoleName(crd), + Kind: "Role", + Name: roleName(crd), APIGroup: "rbac.authorization.k8s.io", }, } diff --git a/internal/fullnode/cluster_role_control.go b/internal/fullnode/role_binding_control.go similarity index 61% rename from internal/fullnode/cluster_role_control.go rename to internal/fullnode/role_binding_control.go index 4fde3618..a9a4afff 100644 --- a/internal/fullnode/cluster_role_control.go +++ b/internal/fullnode/role_binding_control.go @@ -12,51 +12,50 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -// ClusterRoleControl creates or updates ClusterRoles. -type ClusterRoleControl struct { +// RoleBindingControl creates or updates RoleBindings. +type RoleBindingControl struct { client Client } -func NewClusterRoleControl(client Client) ClusterRoleControl { - return ClusterRoleControl{ +func NewRoleBindingControl(client Client) RoleBindingControl { + return RoleBindingControl{ client: client, } } -// Reconcile creates or updates cluster roles. -func (sc ClusterRoleControl) Reconcile(ctx context.Context, log kube.Logger, crd *cosmosv1.CosmosFullNode) kube.ReconcileError { - var crs rbacv1.ClusterRoleList +// Reconcile creates or updates role bindings. +func (sc RoleBindingControl) Reconcile(ctx context.Context, log kube.Logger, crd *cosmosv1.CosmosFullNode) kube.ReconcileError { + var crs rbacv1.RoleBindingList if err := sc.client.List(ctx, &crs, - client.InNamespace(crd.Namespace), client.MatchingLabels{ kube.ControllerLabel: "cosmos-operator", - kube.ComponentLabel: cosmosv1.CosmosFullNodeController, + kube.ComponentLabel: "vc", kube.NameLabel: appName(crd), }, ); err != nil { - return kube.TransientError(fmt.Errorf("list existing cluster roles: %w", err)) + return kube.TransientError(fmt.Errorf("list existing role bindings: %w", err)) } current := ptrSlice(crs.Items) - want := BuildClusterRoles(crd) + want := BuildRoleBindings(crd) diffed := diff.New(current, want) for _, cr := range diffed.Creates() { - log.Info("Creating cluster role", "clusterRoleName", cr.Name) + log.Info("Creating role binding", "roleBindingName", cr.Name) if err := ctrl.SetControllerReference(crd, cr, sc.client.Scheme()); err != nil { - return kube.TransientError(fmt.Errorf("set controller reference on cluster role %q: %w", cr.Name, err)) + return kube.TransientError(fmt.Errorf("set controller reference on role binding %q: %w", cr.Name, err)) } // CreateOrUpdate (vs. only create) fixes a bug with current deployments where updating would remove the owner reference. // This ensures we update the service with the owner reference. if err := kube.CreateOrUpdate(ctx, sc.client, cr); err != nil { - return kube.TransientError(fmt.Errorf("create cluster role %q: %w", cr.Name, err)) + return kube.TransientError(fmt.Errorf("create role binding %q: %w", cr.Name, err)) } } for _, cr := range diffed.Updates() { - log.Info("Updating cluster role", "clusterRoleName", cr.Name) + log.Info("Updating role binding", "roleBindingName", cr.Name) if err := sc.client.Update(ctx, cr); err != nil { - return kube.TransientError(fmt.Errorf("update cluster role %q: %w", cr.Name, err)) + return kube.TransientError(fmt.Errorf("update role binding %q: %w", cr.Name, err)) } } diff --git a/internal/fullnode/cluster_role_binding_control.go b/internal/fullnode/role_control.go similarity index 52% rename from internal/fullnode/cluster_role_binding_control.go rename to internal/fullnode/role_control.go index bab8f87a..234e54cc 100644 --- a/internal/fullnode/cluster_role_binding_control.go +++ b/internal/fullnode/role_control.go @@ -12,51 +12,50 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -// ClusterRoleBindingControl creates or updates ClusterRoleBindings. -type ClusterRoleBindingControl struct { +// RoleControl creates or updates Roles. +type RoleControl struct { client Client } -func NewClusterRoleBindingControl(client Client) ClusterRoleBindingControl { - return ClusterRoleBindingControl{ +func NewRoleControl(client Client) RoleControl { + return RoleControl{ client: client, } } -// Reconcile creates or updates cluster role bindings. -func (sc ClusterRoleBindingControl) Reconcile(ctx context.Context, log kube.Logger, crd *cosmosv1.CosmosFullNode) kube.ReconcileError { - var crs rbacv1.ClusterRoleBindingList +// Reconcile creates or updates roles. +func (sc RoleControl) Reconcile(ctx context.Context, log kube.Logger, crd *cosmosv1.CosmosFullNode) kube.ReconcileError { + var crs rbacv1.RoleList if err := sc.client.List(ctx, &crs, - client.InNamespace(crd.Namespace), client.MatchingLabels{ kube.ControllerLabel: "cosmos-operator", - kube.ComponentLabel: cosmosv1.CosmosFullNodeController, + kube.ComponentLabel: "vc", kube.NameLabel: appName(crd), }, ); err != nil { - return kube.TransientError(fmt.Errorf("list existing cluster role bindings: %w", err)) + return kube.TransientError(fmt.Errorf("list existing roles: %w", err)) } current := ptrSlice(crs.Items) - want := BuildClusterRoleBindings(crd) + want := BuildRoles(crd) diffed := diff.New(current, want) for _, cr := range diffed.Creates() { - log.Info("Creating cluster role binding", "clusterRoleBindingName", cr.Name) + log.Info("Creating role", "roleName", cr.Name) if err := ctrl.SetControllerReference(crd, cr, sc.client.Scheme()); err != nil { - return kube.TransientError(fmt.Errorf("set controller reference on cluster role binding %q: %w", cr.Name, err)) + return kube.TransientError(fmt.Errorf("set controller reference on role %q: %w", cr.Name, err)) } // CreateOrUpdate (vs. only create) fixes a bug with current deployments where updating would remove the owner reference. // This ensures we update the service with the owner reference. if err := kube.CreateOrUpdate(ctx, sc.client, cr); err != nil { - return kube.TransientError(fmt.Errorf("create cluster role binding %q: %w", cr.Name, err)) + return kube.TransientError(fmt.Errorf("create role %q: %w", cr.Name, err)) } } for _, cr := range diffed.Updates() { - log.Info("Updating cluster role binding", "clusterRoleBindingName", cr.Name) + log.Info("Updating role", "roleName", cr.Name) if err := sc.client.Update(ctx, cr); err != nil { - return kube.TransientError(fmt.Errorf("update cluster role binding %q: %w", cr.Name, err)) + return kube.TransientError(fmt.Errorf("update role %q: %w", cr.Name, err)) } } diff --git a/internal/fullnode/service_account_control.go b/internal/fullnode/service_account_control.go index bf5af6d5..b22b1f9d 100644 --- a/internal/fullnode/service_account_control.go +++ b/internal/fullnode/service_account_control.go @@ -30,7 +30,7 @@ func (sc ServiceAccountControl) Reconcile(ctx context.Context, log kube.Logger, client.InNamespace(crd.Namespace), client.MatchingLabels{ kube.ControllerLabel: "cosmos-operator", - kube.ComponentLabel: cosmosv1.CosmosFullNodeController, + kube.ComponentLabel: "vc", kube.NameLabel: appName(crd), }, ); err != nil { diff --git a/local.Dockerfile b/local.Dockerfile index 0ef37e31..45602348 100644 --- a/local.Dockerfile +++ b/local.Dockerfile @@ -13,6 +13,7 @@ RUN go mod download # Copy the go source COPY *.go . COPY api/ api/ +COPY cmd/ cmd/ COPY controllers/ controllers/ COPY internal/ internal/