Skip to content

Commit c4c323f

Browse files
dougkirkleySergK
authored andcommitted
feat: Add the ability to add KeycloakClient service accounts to groups
Signed-off-by: Douglass Kirkley <doug.kirkley@gmail.com>
1 parent c6ac24d commit c4c323f

18 files changed

+202
-1
lines changed

api/v1/keycloakclient_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ type ServiceAccount struct {
208208
// +nullable
209209
// +optional
210210
Attributes map[string]string `json:"attributes,omitempty"`
211+
212+
// Groups is a list of groups assigned to service account
213+
// +nullable
214+
// +optional
215+
Groups []string `json:"groups,omitempty"`
211216
}
212217

213218
type ClientRole struct {

api/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/v1.edp.epam.com_keycloakclients.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,12 @@ spec:
613613
enabled:
614614
description: Enabled is a flag to enable service account.
615615
type: boolean
616+
groups:
617+
description: Groups is a list of groups assigned to service account
618+
items:
619+
type: string
620+
nullable: true
621+
type: array
616622
realmRoles:
617623
description: RealmRoles is a list of realm roles assigned to service
618624
account.

deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,12 @@ spec:
613613
enabled:
614614
description: Enabled is a flag to enable service account.
615615
type: boolean
616+
groups:
617+
description: Groups is a list of groups assigned to service account
618+
items:
619+
type: string
620+
nullable: true
621+
type: array
616622
realmRoles:
617623
description: RealmRoles is a list of realm roles assigned to service
618624
account.

docs/api.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,6 +3108,13 @@ ServiceAccount is a service account configuration.
31083108
Enabled is a flag to enable service account.<br/>
31093109
</td>
31103110
<td>false</td>
3111+
</tr><tr>
3112+
<td><b>groups</b></td>
3113+
<td>[]string</td>
3114+
<td>
3115+
Groups is a list of groups assigned to service account<br/>
3116+
</td>
3117+
<td>false</td>
31113118
</tr><tr>
31123119
<td><b>realmRoles</b></td>
31133120
<td>[]string</td>

internal/controller/keycloakclient/chain/service_account.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,12 @@ func (el *ServiceAccount) Serve(_ context.Context, keycloakClient *keycloakApi.K
4545
}
4646
}
4747

48+
if keycloakClient.Spec.ServiceAccount.Groups != nil {
49+
if err := el.keycloakApiClient.SetServiceAccountGroups(realmName,
50+
keycloakClient.Status.ClientID, keycloakClient.Spec.ServiceAccount.Groups, addOnly); err != nil {
51+
return errors.Wrap(err, "unable to sync service account groups")
52+
}
53+
}
54+
4855
return nil
4956
}

internal/controller/keycloakclient/chain/service_account_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func TestServiceAccount_Serve(t *testing.T) {
3030
},
3131
},
3232
RealmRoles: []string{"baz", "zaz"},
33+
Groups: []string{"group1", "group2"},
3334
},
3435
},
3536
Status: keycloakApi.KeycloakClientStatus{
@@ -46,6 +47,8 @@ func TestServiceAccount_Serve(t *testing.T) {
4647
kc.Spec.ServiceAccount.ClientRoles[0].ClientID: kc.Spec.ServiceAccount.ClientRoles[0].Roles}, false).Return(nil)
4748
apiClient.On("SetServiceAccountAttributes", realmName, kc.Status.ClientID,
4849
kc.Spec.ServiceAccount.Attributes, false).Return(nil)
50+
apiClient.On("SetServiceAccountGroups", realmName, kc.Status.ClientID,
51+
kc.Spec.ServiceAccount.Groups, false).Return(nil)
4952

5053
sa := NewServiceAccount(apiClient)
5154

internal/controller/keycloakclient/keycloakclient_controller_integration_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ var _ = Describe("KeycloakClient controller", Ordered, func() {
111111
Browser: "browser",
112112
DirectGrant: "direct grant",
113113
},
114+
ServiceAccount: &keycloakApi.ServiceAccount{
115+
Enabled: true,
116+
Groups: []string{"test-group"},
117+
},
114118
},
115119
}
116120
Expect(k8sClient.Create(ctx, keycloakClient)).Should(Succeed())
@@ -154,6 +158,9 @@ var _ = Describe("KeycloakClient controller", Ordered, func() {
154158
Browser: "browser",
155159
DirectGrant: "direct grant",
156160
},
161+
ServiceAccount: &keycloakApi.ServiceAccount{
162+
Enabled: true,
163+
},
157164
},
158165
}
159166
Expect(k8sClient.Create(ctx, keycloakClient)).Should(Succeed())

pkg/client/keycloak/adapter/gocloak_adapter_service_account.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,34 @@ func (a GoCloakAdapter) SetServiceAccountAttributes(realm, clientID string, attr
7474

7575
return nil
7676
}
77+
78+
func (a GoCloakAdapter) SetServiceAccountGroups(realm, clientID string, groups []string, addOnly bool) error {
79+
user, err := a.client.GetClientServiceAccount(context.Background(), a.token.AccessToken, realm, clientID)
80+
if err != nil {
81+
return errors.Wrap(err, "unable to get client service account")
82+
}
83+
84+
svcGroups := make(map[string]struct{})
85+
if addOnly && user.Groups != nil {
86+
for _, group := range *user.Groups {
87+
svcGroups[group] = struct{}{}
88+
}
89+
}
90+
91+
for _, group := range groups {
92+
svcGroups[group] = struct{}{}
93+
}
94+
95+
var newGroups []string
96+
for group := range svcGroups {
97+
newGroups = append(newGroups, group)
98+
}
99+
100+
user.Groups = &newGroups
101+
102+
if err = a.client.UpdateUser(context.Background(), a.token.AccessToken, realm, *user); err != nil {
103+
return errors.Wrapf(err, "unable to update service account user: %s", clientID)
104+
}
105+
106+
return nil
107+
}

pkg/client/keycloak/keycloak_client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Client interface {
2727
SyncServiceAccountRoles(realm, clientID string, realmRoles []string,
2828
clientRoles map[string][]string, addOnly bool) error
2929
SetServiceAccountAttributes(realm, clientID string, attributes map[string]string, addOnly bool) error
30+
SetServiceAccountGroups(realm, clientID string, groups []string, addOnly bool) error
3031
ExportToken() ([]byte, error)
3132
}
3233

0 commit comments

Comments
 (0)