Skip to content

Conversation

sandeepbh5
Copy link
Contributor

Description

Migrating the keycloak image to 'redhat's repo'
keycloak chart to 'codecentric'
Fixes # (issue)

Any Newly Introduced Dependencies

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

Checklist:

  • [ .] I agree to use the APACHE-2.0 license for my code changes
  • I have not introduced any 3rd party dependency changes
  • [ .] I have performed a self-review of my code

@sandeepbh5 sandeepbh5 changed the title migrating from bitnami to redhat img & codecentric chart keycloak : migrating from bitnami to redhat img & codecentric chart Sep 25, 2025
@sandeepbh5 sandeepbh5 force-pushed the bitnami-to-redhat-keycloak branch from fb00bb9 to 329d0ca Compare September 25, 2025 10:54
@sandeepbh5 sandeepbh5 force-pushed the bitnami-to-redhat-keycloak branch from da46801 to fe33700 Compare September 30, 2025 12:42
…-compatibility service

- Changed keycloak-tenant-controller to use admin-cli instead of non-existent system-client
- Added platform-keycloak-compat-service for backward compatibility
- Reverted all service URLs back to platform-keycloak.orch-platform.svc
- Creates ClusterIP service that points to same endpoints as platform-keycloak-http
- Change keycloak-tenant-controller to use system-client instead of admin-cli
- Add groups scope to system-client defaultClientScopes in realm config
- This resolves authentication failures due to missing groups scope in Codecentric Keycloak

Fixes: Keycloak authentication failing with 'Invalid scopes: groups' error
Related: Migration from Bitnami to Codecentric Keycloak
- Add automated system-client creation job with groups scope
- Ensures compatibility with Codecentric Keycloak charts
- Runs after Keycloak deployment but before tenant controller
- Fixes authentication issues during Bitnami to Codecentric migration
- Fix authentication failures caused by special characters (&) in passwords
- Add proper URL encoding function for form data
- Ensure reliable system-client creation for fresh deployments
- Resolves CrashLoopBackOff issues in keycloak-tenant-controller
- Replace bash-specific {1..30} syntax with portable while loop
- Fix URL encoding for passwords with special characters
- Ensure compatibility across different shell environments
- Ready for fresh deployment testing
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check notice

Code scanning / Trivy

CPU not limited Low

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV011
Severity: LOW
Message: Container 'setup-client' of Job 'keycloak-system-client-setup' should set 'resources.limits.cpu'
Link: KSV011
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check notice

Code scanning / Trivy

CPU requests not specified Low

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV015
Severity: LOW
Message: Container 'setup-client' of Job 'keycloak-system-client-setup' should set 'resources.requests.cpu'
Link: KSV015
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check notice

Code scanning / Trivy

Memory requests not specified Low

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV016
Severity: LOW
Message: Container 'setup-client' of Job 'keycloak-system-client-setup' should set 'resources.requests.memory'
Link: KSV016
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check notice

Code scanning / Trivy

Memory not limited Low

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV018
Severity: LOW
Message: Container 'setup-client' of Job 'keycloak-system-client-setup' should set 'resources.limits.memory'
Link: KSV018
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check notice

Code scanning / Trivy

Runs with UID <= 10000 Low

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV020
Severity: LOW
Message: Container 'setup-client' of Job 'keycloak-system-client-setup' should set 'securityContext.runAsUser' > 10000
Link: KSV020
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check notice

Code scanning / Trivy

Runs with GID <= 10000 Low

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV021
Severity: LOW
Message: Container 'setup-client' of Job 'keycloak-system-client-setup' should set 'securityContext.runAsGroup' > 10000
Link: KSV021
Comment on lines +36 to +66
- name: setup-client
image: badouralix/curl-jq@sha256:fe8a5ee49f613495df3b57afa86b39f081bd1b3b9ed61248f46c3d3d7df56092
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: ADMIN_USER
value: "admin"
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: NO_PROXY
value: "*"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: "RuntimeDefault"
command: ["/bin/sh"]
args:
- -c
- |

Check warning

Code scanning / Trivy

Restrict container images to trusted registries Medium

Artifact: argocd/applications/configs/keycloak-system-client-setup-job.yaml
Type: kubernetes
Vulnerability KSV0125
Severity: MEDIUM
Message: Container setup-client in job keycloak-system-client-setup (namespace: orch-platform) uses an image from an untrusted registry.
Link: KSV0125
- Fix JSON syntax error in platform-keycloak-realm-config.yaml (remove YAML multiline syntax)
- Update keycloak-config-cli image to working version (6.4.0-26)
- Add IMPORT_FILES_LOCATIONS environment variable for correct config path
- Fix YAML syntax errors in infra-onboarding.yaml
- Ensure admin-cli client has groups scope for backward compatibility

This ensures app-orch-tenant-controller and other services work in fresh deployments.
Comment on lines +35 to +85
- name: keycloak-config-cli
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: IMPORT_MANAGED_GROUP
value: "no-delete"
- name: IMPORT_MANAGED_REQUIRED_ACTION
value: "no-delete"
- name: IMPORT_MANAGED_ROLE
value: "no-delete"
- name: IMPORT_MANAGED_CLIENT
value: "no-delete"
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
- name: IMPORT_FILES_LOCATIONS
value: "/opt/keycloak-config-cli/configs/*"
volumeMounts:
- name: keycloak-config
mountPath: /opt/keycloak-config-cli/configs
readOnly: true
- name: tmp-volume
mountPath: /tmp
- name: var-tmp-volume
mountPath: /var/tmp
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"

Check notice

Code scanning / Trivy

Runs with UID <= 10000 Low

Artifact: argocd/applications/configs/platform-keycloak-config-job.yaml
Type: kubernetes
Vulnerability KSV020
Severity: LOW
Message: Container 'keycloak-config-cli' of Job 'platform-keycloak-config-import' should set 'securityContext.runAsUser' > 10000
Link: KSV020
Comment on lines +35 to +85
- name: keycloak-config-cli
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: IMPORT_MANAGED_GROUP
value: "no-delete"
- name: IMPORT_MANAGED_REQUIRED_ACTION
value: "no-delete"
- name: IMPORT_MANAGED_ROLE
value: "no-delete"
- name: IMPORT_MANAGED_CLIENT
value: "no-delete"
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
- name: IMPORT_FILES_LOCATIONS
value: "/opt/keycloak-config-cli/configs/*"
volumeMounts:
- name: keycloak-config
mountPath: /opt/keycloak-config-cli/configs
readOnly: true
- name: tmp-volume
mountPath: /tmp
- name: var-tmp-volume
mountPath: /var/tmp
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"

Check notice

Code scanning / Trivy

Runs with GID <= 10000 Low

Artifact: argocd/applications/configs/platform-keycloak-config-job.yaml
Type: kubernetes
Vulnerability KSV021
Severity: LOW
Message: Container 'keycloak-config-cli' of Job 'platform-keycloak-config-import' should set 'securityContext.runAsGroup' > 10000
Link: KSV021
Comment on lines +35 to +85
- name: keycloak-config-cli
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: IMPORT_MANAGED_GROUP
value: "no-delete"
- name: IMPORT_MANAGED_REQUIRED_ACTION
value: "no-delete"
- name: IMPORT_MANAGED_ROLE
value: "no-delete"
- name: IMPORT_MANAGED_CLIENT
value: "no-delete"
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
- name: IMPORT_FILES_LOCATIONS
value: "/opt/keycloak-config-cli/configs/*"
volumeMounts:
- name: keycloak-config
mountPath: /opt/keycloak-config-cli/configs
readOnly: true
- name: tmp-volume
mountPath: /tmp
- name: var-tmp-volume
mountPath: /var/tmp
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"

Check warning

Code scanning / Trivy

Restrict container images to trusted registries Medium

Artifact: argocd/applications/configs/platform-keycloak-config-job.yaml
Type: kubernetes
Vulnerability KSV0125
Severity: MEDIUM
Message: Container keycloak-config-cli in job platform-keycloak-config-import (namespace: orch-platform) uses an image from an untrusted registry.
Link: KSV0125
- Update deployRepoRevision to latest commit with all fixes (0e632db)
- Add keycloak-admin-cli-config-job for permanent admin-cli configuration
- Ensures admin-cli client has groups scope with proper protocol mapper
- Guarantees authentication works in fresh deployments and redeployments

This job runs after Keycloak startup and configures:
1. admin-cli client with groups scope in defaultClientScopes
2. groups scope with oidc-group-membership-mapper protocol mapper
3. Proper configuration for backward compatibility with auth libraries

Resolves authentication failures in app-orch-tenant-controller and infra-onboarding.
Updated to 59a331d which includes:
- All Keycloak authentication fixes
- JSON syntax corrections in realm config
- Fixed keycloak-config-cli image version
- New admin-cli configuration job for permanent solution
Comment on lines +35 to +145
- name: keycloak-admin-cli-config
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
command:
- /bin/sh
- -c
- |
set -e
echo "Waiting for Keycloak to be ready..."

# Wait for Keycloak to be available
timeout=120
while [ $timeout -gt 0 ]; do
if curl -f -s "$KEYCLOAK_URL/realms/master/.well-known/openid_configuration" >/dev/null 2>&1; then
echo "Keycloak is ready"
break
fi
echo "Waiting for Keycloak... ($timeout seconds left)"
sleep 5
timeout=$((timeout - 5))
done

if [ $timeout -le 0 ]; then
echo "Timeout waiting for Keycloak"
exit 1
fi

# Configure kcadm
/opt/keycloak/bin/kcadm.sh config credentials --server "$KEYCLOAK_URL" --realm master --user "$KEYCLOAK_USER" --password "$KEYCLOAK_PASSWORD"

# Get admin-cli client ID
ADMIN_CLI_ID=$(/opt/keycloak/bin/kcadm.sh get clients -r master -q clientId=admin-cli --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$ADMIN_CLI_ID" ]; then
echo "admin-cli client not found"
exit 1
fi

echo "Found admin-cli client with ID: $ADMIN_CLI_ID"

# Get groups scope ID
GROUPS_SCOPE_ID=$(/opt/keycloak/bin/kcadm.sh get client-scopes -r master -q name=groups --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$GROUPS_SCOPE_ID" ]; then
echo "groups scope not found"
exit 1
fi

echo "Found groups scope with ID: $GROUPS_SCOPE_ID"

# Check if admin-cli already has groups scope
CURRENT_SCOPES=$(/opt/keycloak/bin/kcadm.sh get clients/$ADMIN_CLI_ID -r master --fields defaultClientScopes)

if echo "$CURRENT_SCOPES" | grep -q "groups"; then
echo "admin-cli client already has groups scope"
else
echo "Adding groups scope to admin-cli client"
/opt/keycloak/bin/kcadm.sh update clients/$ADMIN_CLI_ID -r master -s 'defaultClientScopes=["web-origins","acr","roles","profile","basic","email","groups"]'
echo "Successfully added groups scope to admin-cli client"
fi

# Check if groups scope has protocol mapper
MAPPERS=$(/opt/keycloak/bin/kcadm.sh get client-scopes/$GROUPS_SCOPE_ID -r master --fields protocolMappers)

if echo "$MAPPERS" | grep -q "oidc-group-membership-mapper"; then
echo "groups scope already has protocol mapper"
else
echo "Adding protocol mapper to groups scope"
MAPPER_ID=$(/opt/keycloak/bin/kcadm.sh create client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models -r master -s name=groups -s protocol=openid-connect -s protocolMapper=oidc-group-membership-mapper -s consentRequired=false 2>&1 | grep "Created new model with id" | sed "s/.*Created new model with id '\([^']*\)'.*/\1/")

if [ -n "$MAPPER_ID" ]; then
echo "Created protocol mapper with ID: $MAPPER_ID"
/opt/keycloak/bin/kcadm.sh update client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models/$MAPPER_ID -r master -s 'config={"multivalued":"true","full.path":"false","id.token.claim":"true","access.token.claim":"true","claim.name":"groups","userinfo.token.claim":"true","jsonType.label":"String"}'
echo "Successfully configured groups protocol mapper"
else
echo "Failed to create protocol mapper"
exit 1
fi
fi

echo "Keycloak admin-cli configuration completed successfully"
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m" No newline at end of file

Check failure

Code scanning / Trivy

Root file system is not read-only High

Artifact: argocd/applications/configs/keycloak-admin-cli-config-job.yaml
Type: kubernetes
Vulnerability KSV014
Severity: HIGH
Message: Container 'keycloak-admin-cli-config' of Job 'keycloak-admin-cli-config' should set 'securityContext.readOnlyRootFilesystem' to true
Link: KSV014
Comment on lines +35 to +145
- name: keycloak-admin-cli-config
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
command:
- /bin/sh
- -c
- |
set -e
echo "Waiting for Keycloak to be ready..."

# Wait for Keycloak to be available
timeout=120
while [ $timeout -gt 0 ]; do
if curl -f -s "$KEYCLOAK_URL/realms/master/.well-known/openid_configuration" >/dev/null 2>&1; then
echo "Keycloak is ready"
break
fi
echo "Waiting for Keycloak... ($timeout seconds left)"
sleep 5
timeout=$((timeout - 5))
done

if [ $timeout -le 0 ]; then
echo "Timeout waiting for Keycloak"
exit 1
fi

# Configure kcadm
/opt/keycloak/bin/kcadm.sh config credentials --server "$KEYCLOAK_URL" --realm master --user "$KEYCLOAK_USER" --password "$KEYCLOAK_PASSWORD"

# Get admin-cli client ID
ADMIN_CLI_ID=$(/opt/keycloak/bin/kcadm.sh get clients -r master -q clientId=admin-cli --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$ADMIN_CLI_ID" ]; then
echo "admin-cli client not found"
exit 1
fi

echo "Found admin-cli client with ID: $ADMIN_CLI_ID"

# Get groups scope ID
GROUPS_SCOPE_ID=$(/opt/keycloak/bin/kcadm.sh get client-scopes -r master -q name=groups --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$GROUPS_SCOPE_ID" ]; then
echo "groups scope not found"
exit 1
fi

echo "Found groups scope with ID: $GROUPS_SCOPE_ID"

# Check if admin-cli already has groups scope
CURRENT_SCOPES=$(/opt/keycloak/bin/kcadm.sh get clients/$ADMIN_CLI_ID -r master --fields defaultClientScopes)

if echo "$CURRENT_SCOPES" | grep -q "groups"; then
echo "admin-cli client already has groups scope"
else
echo "Adding groups scope to admin-cli client"
/opt/keycloak/bin/kcadm.sh update clients/$ADMIN_CLI_ID -r master -s 'defaultClientScopes=["web-origins","acr","roles","profile","basic","email","groups"]'
echo "Successfully added groups scope to admin-cli client"
fi

# Check if groups scope has protocol mapper
MAPPERS=$(/opt/keycloak/bin/kcadm.sh get client-scopes/$GROUPS_SCOPE_ID -r master --fields protocolMappers)

if echo "$MAPPERS" | grep -q "oidc-group-membership-mapper"; then
echo "groups scope already has protocol mapper"
else
echo "Adding protocol mapper to groups scope"
MAPPER_ID=$(/opt/keycloak/bin/kcadm.sh create client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models -r master -s name=groups -s protocol=openid-connect -s protocolMapper=oidc-group-membership-mapper -s consentRequired=false 2>&1 | grep "Created new model with id" | sed "s/.*Created new model with id '\([^']*\)'.*/\1/")

if [ -n "$MAPPER_ID" ]; then
echo "Created protocol mapper with ID: $MAPPER_ID"
/opt/keycloak/bin/kcadm.sh update client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models/$MAPPER_ID -r master -s 'config={"multivalued":"true","full.path":"false","id.token.claim":"true","access.token.claim":"true","claim.name":"groups","userinfo.token.claim":"true","jsonType.label":"String"}'
echo "Successfully configured groups protocol mapper"
else
echo "Failed to create protocol mapper"
exit 1
fi
fi

echo "Keycloak admin-cli configuration completed successfully"
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m" No newline at end of file

Check notice

Code scanning / Trivy

Runs with UID <= 10000 Low

Artifact: argocd/applications/configs/keycloak-admin-cli-config-job.yaml
Type: kubernetes
Vulnerability KSV020
Severity: LOW
Message: Container 'keycloak-admin-cli-config' of Job 'keycloak-admin-cli-config' should set 'securityContext.runAsUser' > 10000
Link: KSV020
Comment on lines +35 to +145
- name: keycloak-admin-cli-config
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
command:
- /bin/sh
- -c
- |
set -e
echo "Waiting for Keycloak to be ready..."

# Wait for Keycloak to be available
timeout=120
while [ $timeout -gt 0 ]; do
if curl -f -s "$KEYCLOAK_URL/realms/master/.well-known/openid_configuration" >/dev/null 2>&1; then
echo "Keycloak is ready"
break
fi
echo "Waiting for Keycloak... ($timeout seconds left)"
sleep 5
timeout=$((timeout - 5))
done

if [ $timeout -le 0 ]; then
echo "Timeout waiting for Keycloak"
exit 1
fi

# Configure kcadm
/opt/keycloak/bin/kcadm.sh config credentials --server "$KEYCLOAK_URL" --realm master --user "$KEYCLOAK_USER" --password "$KEYCLOAK_PASSWORD"

# Get admin-cli client ID
ADMIN_CLI_ID=$(/opt/keycloak/bin/kcadm.sh get clients -r master -q clientId=admin-cli --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$ADMIN_CLI_ID" ]; then
echo "admin-cli client not found"
exit 1
fi

echo "Found admin-cli client with ID: $ADMIN_CLI_ID"

# Get groups scope ID
GROUPS_SCOPE_ID=$(/opt/keycloak/bin/kcadm.sh get client-scopes -r master -q name=groups --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$GROUPS_SCOPE_ID" ]; then
echo "groups scope not found"
exit 1
fi

echo "Found groups scope with ID: $GROUPS_SCOPE_ID"

# Check if admin-cli already has groups scope
CURRENT_SCOPES=$(/opt/keycloak/bin/kcadm.sh get clients/$ADMIN_CLI_ID -r master --fields defaultClientScopes)

if echo "$CURRENT_SCOPES" | grep -q "groups"; then
echo "admin-cli client already has groups scope"
else
echo "Adding groups scope to admin-cli client"
/opt/keycloak/bin/kcadm.sh update clients/$ADMIN_CLI_ID -r master -s 'defaultClientScopes=["web-origins","acr","roles","profile","basic","email","groups"]'
echo "Successfully added groups scope to admin-cli client"
fi

# Check if groups scope has protocol mapper
MAPPERS=$(/opt/keycloak/bin/kcadm.sh get client-scopes/$GROUPS_SCOPE_ID -r master --fields protocolMappers)

if echo "$MAPPERS" | grep -q "oidc-group-membership-mapper"; then
echo "groups scope already has protocol mapper"
else
echo "Adding protocol mapper to groups scope"
MAPPER_ID=$(/opt/keycloak/bin/kcadm.sh create client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models -r master -s name=groups -s protocol=openid-connect -s protocolMapper=oidc-group-membership-mapper -s consentRequired=false 2>&1 | grep "Created new model with id" | sed "s/.*Created new model with id '\([^']*\)'.*/\1/")

if [ -n "$MAPPER_ID" ]; then
echo "Created protocol mapper with ID: $MAPPER_ID"
/opt/keycloak/bin/kcadm.sh update client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models/$MAPPER_ID -r master -s 'config={"multivalued":"true","full.path":"false","id.token.claim":"true","access.token.claim":"true","claim.name":"groups","userinfo.token.claim":"true","jsonType.label":"String"}'
echo "Successfully configured groups protocol mapper"
else
echo "Failed to create protocol mapper"
exit 1
fi
fi

echo "Keycloak admin-cli configuration completed successfully"
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m" No newline at end of file

Check notice

Code scanning / Trivy

Runs with GID <= 10000 Low

Artifact: argocd/applications/configs/keycloak-admin-cli-config-job.yaml
Type: kubernetes
Vulnerability KSV021
Severity: LOW
Message: Container 'keycloak-admin-cli-config' of Job 'keycloak-admin-cli-config' should set 'securityContext.runAsGroup' > 10000
Link: KSV021
Comment on lines +35 to +145
- name: keycloak-admin-cli-config
image: quay.io/adorsys/keycloak-config-cli:6.4.0-26
imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_URL
value: "http://platform-keycloak.orch-platform.svc.cluster.local:8080"
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
valueFrom:
secretKeyRef:
name: platform-keycloak
key: admin-password
- name: KEYCLOAK_AVAILABILITYCHECK_ENABLED
value: "true"
- name: KEYCLOAK_AVAILABILITYCHECK_TIMEOUT
value: "120s"
command:
- /bin/sh
- -c
- |
set -e
echo "Waiting for Keycloak to be ready..."

# Wait for Keycloak to be available
timeout=120
while [ $timeout -gt 0 ]; do
if curl -f -s "$KEYCLOAK_URL/realms/master/.well-known/openid_configuration" >/dev/null 2>&1; then
echo "Keycloak is ready"
break
fi
echo "Waiting for Keycloak... ($timeout seconds left)"
sleep 5
timeout=$((timeout - 5))
done

if [ $timeout -le 0 ]; then
echo "Timeout waiting for Keycloak"
exit 1
fi

# Configure kcadm
/opt/keycloak/bin/kcadm.sh config credentials --server "$KEYCLOAK_URL" --realm master --user "$KEYCLOAK_USER" --password "$KEYCLOAK_PASSWORD"

# Get admin-cli client ID
ADMIN_CLI_ID=$(/opt/keycloak/bin/kcadm.sh get clients -r master -q clientId=admin-cli --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$ADMIN_CLI_ID" ]; then
echo "admin-cli client not found"
exit 1
fi

echo "Found admin-cli client with ID: $ADMIN_CLI_ID"

# Get groups scope ID
GROUPS_SCOPE_ID=$(/opt/keycloak/bin/kcadm.sh get client-scopes -r master -q name=groups --fields id | grep '"id"' | sed 's/.*"id" : "\([^"]*\)".*/\1/')

if [ -z "$GROUPS_SCOPE_ID" ]; then
echo "groups scope not found"
exit 1
fi

echo "Found groups scope with ID: $GROUPS_SCOPE_ID"

# Check if admin-cli already has groups scope
CURRENT_SCOPES=$(/opt/keycloak/bin/kcadm.sh get clients/$ADMIN_CLI_ID -r master --fields defaultClientScopes)

if echo "$CURRENT_SCOPES" | grep -q "groups"; then
echo "admin-cli client already has groups scope"
else
echo "Adding groups scope to admin-cli client"
/opt/keycloak/bin/kcadm.sh update clients/$ADMIN_CLI_ID -r master -s 'defaultClientScopes=["web-origins","acr","roles","profile","basic","email","groups"]'
echo "Successfully added groups scope to admin-cli client"
fi

# Check if groups scope has protocol mapper
MAPPERS=$(/opt/keycloak/bin/kcadm.sh get client-scopes/$GROUPS_SCOPE_ID -r master --fields protocolMappers)

if echo "$MAPPERS" | grep -q "oidc-group-membership-mapper"; then
echo "groups scope already has protocol mapper"
else
echo "Adding protocol mapper to groups scope"
MAPPER_ID=$(/opt/keycloak/bin/kcadm.sh create client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models -r master -s name=groups -s protocol=openid-connect -s protocolMapper=oidc-group-membership-mapper -s consentRequired=false 2>&1 | grep "Created new model with id" | sed "s/.*Created new model with id '\([^']*\)'.*/\1/")

if [ -n "$MAPPER_ID" ]; then
echo "Created protocol mapper with ID: $MAPPER_ID"
/opt/keycloak/bin/kcadm.sh update client-scopes/$GROUPS_SCOPE_ID/protocol-mappers/models/$MAPPER_ID -r master -s 'config={"multivalued":"true","full.path":"false","id.token.claim":"true","access.token.claim":"true","claim.name":"groups","userinfo.token.claim":"true","jsonType.label":"String"}'
echo "Successfully configured groups protocol mapper"
else
echo "Failed to create protocol mapper"
exit 1
fi
fi

echo "Keycloak admin-cli configuration completed successfully"
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m" No newline at end of file

Check warning

Code scanning / Trivy

Restrict container images to trusted registries Medium

Artifact: argocd/applications/configs/keycloak-admin-cli-config-job.yaml
Type: kubernetes
Vulnerability KSV0125
Severity: MEDIUM
Message: Container keycloak-admin-cli-config in job keycloak-admin-cli-config (namespace: orch-platform) uses an image from an untrusted registry.
Link: KSV0125
- Enable service account for admin-cli client (required for client credentials flow)
- Set publicClient=false for service account authentication
- Disable directAccessGrantsEnabled for proper service account setup
- Add group creation and membership for service account user
- Ensure groups scope has proper protocol mapper configuration

This fixes authentication issues where the orch-library expects groups
claim in tokens but admin-cli service account had no group membership.
…ibility

The orch-library@v0.6.0 appears to expect admin-cli to use direct access
grants rather than service account authentication. Reverting to:
- directAccessGrantsEnabled: true
- serviceAccountsEnabled: false
- publicClient: true

This matches the pattern used by system-client which works successfully
in the codebase. The groups scope is still maintained for compatibility.
This client is required by orch-library@v0.6.1 authentication code.
The getClientIDTokenFromKeycloak function was failing with 'index out of
range [0]' because it couldn't find the edge-manager-m2m-client.

Configured as service account client with:
- serviceAccountsEnabled: true
- groups scope included
- client credentials authentication
- secret: edge-manager-secret

This should resolve the tenant-controller authentication panics.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant