Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: user management #1740

Merged
merged 31 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bb0910c
feat: update values-schema for users
ferruhcihan Sep 19, 2024
f06bd9e
test: versions
ferruhcihan Sep 19, 2024
b4c0de2
feat: update getUsers in the apl-keycloak-operator secret
ferruhcihan Sep 19, 2024
f00e8ef
feat: update user schema
ferruhcihan Sep 19, 2024
3b8ee12
Merge branch 'main' into APL-221
ferruhcihan Sep 24, 2024
922934f
Merge branch 'main' into APL-221
ferruhcihan Sep 24, 2024
1184e9d
feat: update user schema & write users to file
ferruhcihan Sep 26, 2024
491f8a2
feat: update users test files
ferruhcihan Sep 26, 2024
d17e7ce
feat: update env.gotmpl
ferruhcihan Sep 26, 2024
d2c6f3b
feat: update values schema
ferruhcihan Sep 27, 2024
2894be1
feat: update user test file
ferruhcihan Sep 27, 2024
084db2b
feat: update user test file
ferruhcihan Sep 27, 2024
b533a68
Merge branch 'main' into APL-221
ferruhcihan Sep 27, 2024
afd26a2
fix: revert apl chart notes.txt
ferruhcihan Sep 27, 2024
0e873b2
Merge branch 'main' into APL-221
ferruhcihan Sep 30, 2024
91024f4
fix: revert chart notes
ferruhcihan Sep 30, 2024
d9ccf8f
feat: update keycloak values-schema
ferruhcihan Sep 30, 2024
2ac7d94
test: users
ferruhcihan Oct 2, 2024
2185518
Merge branch 'main' into APL-221
srodenhuis Oct 3, 2024
bb186d6
Merge branch 'main' into APL-221
ferruhcihan Oct 4, 2024
6cda544
feat: update user in values-schema
ferruhcihan Oct 4, 2024
bfbc9dc
test: bootstrap with users
j-zimnowoda Oct 7, 2024
a6a2150
feat: update user management
ferruhcihan Oct 8, 2024
a81496b
feat: add user management values changes
ferruhcihan Oct 8, 2024
9ee90e1
feat: update users
ferruhcihan Oct 9, 2024
6af7a1a
feat: update bootstrap tests
ferruhcihan Oct 9, 2024
7f826c6
feat: update values-schema for user
ferruhcihan Oct 9, 2024
f2f6daa
Merge branch 'main' into APL-221
ferruhcihan Oct 9, 2024
2a461e6
Merge remote-tracking branch 'origin/main' into APL-221
j-zimnowoda Oct 10, 2024
ed8df93
Merge remote-tracking branch 'origin/main' into APL-221
j-zimnowoda Oct 14, 2024
5e3d4b9
chore: versions
j-zimnowoda Oct 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion chart/apl/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ otomi: {}
# clientSecret: ''
# issuer: ''
# # IDP group id used to identify global admin
# adminGroupID: ''
# platformAdminGroupID: ''
# # IDP group id used to identify all teams admin
# allTeamsAdminGroupID: ''
# # IDP group id used to identify team admin
# teamAdminGroupID: ''
1 change: 1 addition & 0 deletions helmfile.d/snippets/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,7 @@ environments:
hasExternalIDP: false
isMultitenant: true
nodeSelector: {}
users: []
e2e:
enabled: false
upgrade:
Expand Down
3 changes: 3 additions & 0 deletions helmfile.d/snippets/env.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ environments:
{{- end }}
{{- end }}
{{- end }}
{{- if eq (exec "bash" (list "-c" "( test -f $ENV_DIR/env/secrets.users.yaml && echo 'true' ) || echo 'false'") | trim) "true" }}
- {{ $ENV_DIR }}/env/secrets.users.yaml{{ $ext }}
{{- end }}
{{- if eq (exec "bash" (list "-c" "( test -f $ENV_DIR/env/secrets.settings.yaml && echo 'true' ) || echo 'false'") | trim) "true" }}
- {{ $ENV_DIR }}/env/secrets.settings.yaml{{ $ext }}
{{- end }}
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"envalid": "7.3.1",
"express": "4.18.1",
"fs-extra": "9.1.0",
"generate-password": "^1.7.1",
"ignore-walk": "3.0.4",
"lodash": "4.17.21",
"node-fetch": "2.6.7",
Expand Down
16 changes: 14 additions & 2 deletions src/cmd/bootstrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('Bootstrapping values', () => {
apps: { 'cert-manager': { issuer: 'custom-ca' } },
cluster: { name: 'bla', provider: 'dida' },
}
const users = [{ id: 'user1', initialPassword: 'existing-password' }, { id: 'user2' }]
const secrets = { secret: 'true', deep: { nested: 'secret' } }
const ageKeys = { publicKey: 'agePublicKey', privateKey: 'agePrivateKey' }
const kmsValues = {
Expand Down Expand Up @@ -241,6 +242,11 @@ describe('Bootstrapping values', () => {
})
describe('processing values', () => {
const generatedSecrets = { gen: 'x' }
const generatedPassword = 'generated-password'
const usersWithPasswords = [
{ id: 'user1', initialPassword: 'existing-password' },
{ id: 'user2', initialPassword: generatedPassword },
]
const ca = { a: 'cert' }
const mergedValues = merge(cloneDeep(values), cloneDeep(secrets))
const mergedSecretsWithCa = merge(cloneDeep(secrets), cloneDeep(ca))
Expand All @@ -262,6 +268,7 @@ describe('Bootstrapping values', () => {
terminal,
validateValues: jest.fn().mockReturnValue(true),
writeValues: jest.fn(),
generatePassword: jest.fn().mockReturnValue(generatedPassword),
}
})
describe('Creating CA', () => {
Expand Down Expand Up @@ -335,10 +342,15 @@ describe('Bootstrapping values', () => {
expect(res).toEqual(mergedValues)
})
it('should merge original with generated values and write them to env dir', async () => {
const writtenValues = merge(cloneDeep(values), cloneDeep(mergedSecretsWithGenAndCa))
deps.loadYaml.mockReturnValue(values)
const writtenValues = merge(
cloneDeep(values),
cloneDeep(mergedSecretsWithGenAndCa),
cloneDeep({ users: usersWithPasswords }),
)
deps.loadYaml.mockReturnValue({ ...values, users })
deps.getStoredClusterSecrets.mockReturnValue(secrets)
deps.generateSecrets.mockReturnValue(generatedSecrets)
deps.generatePassword.mockReturnValue(generatedPassword)
await processValues(deps)
expect(deps.writeValues).toHaveBeenNthCalledWith(2, writtenValues)
})
Expand Down
17 changes: 16 additions & 1 deletion src/cmd/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { copy, pathExists } from 'fs-extra'
import { copyFile, mkdir, readFile, writeFile } from 'fs/promises'
import { generate as generatePassword } from 'generate-password'
import { cloneDeep, get, merge } from 'lodash'
import { pki } from 'node-forge'
import path from 'path'
Expand Down Expand Up @@ -252,6 +253,7 @@ export const processValues = async (
generateSecrets,
createK8sSecret,
createCustomCA,
generatePassword,
},
): Promise<Record<string, any> | undefined> => {
const d = deps.terminal(`cmd:${cmdName}:processValues`)
Expand Down Expand Up @@ -287,8 +289,21 @@ export const processValues = async (
}
// merge existing secrets over newly generated ones to keep them
const allSecrets = merge(cloneDeep(caSecrets), cloneDeep(storedSecrets), cloneDeep(generatedSecrets))
// generate initial passwords for users if they don't have one
const users = get(originalInput, 'users', [])
for (const user of users) {
if (!user.initialPassword) {
user.initialPassword = deps.generatePassword({
length: 16,
numbers: true,
symbols: true,
lowercase: true,
uppercase: true,
})
}
}
// we have generated all we need, now store everything by merging the original values over all the secrets
await deps.writeValues(merge(cloneDeep(allSecrets), cloneDeep(originalInput)))
await deps.writeValues(merge(cloneDeep(allSecrets), cloneDeep(originalInput), cloneDeep({ users })))
// and do some context dependent post processing:
if (deps.isChart) {
// to support potential failing chart install we store secrets on cluster
Expand Down
3 changes: 3 additions & 0 deletions src/common/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,17 @@ export const writeValues = async (inValues: Record<string, any>, overwrite = fal
'databases',
'files',
'bootstrap',
'users',
]
const secretSettings = omit(secrets, fieldsToOmit)
const license = { license: values?.license }
const settings = omit(plainValues, fieldsToOmit)
const users = { users: values?.users }
// and write to their files
const promises: Promise<void>[] = []
if (settings) promises.push(writeValuesToFile(`${env.ENV_DIR}/env/settings.yaml`, settings, overwrite))
if (license) promises.push(writeValuesToFile(`${env.ENV_DIR}/env/secrets.license.yaml`, license, overwrite))
if (users) promises.push(writeValuesToFile(`${env.ENV_DIR}/env/secrets.users.yaml`, users, overwrite))
if (secretSettings || overwrite)
promises.push(writeValuesToFile(`${env.ENV_DIR}/env/secrets.settings.yaml`, secretSettings, overwrite))
if (plainValues.cluster || overwrite)
Expand Down
7 changes: 7 additions & 0 deletions tests/bootstrap/input.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ otomi:
apps:
metrics-server:
enabled: false
users:
j-zimnowoda marked this conversation as resolved.
Show resolved Hide resolved
- email: [email protected]
firstName: platform
lastName: admin
isPlatformAdmin: true
isTeamAdmin: false
teams: []
22 changes: 22 additions & 0 deletions tests/fixtures/env/secrets.users.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
users:
- email: [email protected]
firstName: platform
lastName: admin
isPlatformAdmin: true
isTeamAdmin: true
teams: ['demo']
initialPassword: 'platform-admin-password'
- email: [email protected]
firstName: team
lastName: admin
isPlatformAdmin: false
isTeamAdmin: true
teams: ['demo']
initialPassword: 'team-admin-password'
- email: [email protected]
firstName: team
lastName: member
isPlatformAdmin: false
isTeamAdmin: false
teams: ['demo']
initialPassword: 'team-member-password'
3 changes: 2 additions & 1 deletion tests/fixtures/env/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ obj:
thanos: my-clusterid-thanos
type: linode
oidc:
adminGroupID: someAdminGroupID
platformAdminGroupID: someAdminGroupID
clientID: someClientID
issuer: https://login.microsoftonline.com/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
subClaimMapper: oid
allTeamsAdminGroupID: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
teamAdminGroupID: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
otomi:
additionalClusters:
Expand Down
4 changes: 4 additions & 0 deletions values-changes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,7 @@ changes:
deletions:
- 'teamConfig.{team}.managedMonitoring.prometheus'
- 'apps.grafana.resources.downloadDashboards'
- version: 30
relocations:
- 'oidc.adminGroupID': 'oidc.platformAdminGroupID'
- 'oidc.teamAdminGroupID': 'oidc.allTeamsAdminGroupID'
41 changes: 38 additions & 3 deletions values-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,6 @@ definitions:
- value
required:
- name

sealedsecret:
type: object
description: Define location of code to build
Expand Down Expand Up @@ -1341,7 +1340,6 @@ definitions:
- type
- encryptedData
- name

workload:
type: object
description: Define location of the application's manifests or chart
Expand Down Expand Up @@ -1435,6 +1433,37 @@ definitions:
required:
- name
- url
user:
type: object
description: A user in keycloak, who can be a platform admin, a team admin, or a team member.
properties:
email:
$ref: '#/definitions/email'
x-secret: ''
firstName:
type: string
x-secret: ''
lastName:
type: string
x-secret: ''
isPlatformAdmin:
type: boolean
x-secret: ''
isTeamAdmin:
type: boolean
x-secret: ''
teams:
type: array
items:
type: string
x-secret: ''
initialPassword:
j-zimnowoda marked this conversation as resolved.
Show resolved Hide resolved
type: string
x-secret: ''
required:
- email
- firstName
- lastName

properties:
alerts:
Expand Down Expand Up @@ -2896,7 +2925,9 @@ properties:
clientSecret:
type: string
x-secret: ''
adminGroupID:
platformAdminGroupID:
$ref: '#/definitions/wordCharacterPattern'
allTeamsAdminGroupID:
j-zimnowoda marked this conversation as resolved.
Show resolved Hide resolved
$ref: '#/definitions/wordCharacterPattern'
teamAdminGroupID:
$ref: '#/definitions/wordCharacterPattern'
Expand Down Expand Up @@ -3221,5 +3252,9 @@ properties:
type: string
helm:
type: object
users:
type: array
items:
$ref: '#/definitions/user'
required:
- cluster
16 changes: 14 additions & 2 deletions values/apl-keycloak-operator/apl-keycloak-operator-raw.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
{{- $k := $c | get "keycloak" }}
{{- $doms := tpl (readFile "../../helmfile.d/snippets/domains.gotmpl") $v | fromYaml }}
{{- $joinTpl := readFile "../../helmfile.d/utils/joinListWithSep.gotmpl" }}
{{ $users := list }}
{{- range $user := $v.users }}
j-zimnowoda marked this conversation as resolved.
Show resolved Hide resolved
{{ $groups := list }}
{{- if $user.isPlatformAdmin }}{{ $groups = append $groups "platform-admin" }}{{ end }}
{{- if $user.isTeamAdmin }}{{ $groups = append $groups "team-admin" }}{{ end }}
{{- range $team := $user.teams }}{{ $groups = append $groups (print "team-" $team) }}{{ end }}
{{- $users = append $users (dict "email" $user.email "firstName" $user.firstName "lastName" $user.lastName "initialPassword" $user.initialPassword "groups" $groups) }}
{{- end }}
{{- $users := $users | toJson }}

resources:
- apiVersion: v1
Expand All @@ -29,6 +38,7 @@ resources:
KEYCLOAK_ADMIN: {{ .Values.apps.keycloak.adminUsername | b64enc }}
KEYCLOAK_ADMIN_PASSWORD: {{ $k.adminPassword | b64enc }}
KEYCLOAK_CLIENT_SECRET: {{ $k.idp.clientSecret | b64enc }}
USERS: {{ $users | b64enc }}
{{- if $v.otomi.hasExternalIDP }}
IDP_CLIENT_ID: {{ $oi.clientID | b64enc}}
IDP_CLIENT_SECRET: {{ $oi.clientSecret | b64enc }}
Expand Down Expand Up @@ -56,8 +66,10 @@ resources:
{{- with $oi | get "subClaimMapper" nil }}
IDP_SUB_CLAIM_MAPPER: {{ . }}{{ end }}
IDP_GROUP_MAPPINGS_TEAMS: '{{ $teamsMapping | toJson }}'
{{- with $oi | get "adminGroupID" nil }}
IDP_GROUP_apl_ADMIN: {{ . }}{{ end }}
{{- with $oi | get "platformAdminGroupID" nil }}
IDP_GROUP_PLATFORM_ADMIN: {{ . }}{{ end }}
{{- with $oi | get "allTeamsAdminGroupID" nil }}
IDP_GROUP_ALL_TEAMS_ADMIN: {{ . }}{{ end }}
{{- with $oi | get "teamAdminGroupID" nil }}
IDP_GROUP_TEAM_ADMIN: {{ . }}{{ end }}
IDP_OIDC_URL: {{ $oi.issuer }}
Expand Down
6 changes: 4 additions & 2 deletions values/jobs/keycloak.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ env:
{{- with $o | get "subClaimMapper" nil }}
IDP_SUB_CLAIM_MAPPER: {{ . }}{{ end }}
IDP_GROUP_MAPPINGS_TEAMS: '{{ $teamsMapping | toJson }}'
{{- with $o | get "adminGroupID" nil }}
IDP_GROUP_OTOMI_ADMIN: {{ . }}{{ end }}
{{- with $o | get "platformAdminGroupID" nil }}
IDP_GROUP_PLATFORM_ADMIN: {{ . }}{{ end }}
{{- with $o | get "allTeamsAdminGroupID" nil }}
IDP_GROUP_ALL_TEAMS_ADMIN: {{ . }}{{ end }}
{{- with $o | get "teamAdminGroupID" nil }}
IDP_GROUP_TEAM_ADMIN: {{ . }}{{ end }}
IDP_OIDC_URL: {{ $o.issuer }}
Expand Down
6 changes: 3 additions & 3 deletions versions.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
api: main
console: main
tasks: main
api: APL-221
console: APL-221
tasks: APL-221
tools: 2.7.0