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 #118

Merged
merged 25 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8a1e915
chore: release branch [ci skip] (#116)
Ani1357 Sep 18, 2024
1647ce6
feat: update readme and launch&tasks.json files for keycloak operator
ferruhcihan Sep 18, 2024
b26edab
feat: rm unnecessary lines from launch.json and package.json
ferruhcihan Sep 18, 2024
b7f14f7
feat: add createTeamUser in the keycloak operator
ferruhcihan Sep 19, 2024
dbff66a
Merge branch 'main' into APL-221
ferruhcihan Sep 24, 2024
b9d112e
feat: update groups
ferruhcihan Sep 25, 2024
21a7ada
feat: update create user
ferruhcihan Sep 25, 2024
86a9234
feat: update harbor operator
ferruhcihan Sep 25, 2024
3d769bd
feat: update create user
ferruhcihan Sep 26, 2024
e72ac42
feat: add delete keycloak users function
ferruhcihan Sep 26, 2024
1bb4d4e
test: delete keycloak users
ferruhcihan Sep 27, 2024
9dae385
feat: update create keycloak user
ferruhcihan Sep 27, 2024
b720b98
feat: update keycloak user without credentials
ferruhcihan Sep 27, 2024
008fb62
test: update user
ferruhcihan Sep 27, 2024
7d3f173
feat: update keycloak createUpdateUser
ferruhcihan Sep 27, 2024
e6e8fc4
feat: update keycloak.ts
ferruhcihan Sep 30, 2024
a89275d
test: users
ferruhcihan Oct 2, 2024
efcd26c
feat: keycloak userCreateUpdate
ferruhcihan Oct 2, 2024
5575ba9
feat: update user creation
ferruhcihan Oct 4, 2024
a6bae9e
feat: update keycloak manageUsers flow
ferruhcihan Oct 7, 2024
368bc63
Merge branch 'main' into APL-221
ferruhcihan Oct 8, 2024
2479e86
feat: update keycloak.ts and add keycloak.test.ts
ferruhcihan Oct 8, 2024
4c3fd7f
feat: update manageUsers
ferruhcihan Oct 9, 2024
1341489
feat: update existing otomi-admin user groups
ferruhcihan Oct 10, 2024
df3f196
fix: update platformAdminUser variable name
ferruhcihan Oct 10, 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
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"camelcase",
"creds",
"gitea",
"keycloak",
"kubernetes",
"oidc",
"openid",
Expand Down
34 changes: 5 additions & 29 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,41 +113,17 @@
{
"type": "node",
"request": "launch",
"name": "Debug Harbor task",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "tasks:harbor-dev"],
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env"
// "env": {
// "NODE_EXTRA_CA_CERTS": "${workspaceFolder}/.env.ca"
// }
},
{
"type": "node",
"request": "launch",
"name": "Debug Keycloak task",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "tasks:keycloak-dev"],
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env",
"env": {
"NODE_EXTRA_CA_CERTS": "${workspaceFolder}/.env.ca"
}
},
{
"type": "node",
"request": "launch",
"name": "Debug Keycloak operator",
"name": "Debug keycloak operator",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "operator:keycloak-dev"],
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env",
"env": {
"NODE_EXTRA_CA_CERTS": "${workspaceFolder}/.env.ca"
}
"NODE_EXTRA_CA_CERTS": "${workspaceFolder}/.env.ca",
"KUBECONFIG": "/path/to/your/kubeconfig.yaml",
},
"preLaunchTask": "port-forward-keycloak"
},
{
"type": "node",
Expand Down
11 changes: 11 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@
"reveal": "always",
"panel": "new"
}
},
{
"label": "port-forward-keycloak",
"type": "shell",
"command": "export KUBECONFIG=/path/to/your/kubeconfig.yaml && kubectl -n keycloak port-forward svc/keycloak-operator 8084:80",
"problemMatcher": [],
"isBackground": true,
"presentation": {
"reveal": "always",
"panel": "new"
}
}
]
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Then start a proxy to the api you wish to target:

- gitea: `k -n gitea port-forward svc/gitea-http 8082:3000 &`
- harbor: `k -n harbor port-forward svc/harbor-core 8083:80 &`
- keycloak: `k -n keycloak port-forward svc/keycloak-http 8084:80 &`
- keycloak: `k -n keycloak port-forward svc/keycloak-operator 8084:80 &`

Or start them all with `bin/start-proxies.sh`

Expand Down
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,6 @@
"tasks:copy-certs-dev": "ts-node-dev ./src/tasks/otomi/copy-certs.ts",
"tasks:copy-certs": "node dist/tasks/otomi/copy-certs.js",
"tasks:copy-certs-argo": "node dist/tasks/otomi/copy-certs-argo.js",
"tasks:harbor-dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 ts-node-dev ./src/tasks/harbor/harbor.ts",
"tasks:harbor": "node dist/tasks/harbor/harbor.js",
"tasks:keycloak-dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 ts-node-dev ./src/tasks/keycloak/keycloak.ts",
"tasks:keycloak": "node dist/tasks/keycloak/keycloak.js",
"tasks:keycloak-users-dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 ts-node-dev ./src/tasks/keycloak/users.ts",
"tasks:otomi-chart-dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 ts-node-dev ./src/tasks/otomi/otomi-chart.ts",
"tasks:otomi-chart": "node dist/tasks/otomi/otomi-chart.js",
Expand Down
8 changes: 4 additions & 4 deletions src/operator/harbor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ async function setupHarbor() {

const config: any = {
auth_mode: 'oidc_auth',
oidc_admin_group: 'admin',
oidc_admin_group: 'platform-admin',
j-zimnowoda marked this conversation as resolved.
Show resolved Hide resolved
oidc_client_id: 'otomi',
oidc_client_secret: env.oidcClientSecret,
oidc_endpoint: env.oidcEndpoint,
Expand Down Expand Up @@ -309,7 +309,7 @@ async function getBearerToken(): Promise<HttpBearerAuth> {
// unauthenticated, so remove and recreate secret
await k8sApi.deleteNamespacedSecret(systemSecretName, systemNamespace)
// now, the next call might throw IF:
// - authMode oidc was already turned on and an otomi admin accidentally removed the secret
// - authMode oidc was already turned on and an platform admin accidentally removed the secret
// but that is very unlikely, an unresolvable problem and needs a manual db fix
robotSecret = await createSystemRobotSecret()
}
Expand Down Expand Up @@ -366,7 +366,7 @@ async function processNamespace(namespace: string) {
const projAdminMember: ProjectMember = {
roleId: HarborRole.admin,
memberGroup: {
groupName: 'team-admin',
groupName: 'all-teams-admin',
j-zimnowoda marked this conversation as resolved.
Show resolved Hide resolved
groupType: HarborGroupType.http,
},
}
Expand All @@ -377,7 +377,7 @@ async function processNamespace(namespace: string) {
)
await doApiCall(
errors,
`Associating "project-admin" role for "team-admin" with harbor project "${projectName}"`,
`Associating "project-admin" role for "all-teams-admin" with harbor project "${projectName}"`,
() => memberApi.createProjectMember(projectId, undefined, undefined, projAdminMember),
)

Expand Down
76 changes: 76 additions & 0 deletions src/operator/keycloak.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { expect } from 'chai'
import sinon from 'sinon'
import { addUserGroups, removeUserGroups } from './keycloak'

describe('Keycloak User Group Management', () => {
let api: any
let existingUser: any
let keycloakRealm: string

beforeEach(() => {
keycloakRealm = 'otomi'
existingUser = { id: 'user-id' }
api = {
users: {
realmUsersIdGroupsGet: sinon.stub(),
realmUsersIdGroupsGroupIdDelete: sinon.stub(),
realmUsersIdGroupsGroupIdPut: sinon.stub(),
},
groups: {
realmGroupsGet: sinon.stub(),
},
}
})

afterEach(() => {
sinon.restore()
})

describe('removeUserGroups', () => {
it('should remove user from groups not in teamGroups', async () => {
const existingUserGroups = [
{ name: 'group1', id: 'group1-id' },
{ name: 'group2', id: 'group2-id' },
]
api.users.realmUsersIdGroupsGet.resolves({ body: existingUserGroups })

await removeUserGroups(api, existingUser, ['group1'])

expect(api.users.realmUsersIdGroupsGroupIdDelete.calledWith(keycloakRealm, 'user-id', 'group2-id')).to.be.true
expect(api.users.realmUsersIdGroupsGroupIdDelete.calledWith(keycloakRealm, 'user-id', 'group1-id')).to.be.false
})

it('should handle errors gracefully', async () => {
api.users.realmUsersIdGroupsGet.rejects(new Error('API Error'))

await removeUserGroups(api, existingUser, ['group1'])

expect(api.users.realmUsersIdGroupsGroupIdDelete.called).to.be.false
})
})

describe('addUserGroups', () => {
it('should add user to groups in teamGroups if not already present', async () => {
const currentKeycloakGroups = [
{ name: 'group1', id: 'group1-id' },
{ name: 'group2', id: 'group2-id' },
]
const existingUserGroups = [{ name: 'group1', id: 'group1-id' }]
api.groups.realmGroupsGet.resolves({ body: currentKeycloakGroups })
api.users.realmUsersIdGroupsGet.resolves({ body: existingUserGroups })

await addUserGroups(api, existingUser, ['group1', 'group2'])

expect(api.users.realmUsersIdGroupsGroupIdPut.calledWith(keycloakRealm, 'user-id', 'group2-id')).to.be.true
expect(api.users.realmUsersIdGroupsGroupIdPut.calledWith(keycloakRealm, 'user-id', 'group1-id')).to.be.false
})

it('should handle errors gracefully', async () => {
api.groups.realmGroupsGet.rejects(new Error('API Error'))

await addUserGroups(api, existingUser, ['group1'])

expect(api.users.realmUsersIdGroupsGroupIdPut.called).to.be.false
})
})
})
Loading