From 78624d6f61b188611c830ea64f7849fcd16677b5 Mon Sep 17 00:00:00 2001 From: Sebastian Widmer Date: Wed, 23 Mar 2022 17:26:24 +0100 Subject: [PATCH 1/2] Fix creating rolebindings with admin permissions --- config/rbac/role.yaml | 6 +----- controllers/periodic_syncer.go | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 44f29cf..17f54ed 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -115,8 +115,4 @@ rules: - rolebindings - subjects verbs: - - create - - get - - list - - patch - - update + - '*' diff --git a/controllers/periodic_syncer.go b/controllers/periodic_syncer.go index 1a21caf..82aec99 100644 --- a/controllers/periodic_syncer.go +++ b/controllers/periodic_syncer.go @@ -36,7 +36,7 @@ type PeriodicSyncer struct { //+kubebuilder:rbac:groups=appuio.io,resources=teams,verbs=create //+kubebuilder:rbac:groups=appuio.io,resources=users,verbs=create //+kubebuilder:rbac:groups=organization.appuio.io;rbac.appuio.io,resources=organizations,verbs=create -//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=subjects;rolebindings,verbs=get;list;create;update;patch +//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=subjects;rolebindings,verbs=* // Sync lists all Keycloak groups in the realm and creates corresponding Organizations if they do not exist func (r *PeriodicSyncer) Sync(ctx context.Context) error { From 5c6c1fdbc5af52615d11ea25bca88647c9d9d042 Mon Sep 17 00:00:00 2001 From: Sebastian Widmer Date: Wed, 23 Mar 2022 17:50:20 +0100 Subject: [PATCH 2/2] Prefix users in imported rolebindigs --- controllers/periodic_syncer.go | 5 +++-- controllers/periodic_syncer_test.go | 17 +++++++++-------- main.go | 13 ++++++++----- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/controllers/periodic_syncer.go b/controllers/periodic_syncer.go index 82aec99..13e1b04 100644 --- a/controllers/periodic_syncer.go +++ b/controllers/periodic_syncer.go @@ -29,7 +29,8 @@ type PeriodicSyncer struct { Keycloak KeycloakClient // SyncClusterRoles to give to group members when importing - SyncClusterRoles []string + SyncClusterRoles []string + SyncClusterRolesUserPrefix string } //+kubebuilder:rbac:groups=appuio.io,resources=organizationmembers,verbs=create @@ -267,7 +268,7 @@ func (r *PeriodicSyncer) setRolebindingsFromGroup(ctx context.Context, group key subjects = append(subjects, rbacv1.Subject{ Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, - Name: m.Username, + Name: r.SyncClusterRolesUserPrefix + m.Username, }) } diff --git a/controllers/periodic_syncer_test.go b/controllers/periodic_syncer_test.go index 6902d08..ee6569d 100644 --- a/controllers/periodic_syncer_test.go +++ b/controllers/periodic_syncer_test.go @@ -61,10 +61,11 @@ func Test_Sync_Success(t *testing.T) { Times(1) err := (&PeriodicSyncer{ - Client: c, - Recorder: erMock, - Keycloak: keyMock, - SyncClusterRoles: []string{"import-role", "existing-role"}, + Client: c, + Recorder: erMock, + Keycloak: keyMock, + SyncClusterRoles: []string{"import-role", "existing-role"}, + SyncClusterRolesUserPrefix: "appuio#", }).Sync(ctx) require.NoError(t, err) @@ -83,12 +84,12 @@ func Test_Sync_Success(t *testing.T) { { Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, - Name: "bar3", + Name: "appuio#bar3", }, { Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, - Name: "bar", + Name: "appuio#bar", }, }, rb.Subjects, "create new role") require.NoError(t, c.Get(ctx, types.NamespacedName{Name: "existing-role", Namespace: "bar"}, &rb)) @@ -96,12 +97,12 @@ func Test_Sync_Success(t *testing.T) { { Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, - Name: "bar3", + Name: "appuio#bar3", }, { Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, - Name: "bar", + Name: "appuio#bar", }, }, rb.Subjects, "update exiting role") diff --git a/main.go b/main.go index a1ae977..a85190f 100644 --- a/main.go +++ b/main.go @@ -67,6 +67,7 @@ func main() { crontab := flag.String("sync-schedule", "@every 5m", "A cron style schedule for the organization synchronization interval.") timeout := flag.Duration("sync-timeout", 10*time.Second, "The timeout for a single synchronization run.") syncRoles := flag.String("sync-roles", "", "A comma separated list of cluster roles to bind to users when importing a new organization.") + syncRolesUserPrefix := flag.String("sync-roles-user-prefix", "appuio#", "A prefix given to the users when assigning cluster roles from `sync-roles`.") opts := zap.Options{} opts.BindFlags(flag.CommandLine) @@ -87,6 +88,7 @@ func main() { mgr, or, err := setupManager( kc, roles, + *syncRolesUserPrefix, ctrl.Options{ Scheme: scheme, MetricsBindAddress: *metricsAddr, @@ -116,7 +118,7 @@ func main() { <-c.Stop().Done() } -func setupManager(kc controllers.KeycloakClient, syncRoles []string, opt ctrl.Options) (ctrl.Manager, *controllers.PeriodicSyncer, error) { +func setupManager(kc controllers.KeycloakClient, syncRoles []string, syncRolesUserPrefix string, opt ctrl.Options) (ctrl.Manager, *controllers.PeriodicSyncer, error) { mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), opt) if err != nil { return nil, nil, err @@ -151,10 +153,11 @@ func setupManager(kc controllers.KeycloakClient, syncRoles []string, opt ctrl.Op //+kubebuilder:scaffold:builder ps := &controllers.PeriodicSyncer{ - Client: mgr.GetClient(), - Recorder: mgr.GetEventRecorderFor("keycloak-adapter"), - Keycloak: kc, - SyncClusterRoles: syncRoles, + Client: mgr.GetClient(), + Recorder: mgr.GetEventRecorderFor("keycloak-adapter"), + Keycloak: kc, + SyncClusterRoles: syncRoles, + SyncClusterRolesUserPrefix: syncRolesUserPrefix, } if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {