diff --git a/argocd/applications/configs/app-deployment-manager.yaml b/argocd/applications/configs/app-deployment-manager.yaml index b20732eb1..d7173a531 100644 --- a/argocd/applications/configs/app-deployment-manager.yaml +++ b/argocd/applications/configs/app-deployment-manager.yaml @@ -31,7 +31,7 @@ adm: openidc: # -- the endpoint of a Keycloak Realm e.g. http://keycloak/realms/master - issuer: "http://platform-keycloak.orch-platform.svc/realms/master" + issuer: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" insecureSkipVerify: false gitea: diff --git a/argocd/applications/configs/app-orch-catalog.yaml b/argocd/applications/configs/app-orch-catalog.yaml index 53082941d..a7e1927a1 100644 --- a/argocd/applications/configs/app-orch-catalog.yaml +++ b/argocd/applications/configs/app-orch-catalog.yaml @@ -14,7 +14,7 @@ traefikReverseProxy: enabled: true secretName: tls-orch ## must be created in orch-gateway namespace openidc: - issuer: http://platform-keycloak.orch-platform.svc/realms/master + issuer: http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master storage: size: 1Gi postgres: diff --git a/argocd/applications/configs/infra-core.yaml b/argocd/applications/configs/infra-core.yaml index 3a309cdfa..cd46fccea 100644 --- a/argocd/applications/configs/infra-core.yaml +++ b/argocd/applications/configs/infra-core.yaml @@ -15,7 +15,7 @@ credentials: serviceAccount: name: "orch-svc" params: - keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" + keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" vaultUrl: "http://vault.orch-platform.svc.cluster.local:8200" api: @@ -31,7 +31,7 @@ api: oidc: name: "keycloak-api" oidc_env_name: "OIDC_SERVER_URL" - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" oidc_tls_insecure_skip_verify_env_name: "OIDC_TLS_INSECURE_SKIP_VERIFY" oidc_tls_insecure_skip_verify_value: "true" multiTenancy: @@ -56,7 +56,7 @@ apiv2: oidc: name: "keycloak-api" oidc_env_name: "OIDC_SERVER_URL" - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" oidc_tls_insecure_skip_verify_env_name: "OIDC_TLS_INSECURE_SKIP_VERIFY" oidc_tls_insecure_skip_verify_value: "true" resources: null @@ -80,7 +80,7 @@ tenant-controller: inventoryAddress: "inventory.orch-infra.svc.cluster.local:50051" traceURL: "orchestrator-observability-opentelemetry-collector.orch-platform.svc:4318" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" resources: null serviceAccount: name: "orch-svc" diff --git a/argocd/applications/configs/infra-external.yaml b/argocd/applications/configs/infra-external.yaml index edbb496e6..0325a766f 100644 --- a/argocd/applications/configs/infra-external.yaml +++ b/argocd/applications/configs/infra-external.yaml @@ -19,7 +19,7 @@ loca-manager: env: vaultUrl: "http://vault.orch-platform.svc.cluster.local:8200" vaultRole: "orch-svc" - keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" + keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" loca-metadata-manager: serviceAccount: @@ -78,7 +78,7 @@ loca-credentials: serviceAccount: name: "orch-svc" params: - keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" + keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" vaultUrl: "http://vault.orch-platform.svc.cluster.local:8200" amt: @@ -111,6 +111,6 @@ amt: password: "" env: oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" oidc_tls_insecure_skip_verify_value: "true" diff --git a/argocd/applications/configs/infra-managers.yaml b/argocd/applications/configs/infra-managers.yaml index e805a82da..40fa7753b 100644 --- a/argocd/applications/configs/infra-managers.yaml +++ b/argocd/applications/configs/infra-managers.yaml @@ -17,7 +17,7 @@ host-manager: secretName: "tls-orch" tlsOption: "gateway-tls" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" multiTenancy: enforceMultiTenancy: "true" resources: null @@ -34,7 +34,7 @@ maintenance-manager: secretName: "tls-orch" tlsOption: "gateway-tls" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" telemetryMgrArgs: enableVal: false # disable telemetry profile validation multiTenancy: @@ -62,7 +62,7 @@ telemetry-manager: secretName: "tls-orch" tlsOption: "gateway-tls" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" multiTenancy: enforceMultiTenancy: "true" resources: null @@ -79,7 +79,7 @@ os-resource-manager: image: pullPolicy: IfNotPresent oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local/realms/master" autoProvision: enabled: false # autoprovisioning disabled by default, can be enabled by enable-autoprovision profile multiTenancy: @@ -98,7 +98,7 @@ attestationstatus-manager: secretName: "tls-orch" tlsOption: "gateway-tls" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" multiTenancy: enforceMultiTenancy: "true" resources: null diff --git a/argocd/applications/configs/infra-onboarding.yaml b/argocd/applications/configs/infra-onboarding.yaml index 832692054..3341c0f30 100644 --- a/argocd/applications/configs/infra-onboarding.yaml +++ b/argocd/applications/configs/infra-onboarding.yaml @@ -29,16 +29,17 @@ onboarding-manager: tlsOption: "gateway-tls" gatewayNamespace: orch-gateway env: + mode: "prod" # Override dev profile to use prod mode since latest-dev manifest doesn't exist tinkerActionsVersion: "1.19.3" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" # Skip AuthZ for CDN-boots clients: bypass: - cdn-boots vaultUrl: "http://vault.orch-platform.svc.cluster.local:8200" vaultRole: "orch-svc" - keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" + keycloakUrl: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" multiTenancy: enforceMultiTenancy: true resources: null @@ -49,9 +50,10 @@ dkam: managerArgs: traceURL: "orchestrator-observability-opentelemetry-collector.orch-platform.svc:4318" env: + mode: "prod" # Override dev profile to use prod mode since latest-dev manifest doesn't exist rs_proxy_address: "rs-proxy.orch-platform.svc.cluster.local:8081/" oidc: - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" resources: null infra-config: diff --git a/argocd/applications/configs/keycloak-admin-cli-config-job.yaml b/argocd/applications/configs/keycloak-admin-cli-config-job.yaml new file mode 100644 index 000000000..e273ffa07 --- /dev/null +++ b/argocd/applications/configs/keycloak-admin-cli-config-job.yaml @@ -0,0 +1,145 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: batch/v1 +kind: Job +metadata: + name: keycloak-admin-cli-config + namespace: orch-platform + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-weight: "2" + helm.sh/hook-delete-policy: hook-succeeded + # Security annotations for image registry approval + security.approved-registries: "quay.io" + security.image-purpose: "keycloak-config-cli for admin-cli client configuration" + security.image-vendor: "adorsys/keycloak-config-cli" + security.image-verification: "official-keycloak-tooling" +spec: + template: + metadata: + labels: + app: keycloak-admin-cli-config + sidecar.istio.io/inject: "false" + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: "RuntimeDefault" + containers: + - 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 diff --git a/argocd/applications/configs/keycloak-system-client-setup-job.yaml b/argocd/applications/configs/keycloak-system-client-setup-job.yaml new file mode 100644 index 000000000..49267f986 --- /dev/null +++ b/argocd/applications/configs/keycloak-system-client-setup-job.yaml @@ -0,0 +1,174 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: batch/v1 +kind: Job +metadata: + name: keycloak-system-client-setup + namespace: orch-platform + annotations: + # Security annotations for image registry approval + security.approved-registries: "docker.io" + security.image-purpose: "system-client setup for Keycloak tenant controller" + security.image-vendor: "badouralix/curl-jq" + security.image-verification: "community-maintained-tool" +spec: + # Allow the job to run multiple times during upgrades + completions: 1 + parallelism: 1 + backoffLimit: 3 + template: + metadata: + labels: + app: keycloak-system-client-setup + sidecar.istio.io/inject: "false" + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: "RuntimeDefault" + containers: + - 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 + - | + set -e + echo "=== System Client Setup Job ===" + echo "Keycloak URL: $KEYCLOAK_URL" + echo "Admin User: $ADMIN_USER" + + # Wait for Keycloak to be ready + echo "Waiting for Keycloak to be ready..." + i=0 + while [ $i -lt 30 ]; do + if curl -s -f "$KEYCLOAK_URL/realms/master/.well-known/openid_configuration" >/dev/null 2>&1; then + echo "✓ Keycloak is ready" + break + fi + echo "Waiting for Keycloak... ($i/30)" + sleep 10 + i=$((i + 1)) + done + + # URL encode password (handle & character) + ENCODED_PASSWORD=$(echo "$ADMIN_PASSWORD" | sed 's/&/%26/g') + + # Get admin token + echo "Getting admin token..." + ADMIN_TOKEN=$(curl -s -X POST "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password&client_id=admin-cli&username=$ADMIN_USER&password=$ENCODED_PASSWORD" \ + | jq -r ".access_token // \"null\"") + + if [ "$ADMIN_TOKEN" = "null" ]; then + echo "❌ Failed to get admin token" + exit 1 + fi + echo "✓ Got admin token" + + # Check if system-client already exists + EXISTING_CLIENT=$(curl -s "$KEYCLOAK_URL/admin/realms/master/clients?clientId=system-client" \ + -H "Authorization: Bearer $ADMIN_TOKEN") + + if echo "$EXISTING_CLIENT" | jq -e '.[0]' >/dev/null 2>&1; then + echo "✓ system-client already exists" + SYSTEM_CLIENT_ID=$(echo "$EXISTING_CLIENT" | jq -r '.[0].id') + else + echo "Creating system-client..." + curl -s -X POST "$KEYCLOAK_URL/admin/realms/master/clients" \ + -H "Authorization: Bearer $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "clientId": "system-client", + "name": "System Client for KTC", + "enabled": true, + "publicClient": true, + "directAccessGrantsEnabled": true, + "protocol": "openid-connect", + "defaultClientScopes": ["web-origins", "acr", "roles", "profile", "basic", "email"] + }' + + SYSTEM_CLIENT_ID=$(curl -s "$KEYCLOAK_URL/admin/realms/master/clients?clientId=system-client" \ + -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[0].id') + echo "✓ system-client created with ID: $SYSTEM_CLIENT_ID" + fi + + # Get or create groups scope + GROUPS_SCOPE_ID=$(curl -s "$KEYCLOAK_URL/admin/realms/master/client-scopes" \ + -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[] | select(.name == "groups") | .id') + + if [ -z "$GROUPS_SCOPE_ID" ] || [ "$GROUPS_SCOPE_ID" = "null" ]; then + echo "Creating groups scope..." + curl -s -X POST "$KEYCLOAK_URL/admin/realms/master/client-scopes" \ + -H "Authorization: Bearer $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "groups", + "description": "Groups scope for backward compatibility", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + }' + + GROUPS_SCOPE_ID=$(curl -s "$KEYCLOAK_URL/admin/realms/master/client-scopes" \ + -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[] | select(.name == "groups") | .id') + fi + + echo "✓ Groups scope ID: $GROUPS_SCOPE_ID" + + # Add groups scope to system-client + echo "Adding groups scope to system-client..." + curl -s -X PUT \ + "$KEYCLOAK_URL/admin/realms/master/clients/$SYSTEM_CLIENT_ID/default-client-scopes/$GROUPS_SCOPE_ID" \ + -H "Authorization: Bearer $ADMIN_TOKEN" + + # Test authentication with URL-encoded password + echo "Testing system-client authentication..." + AUTH_RESULT=$(curl -s -X POST "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password&client_id=system-client&username=$ADMIN_USER&password=$ENCODED_PASSWORD&scope=openid profile email groups") + + TOKEN=$(echo "$AUTH_RESULT" | jq -r ".access_token // \"null\"") + + if [ "$TOKEN" != "null" ]; then + echo "✅ SUCCESS: system-client authentication works with groups scope!" + echo "Setup complete - system-client is ready for keycloak-tenant-controller" + else + echo "❌ FAILED: Authentication test failed" + echo "Response: $AUTH_RESULT" + exit 1 + fi \ No newline at end of file diff --git a/argocd/applications/configs/metadata-broker.yaml b/argocd/applications/configs/metadata-broker.yaml index e83c27016..ba1637156 100644 --- a/argocd/applications/configs/metadata-broker.yaml +++ b/argocd/applications/configs/metadata-broker.yaml @@ -5,7 +5,7 @@ # Intentionally blank. There are no base settings overrides. openidc: - issuer: http://platform-keycloak.orch-platform.svc/realms/master + issuer: http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master service: traefik: diff --git a/argocd/applications/configs/nexus-api-gw.yaml b/argocd/applications/configs/nexus-api-gw.yaml index d4d851351..c17cf7b9a 100644 --- a/argocd/applications/configs/nexus-api-gw.yaml +++ b/argocd/applications/configs/nexus-api-gw.yaml @@ -16,6 +16,6 @@ oidc: name: "keycloak-api" oidc_env_name: "OIDC_SERVER_URL" # TODO: Use `platform-keycloak.orch-platform.svc.cluster.local` to avoid possible DNS search domain problems. - oidc_server_url: "http://platform-keycloak.orch-platform.svc/realms/master" + oidc_server_url: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" oidc_tls_insecure_skip_verify_env_name: "OIDC_TLS_INSECURE_SKIP_VERIFY" oidc_tls_insecure_skip_verify_value: "true" diff --git a/argocd/applications/configs/platform-keycloak-compat-service.yaml b/argocd/applications/configs/platform-keycloak-compat-service.yaml new file mode 100644 index 000000000..5e97b1395 --- /dev/null +++ b/argocd/applications/configs/platform-keycloak-compat-service.yaml @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# Backward-compatible service for platform-keycloak +# This service ensures existing references to platform-keycloak.orch-platform.svc +# continue to work after migrating to the codecentric keycloakx chart + +apiVersion: v1 +kind: Service +metadata: + name: platform-keycloak + namespace: orch-platform + labels: + app.kubernetes.io/component: http + app.kubernetes.io/instance: platform-keycloak + app.kubernetes.io/name: keycloakx + argocd.argoproj.io/managed-by: platform-keycloak-compat + annotations: + argocd.argoproj.io/sync-wave: "151" +spec: + type: ClusterIP + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/instance: platform-keycloak + app.kubernetes.io/name: keycloakx \ No newline at end of file diff --git a/argocd/applications/configs/platform-keycloak-config-job.yaml b/argocd/applications/configs/platform-keycloak-config-job.yaml new file mode 100644 index 000000000..1264b031f --- /dev/null +++ b/argocd/applications/configs/platform-keycloak-config-job.yaml @@ -0,0 +1,93 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: batch/v1 +kind: Job +metadata: + name: platform-keycloak-config-import + namespace: orch-platform + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: hook-succeeded + # Security annotations for image registry approval + security.approved-registries: "quay.io" + security.image-purpose: "keycloak-config-cli for realm configuration import" + security.image-vendor: "adorsys/keycloak-config-cli" + security.image-verification: "official-keycloak-tooling" +spec: + template: + metadata: + labels: + app: keycloak-config-import + sidecar.istio.io/inject: "false" + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: "RuntimeDefault" + containers: + - 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" + volumes: + - name: keycloak-config + configMap: + name: platform-keycloak-config + - name: tmp-volume + emptyDir: {} + - name: var-tmp-volume + emptyDir: {} diff --git a/argocd/applications/configs/platform-keycloak-realm-config.yaml b/argocd/applications/configs/platform-keycloak-realm-config.yaml new file mode 100644 index 000000000..489b292ce --- /dev/null +++ b/argocd/applications/configs/platform-keycloak-realm-config.yaml @@ -0,0 +1,451 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: v1 +kind: ConfigMap +metadata: + name: platform-keycloak-config + namespace: orch-platform +data: + realm-master.json: | + { + "realm": "master", + "accountTheme": "keycloak", + "displayName": "Keycloak", + "displayNameHtml": "", + "defaultSignatureAlgorithm": "PS512", + "accessTokenLifespan": 3600, + "ssoSessionIdleTimeout": 5400, + "ssoSessionMaxLifespan": 43200, + "passwordPolicy": "length(14) and digits(1) and specialChars(1) and upperCase(1) and lowerCase(1)", + "bruteForceProtected": true, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 300, + "quickLoginCheckMilliSeconds": 200, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 5, + "roles": { + "realm": [ + { + "name": "en-agent-rw" + }, + { + "name": "secrets-root-role" + }, + { + "name": "rs-access-r" + }, + { + "name": "rs-proxy-r" + }, + { + "name": "app-service-proxy-read-role" + }, + { + "name": "app-service-proxy-write-role" + }, + { + "name": "app-deployment-manager-read-role" + }, + { + "name": "app-deployment-manager-write-role" + }, + { + "name": "app-resource-manager-read-role" + }, + { + "name": "app-resource-manager-write-role" + }, + { + "name": "app-vm-console-write-role" + }, + { + "name": "catalog-publisher-read-role" + }, + { + "name": "catalog-publisher-write-role" + }, + { + "name": "catalog-other-read-role" + }, + { + "name": "catalog-other-write-role" + }, + { + "name": "catalog-restricted-read-role" + }, + { + "name": "catalog-restricted-write-role" + }, + { + "name": "clusters-read-role" + }, + { + "name": "clusters-write-role" + }, + { + "name": "cluster-templates-read-role" + }, + { + "name": "cluster-templates-write-role" + }, + { + "name": "cluster-artifacts-read-role" + }, + { + "name": "cluster-artifacts-write-role" + }, + { + "name": "infra-manager-core-read-role" + }, + { + "name": "infra-manager-core-write-role" + }, + { + "name": "alrt-r" + }, + { + "name": "alrt-rw" + }, + { + "name": "alrt-rx-rw" + }, + { + "name": "ao-m2m-rw" + }, + { + "name": "co-m2m-rw" + }, + { + "name": "org-read-role" + }, + { + "name": "org-write-role" + }, + { + "name": "org-update-role" + }, + { + "name": "org-delete-role" + } + ], + "client": { + "alerts-m2m-client": [], + "host-manager-m2m-client": [], + "ktc-m2m-client": [], + "3rd-party-host-manager-m2m-client": [], + "edge-manager-m2m-client": [], + "en-m2m-template-client": [], + "webui-client": [], + "docsui-client": [], + "account": [ + { + "name": "view-profile", + "clientRole": true + }, + { + "name": "manage-account", + "clientRole": true + } + ], + "telemetry-client": [ + { + "name": "admin", + "clientRole": true + }, + { + "name": "viewer", + "clientRole": true + } + ], + "cluster-management-client": [ + { + "name": "restricted-role", + "clientRole": true + }, + { + "name": "standard-role", + "clientRole": true + }, + { + "name": "base-role", + "clientRole": true + } + ], + "registry-client": [ + { + "name": "registry-admin-role", + "clientRole": true + }, + { + "name": "registry-editor-role", + "clientRole": true + }, + { + "name": "registry-viewer-role", + "clientRole": true + } + ] + } + }, + "clients": [ + { + "clientId": "alerts-m2m-client", + "name": "Alerts M2M Client", + "description": "Client for Alerts", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "fullScopeAllowed": true, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email", + "basic" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "system-client", + "name": "System Client", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "oauth2.device.authorization.grant.enabled": "true", + "backchannel.logout.session.required": "true", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "fullScopeAllowed": true, + "defaultClientScopes": [ + "roles", + "profile", + "email", + "basic", + "groups" + ], + "optionalClientScopes": [ + "groups", + "offline_access" + ] + }, + { + "clientId": "admin-cli", + "name": "Admin CLI", + "description": "Admin CLI client with groups scope for compatibility", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email", + "groups" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "clientId": "edge-manager-m2m-client", + "name": "Edge Manager M2M Client", + "description": "Machine-to-machine client for edge manager services", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "edge-manager-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "client.secret.creation.time": "1698847200", + "oauth2.device.authorization.grant.enabled": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email", + "groups" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "name": "groups", + "description": "Groups scope", + "type": "Optional", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "full.path": "false", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "userinfo.token.claim": "true", + "jsonType.label": "String" + } + } + ] + } + ], + "groups": [ + { + "name": "apps-m2m-service-account", + "path": "/apps-m2m-service-account", + "realmRoles": [ + "ao-m2m-rw", + "co-m2m-rw" + ] + }, + { + "name": "edge-manager-group", + "path": "/edge-manager-group", + "realmRoles": [ + "app-service-proxy-read-role", + "app-service-proxy-write-role", + "app-deployment-manager-read-role", + "app-deployment-manager-write-role" + ] + } + ], + "users": [ + { + "username": "service-account-alerts-m2m-client", + "enabled": true, + "totp": false, + "serviceAccountClientId": "alerts-m2m-client", + "realmRoles": [ + "default-roles-master" + ], + "clientRoles": { + "alerts-m2m-client": [ + "uma_protection" + ] + }, + "notBefore": 0 + } + ], + "components": { + "org.keycloak.keys.KeyProvider": [ + { + "name": "fallback-PS512", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "keySize": [ + "4096" + ], + "active": [ + "true" + ], + "priority": [ + "-100" + ], + "enabled": [ + "true" + ], + "algorithm": [ + "PS512" + ] + } + } + ] + } + } diff --git a/argocd/applications/configs/platform-keycloak.yaml b/argocd/applications/configs/platform-keycloak.yaml index 311baa55d..48a3d5433 100644 --- a/argocd/applications/configs/platform-keycloak.yaml +++ b/argocd/applications/configs/platform-keycloak.yaml @@ -2,1216 +2,159 @@ # # SPDX-License-Identifier: Apache-2.0 -global: - security: - allowInsecureImages: true +# Keycloak Configuration - CodeCentric Chart +# Modular configuration for production deployment + +################################# +# IDENTITY & NAMING +################################# +## Ensure service name compatibility with existing consumers +fullnameOverride: "platform-keycloak" + +################################# +# CONTAINER & IMAGE +################################# image: - registry: docker.io - repository: bitnamilegacy/keycloak - tag: 26.1.3-debian-12-r0 + repository: quay.io/keycloak/keycloak + tag: "26.0.7" pullPolicy: IfNotPresent -containerSecurityContext: +################################# +# SECURITY CONFIGURATION +################################# +securityContext: + runAsNonRoot: true + runAsUser: 1000 allowPrivilegeEscalation: false capabilities: drop: ["ALL"] seccompProfile: type: "RuntimeDefault" -# disable network policy to avoid intermittent dns issues -networkPolicy: - enabled: false +podSecurityContext: + fsGroup: 1000 -## PostgreSQL chart configuration -## ref: https://github.com/bitnami/charts/blob/main/bitnami/postgresql/values.yaml -## @param postgresql.enabled Switch to enable or disable the PostgreSQL helm chart -postgresql: - enabled: false +podLabels: + sidecar.istio.io/inject: "false" -## Service configuration -## +################################# +# NETWORK & SERVICE +################################# service: - ## @param service.type Kubernetes service type, default: LoadBalancer - ## + metadata: + name: platform-keycloak type: ClusterIP - ports: - http: 8080 - -## Keycloak authentication parameters -## ref: https://github.com/bitnami/containers/tree/main/bitnami/keycloak#admin-credentials -## -auth: - ## @param auth.adminUser Keycloak administrator user - ## - adminUser: admin - ## @param auth.adminPassword Keycloak administrator password for the new user - ## - adminPassword: "" + httpPort: 8080 - passwordSecretKey: admin-password - existingSecret: platform-keycloak +networkPolicy: + enabled: false -## Adds argument for enabling legacy logout redirect -## This is needed for the Grafana client integration which does not currently support the new way keycloak does single sign-out. -## Keycloak mentions that this legacy feature will be removed in Keycloak 23.0. -extraStartupArgs: >- - --spi-login-protocol-openid-connect-legacy-logout-redirect-uri=true - --spi-brute-force-protector-default-brute-force-detector-allow-concurrent-requests=true +################################# +# KEYCLOAK CONFIGURATION +################################# +## Startup configuration +command: + - "/opt/keycloak/bin/kc.sh" -## Configuration for keycloak-config-cli -## ref: https://github.com/adorsys/keycloak-config-cli -## -keycloakConfigCli: - image: - pullPolicy: IfNotPresent - registry: docker.io - repository: bitnamilegacy/keycloak-config-cli - tag: 6.4.0-debian-12-r0 +args: + - "start" + - "--spi-login-protocol-openid-connect-legacy-logout-redirect-uri=true" + - "--spi-brute-force-protector-default-brute-force-detector-allow-concurrent-requests=true" - ## @param keycloakConfigCli.enabled Whether to enable keycloak-config-cli job - ## - enabled: true - args: - - --import.managed.group="no-delete" - - --import.managed.required-action="no-delete" - - --import.managed.role="no-delete" - - --import.managed.client="no-delete" +## Environment variables for Keycloak configuration +extraEnv: | + - name: JAVA_OPTS_APPEND + value: >- + -Djgroups.dns.query=platform-keycloak-headless.orch-platform.svc.cluster.local + - name: KC_HTTP_RELATIVE_PATH + value: "/" + - name: KC_CACHE + value: "ispn" + - name: KC_CACHE_STACK + value: "kubernetes" + # Admin credentials + - name: KC_BOOTSTRAP_ADMIN_USERNAME + value: "admin" + - name: KC_BOOTSTRAP_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: platform-keycloak + key: admin-password + # HTTP/HTTPS configuration + - name: KC_HOSTNAME_STRICT + value: "false" + # HTTP/HTTPS configuration + - name: KC_HOSTNAME_STRICT_HTTPS + value: "false" + - name: KC_HTTP_ENABLED + value: "true" + - name: KC_PROXY + value: "passthrough" + # Feature enablement + - name: KC_HEALTH_ENABLED + value: "true" + - name: KC_METRICS_ENABLED + value: "true" + # Database username from secret (password is handled by database: section) + - name: KC_DB_USERNAME + valueFrom: + secretKeyRef: + name: platform-keycloak-local-postgresql + key: PGUSER + # Proxy configuration + - name: HTTPS_PROXY + value: "http://proxy-dmz.intel.com:912" + - name: HTTP_PROXY + value: "http://proxy-dmz.intel.com:912" + - name: NO_PROXY + value: "localhost,svc,cluster.local,default,internal,caas.intel.com,certificates.intel.com,localhost,127.0.0.0/8,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12,169.254.169.254,orch-platform,orch-app,orch-cluster,orch-infra,orch-database,cattle-system,orch-secret,s3.amazonaws.com,s3.us-west-2.amazonaws.com,ec2.us-west-2.amazonaws.com,eks.amazonaws.com,elb.us-west-2.amazonaws.com,dkr.ecr.us-west-2.amazonaws.com,espd.infra-host.com,pid.infra-host.com,espdqa.infra-host.com,argocd-repo-server" - ## @param keycloakConfigCli.annotations [object] Annotations for keycloak-config-cli job - ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ - ## - annotations: - helm.sh/hook: "post-install" - helm.sh/hook-delete-policy: "hook-succeeded" +################################# +# DATABASE CONFIGURATION +################################# +database: + vendor: postgres + hostname: postgresql.orch-database.svc.cluster.local + port: 5432 + database: orch-platform-platform-keycloak + existingSecret: platform-keycloak-local-postgresql + existingSecretKey: PGPASSWORD - ## do not inject sidecar to pods for job - podLabels: - sidecar.istio.io/inject: "false" - - ## @param keycloakConfigCli.configuration keycloak-config-cli realms configuration - ## NOTE: nil keys will be considered files to import locally - ## Example: - ## configuration: - ## realm1.json: | - ## { - ## "realm": "realm1", - ## "clients": [] - ## } - ## files/realm2.yaml: - ## realm3.yaml: | - ## realm: realm3 - ## clients: [] - ## +dbchecker: + enabled: true + securityContext: + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL - # yamllint disable rule:line-length - configuration: - realm-master.json: | - { - "realm": "master", - "accountTheme": "keycloak", - "displayName": "Keycloak", - "displayNameHtml": "", - "defaultSignatureAlgorithm": "PS512", - "accessTokenLifespan": 3600, - "ssoSessionIdleTimeout": 5400, - "ssoSessionMaxLifespan": 43200, - "passwordPolicy": "length(14) and digits(1) and specialChars(1) and upperCase(1) and lowerCase(1)", - "bruteForceProtected": true, - "permanentLockout": false, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 300, - "quickLoginCheckMilliSeconds": 200, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 5, - "roles": { - "realm": [ - { - "name": "en-agent-rw" - }, - { - "name": "secrets-root-role" - }, - { - "name": "rs-access-r" - }, - { - "name": "rs-proxy-r" - }, - { - "name": "app-service-proxy-read-role" - }, - { - "name": "app-service-proxy-write-role" - }, - { - "name": "app-deployment-manager-read-role" - }, - { - "name": "app-deployment-manager-write-role" - }, - { - "name": "app-resource-manager-read-role" - }, - { - "name": "app-resource-manager-write-role" - }, - { - "name": "app-vm-console-write-role" - }, - { - "name": "catalog-publisher-read-role" - }, - { - "name": "catalog-publisher-write-role" - }, - { - "name": "catalog-other-read-role" - }, - { - "name": "catalog-other-write-role" - }, - { - "name": "catalog-restricted-read-role" - }, - { - "name": "catalog-restricted-write-role" - }, - { - "name": "clusters-read-role" - }, - { - "name": "clusters-write-role" - }, - { - "name": "cluster-templates-read-role" - }, - { - "name": "cluster-templates-write-role" - }, - { - "name": "cluster-artifacts-read-role" - }, - { - "name": "cluster-artifacts-write-role" - }, - { - "name": "infra-manager-core-read-role" - }, - { - "name": "infra-manager-core-write-role" - }, - { - "name": "alrt-r" - }, - { - "name": "alrt-rw" - }, - { - "name": "alrt-rx-rw" - }, - { - "name": "ao-m2m-rw" - }, - { - "name": "co-m2m-rw" - }, - { - "name": "org-read-role" - }, - { - "name": "org-write-role" - }, - { - "name": "org-update-role" - }, - { - "name": "org-delete-role" - } - ], - "client": { - "alerts-m2m-client": [], - "host-manager-m2m-client": [], - "ktc-m2m-client": [], - "3rd-party-host-manager-m2m-client": [], - "edge-manager-m2m-client": [], - "en-m2m-template-client": [], - "webui-client": [], - "docsui-client": [], - "account": [ - { - "name": "view-profile", - "clientRole": true - }, - { - "name": "manage-account", - "clientRole": true - } - ], - "telemetry-client": [ - { - "name": "admin", - "clientRole": true - }, - { - "name": "viewer", - "clientRole": true - } - ], - "cluster-management-client": [ - { - "name": "restricted-role", - "clientRole": true - }, - { - "name": "standard-role", - "clientRole": true - }, - { - "name": "base-role", - "clientRole": true - } - ], - "registry-client": [ - { - "name": "registry-admin-role", - "clientRole": true - }, - { - "name": "registry-editor-role", - "clientRole": true - }, - { - "name": "registry-viewer-role", - "clientRole": true - } - ] - } - }, - "clients": [ - { - "clientId": "alerts-m2m-client", - "name": "Alerts M2M Client", - "description": "Client for Alerts", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email", - "basic" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "clientId": "host-manager-m2m-client", - "name": "Host Manager Client", - "description": "Client for the EN Host Manager to use in creating edgenode m2m clients", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email", - "basic" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "clientId": "ktc-m2m-client", - "name": "Keycloak Tenant Controller client", - "description": "Client for the Keycloak Tenant Controller to use in creating Tenant specific roles and groups in Keycloak", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "groups", - "email", - "basic" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "clientId": "3rd-party-host-manager-m2m-client", - "name": "3rd Party Host Manager Client", - "description": "Client for the 3rd party Host Manager to use in creating edgenode m2m clients", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email", - "basic" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "clientId": "edge-manager-m2m-client", - "name": "Edge Manager M2M Client", - "description": "Client for the accessing Orchestrator with Edge-Manager persona", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "roles", - "email", - "groups", - "basic" - ], - "optionalClientScopes": [ - "offline_access", - ] - }, - { - "clientId": "en-m2m-template-client", - "name": "Edge Node M2M Template Client", - "description": "Client to use as basis for Roles to assign to new Edge Node M2M clients", - "surrogateAuthRequired": false, - "enabled": false, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email", - "basic" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "clientId": "telemetry-client", - "name": "Telemetry Client", - "rootUrl": {{ .Values.clusterSpecific.telemetryClientRootUrl | toJson }}, - "enabled": true, - "clientAuthenticatorType": "client-secret", - "redirectUris": {{ .Values.clusterSpecific.telemetryRedirectUrls | toJson }}, - "webOrigins": [ - "+" - ], - "protocol": "openid-connect", - "directAccessGrantsEnabled": true, - "attributes": { - "oidc.ciba.grant.enabled": "false", - "client.secret.creation.time": "1683218404", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "+", - "display.on.consent.screen": "false", - "use.jwks.url": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "roles", - "profile", - "email", - "basic" - ], - "optionalClientScopes": [ - "groups", - "offline_access" - ] - }, - { - "clientId": "cluster-management-client", - "name": "Cluster Management Client", - "rootUrl": {{ .Values.clusterSpecific.clusterManagementClientRootUrl | toJson }}, - "adminUrl": {{ .Values.clusterSpecific.clusterManagementClientRootUrl | toJson }}, - "surrogateAuthRequired": false, - "enabled": true, - "clientAuthenticatorType": "client-secret", - "redirectUris": {{ .Values.clusterSpecific.clusterManagementRedirectUrls | toJson }}, - "webOrigins": [ - "+" - ], - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "tls.client.certificate.bound.access.tokens": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - }, - "fullScopeAllowed": true, - "protocolMappers": [ - { - "name": "Group Path", - "protocol": "openid-connect", - "protocolMapper": "oidc-group-membership-mapper", - "consentRequired": false, - "config": { - "full.path": "true", - "id.token.claim": "false", - "access.token.claim": "false", - "claim.name": "full_group_path", - "userinfo.token.claim": "true" - } - }, - { - "name": "Groups Mapper", - "protocol": "openid-connect", - "protocolMapper": "oidc-group-membership-mapper", - "consentRequired": false, - "config": { - "full.path": "false", - "id.token.claim": "false", - "access.token.claim": "false", - "claim.name": "groups", - "userinfo.token.claim": "true" - } - }, - { - "name": "Client Audience", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-mapper", - "consentRequired": false, - "config": { - "included.client.audience": "cluster-management-client", - "id.token.claim": "false", - "access.token.claim": "true" - } - } - ], - "defaultClientScopes": [ - "profile", - "roles", - "email", - "basic" - ], - "optionalClientScopes": [ - "groups", - "offline_access", - ], - "authorizationServicesEnabled": false - }, - { - "clientId": "webui-client", - "name": "WebUI Client", - "rootUrl": {{ .Values.clusterSpecific.webuiClientRootUrl | toJson }}, - "enabled": true, - "clientAuthenticatorType": "client-secret", - "redirectUris": {{ .Values.clusterSpecific.webuiRedirectUrls | toJson }}, - "webOrigins": [ - "+" - ], - "protocol": "openid-connect", - "directAccessGrantsEnabled": false, - "attributes": { - "oidc.ciba.grant.enabled": "false", - "client.secret.creation.time": "1683218404", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "+", - "display.on.consent.screen": "false", - "oauth2.device.authorization.grant.enabled": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "roles", - "profile", - "email", - "basic" - ], - "optionalClientScopes": [ - "groups", - "offline_access" - ] - }, - { - "clientId": "docsui-client", - "name": "DocsUI Client", - "rootUrl": {{ .Values.clusterSpecific.docsuiClientRootUrl | toJson }}, - "enabled": true, - "clientAuthenticatorType": "client-secret", - "redirectUris": {{ .Values.clusterSpecific.docsuiRedirectUrls | toJson }}, - "webOrigins": [ - "+" - ], - "protocol": "openid-connect", - "directAccessGrantsEnabled": false, - "attributes": { - "oidc.ciba.grant.enabled": "false", - "client.secret.creation.time": "1683218404", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "+", - "display.on.consent.screen": "false", - "oauth2.device.authorization.grant.enabled": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "roles", - "profile", - "email", - "basic" - ], - "optionalClientScopes": [ - "groups", - "offline_access" - ] - }, - { - "clientId": "system-client", - "name": "System Client", - "surrogateAuthRequired": false, - "enabled": true, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "true", - "backchannel.logout.session.required": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "roles", - "profile", - "email", - "basic" - ], - "optionalClientScopes": [ - "groups", - "offline_access" - ] - }, - { - "frontchannelLogout": true, - "standardFlowEnabled": true, - "clientId": "registry-client", - "name": "Registry Client", - "rootUrl": {{ .Values.clusterSpecific.registryClientRootUrl | toJson }}, - "enabled": true, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/c/oidc/callback" - ], - "webOrigins": [ - "+" - ], - "protocol": "openid-connect", - "directAccessGrantsEnabled": true, - "attributes": { - "oidc.ciba.grant.enabled": "false", - "client.secret.creation.time": "1683218404", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "+", - "display.on.consent.screen": "false", - "use.jwks.url": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "fullScopeAllowed": true, - "defaultClientScopes": [ - "roles", - "profile", - "email", - "groups", - "basic" - ], - "optionalClientScopes": [ - "offline_access" - ] - } - ], - "clientScopes": [ - { - "name": "groups", - "description": "Groups scope", - "type": "Optional", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-group-membership-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "full.path": "false", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "userinfo.token.claim": "true", - "jsonType.label": "String" - } - } - ] - }, - { - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "gui.order": "", - "consent.screen.text": '{{"$"}}{{"{"}}roleScopeConsentText{{"}"}}' - }, - "protocolMappers": [ - { - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String" - } - }, - { - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "resource_access.{{"$"}}{{"{"}}client_id{{"}"}}.roles", - "jsonType.label": "String" - } - } - ] - } - ], - "groups": [ - { - "name": "registry-app-admin-group", - "path": "/registry-app-admin-group", - }, - { - "name": "registry-app-editor-group", - "path": "/registry-app-editor-group", - }, - { - "name": "registry-app-viewer-group", - "path": "/registry-app-viewer-group", - }, - { - "name": "apps-m2m-service-account", - "path": "/apps-m2m-service-account", - "realmRoles": [ - "ao-m2m-rw", - "co-m2m-rw" - ] - }, - { - "name": "org-admin-group", - "path": "/org-admin-group", - "realmRoles": [ - "org-read-role", - "org-update-role", - "org-delete-role", - "org-write-role" - ] - }, - { - "name": "sre-admin-group", - "path": "/sre-admin-group", - "realmRoles": [ - "alrt-r" - ], - "clientRoles": { - "account": [ - "view-profile", - "manage-account" - ], - "telemetry-client": [ - "viewer" - ] - } - }, - { - "name": "iam-admin-group", - "path": "/iam-admin-group", - "realmRoles": [ - "admin", - "secrets-root-role" - ], - "clientRoles": { - "account": [ - "view-profile", - "manage-account" - ], - "master-realm": [ - "view-users", - "query-users", - "manage-clients" - ] - } - }, - { - "name": "service-admin-group", - "path": "/service-admin-group", - "realmRoles": [ - "alrt-rx-rw", - "rs-access-r", - "infra-manager-core-read-role", - "infra-manager-core-write-role", - "alrt-rw" - ], - "clientRoles": { - "account": [ - "view-profile", - "manage-account" - ], - "master-realm": [ - "view-users", - "query-users", - "manage-clients" - ], - "telemetry-client": [ - "admin" - ], - "cluster-management-client": [ - "restricted-role", - "standard-role", - "base-role" - ], - "registry-client": [ - "registry-admin-role" - ] - } - }, - { - "name": "edge-manager-group", - "path": "/edge-manager-group", - "realmRoles": [ - "app-service-proxy-read-role", - "app-service-proxy-write-role", - "app-deployment-manager-read-role", - "app-deployment-manager-write-role", - "app-resource-manager-read-role", - "app-resource-manager-write-role", - "app-vm-console-write-role", - "catalog-publisher-read-role", - "catalog-publisher-write-role", - "catalog-other-read-role", - "catalog-other-write-role", - "catalog-restricted-read-role", - "catalog-restricted-write-role", - "clusters-read-role", - "clusters-write-role", - "cluster-templates-read-role", - "cluster-templates-write-role", - "cluster-artifacts-read-role", - "cluster-artifacts-write-role", - "infra-manager-core-read-role", - "alrt-rw" - ], - "clientRoles": { - "telemetry-client": [ - "viewer" - ], - "cluster-management-client": [ - "standard-role", - "base-role" - ], - "registry-client": [ - "registry-editor-role" - ] - } - }, - { - "name": "edge-operator-group", - "path": "/edge-operator-group", - "realmRoles": [ - "app-service-proxy-read-role", - "app-service-proxy-write-role", - "app-deployment-manager-read-role", - "app-deployment-manager-write-role", - "app-resource-manager-read-role", - "app-resource-manager-write-role", - "app-vm-console-write-role", - "catalog-publisher-read-role", - "catalog-other-read-role", - "clusters-read-role", - "clusters-write-role", - "cluster-templates-read-role", - "cluster-artifacts-read-role", - "cluster-artifacts-write-role", - "infra-manager-core-read-role", - "alrt-r" - ], - "clientRoles": { - "telemetry-client": [ - "viewer" - ], - "registry-client": [ - "registry-viewer-role" - ] - } - }, - { - "name": "host-manager-group", - "path": "/host-manager-group", - "realmRoles": [ - "infra-manager-core-read-role", - "infra-manager-core-write-role" - ], - "clientRoles": { - "telemetry-client": [ - "viewer" - ] - } - }, - { - "name": "sre-group", - "path": "/sre-group", - "realmRoles": [ - "alrt-r", - "clusters-read-role", - "clusters-write-role", - "cluster-templates-read-role", - "infra-manager-core-read-role" - ], - "clientRoles": { - "telemetry-client": [ - "viewer" - ], - "cluster-management-client": [ - "base-role", - "restricted-role" - ] - } - } - ], - "users": [ - { - "username": "service-account-alerts-m2m-client", - "enabled": true, - "totp": false, - "serviceAccountClientId": "alerts-m2m-client", - "realmRoles": [ - "default-roles-master" - ], - "clientRoles": { - "alerts-m2m-client": [ - "uma_protection" - ], - "master-realm": [ - "view-users" - ] - }, - "notBefore": 0 - }, - { - "username": "service-account-host-manager-m2m-client", - "enabled": true, - "totp": false, - "serviceAccountClientId": "host-manager-m2m-client", - "realmRoles": [ - "default-roles-master", - "rs-access-r" - ], - "clientRoles": { - "host-manager-m2m-client": [ - "uma_protection" - ], - "master-realm": [ - "query-clients", - "manage-authorization", - "view-clients", - "view-users", - "create-client", - "manage-users", - "manage-clients", - "view-realm" - ] - }, - "notBefore": 0 - }, - { - "username": "service-account-ktc-m2m-client", - "enabled": true, - "totp": false, - "serviceAccountClientId": "ktc-m2m-client", - "realmRoles": [ - "admin", - "create-realm", - "default-roles-master", - "rs-access-r" - ], - "clientRoles": { - "ktc-m2m-client": [ - "uma_protection" - ], - "master-realm": [ - "query-clients", - "manage-authorization", - "view-clients", - "view-users", - "create-client", - "manage-users", - "manage-clients" - ] - }, - "notBefore": 0 - }, - { - "username": "service-account-3rd-party-host-manager-m2m-client", - "enabled": true, - "totp": false, - "serviceAccountClientId": "3rd-party-host-manager-m2m-client", - "realmRoles": [ - "default-roles-master", - "rs-access-r" - ], - "clientRoles": { - "3rd-party-host-manager-m2m-client": [ - "uma_protection" - ], - "master-realm": [ - "query-clients", - "manage-authorization", - "view-clients", - "view-users", - "create-client", - "manage-users", - "manage-clients", - "view-realm", - ] - }, - "notBefore": 0 - }, - { - "username": "service-account-en-m2m-template-client", - "enabled": true, - "totp": false, - "serviceAccountClientId": "en-m2m-template-client", - "realmRoles": [ - "default-roles-master", - "rs-access-r", - "en-agent-rw" - ], - "clientRoles": { - "en-m2m-template-client": [ - "uma_protection" - ] - }, - "notBefore": 0 - }, - { - "username": "service-account-edge-manager-m2m-client", - "enabled": true, - "totp": false, - "serviceAccountClientId": "edge-manager-m2m-client", - "realmRoles": [ - "default-roles-master" - ], - "clientRoles": { - "edge-manager-m2m-client": [ - "uma_protection" - ] - }, - "notBefore": 0, - "groups": [ - "/edge-manager-group", - "/apps-m2m-service-account" - ] - }, - ], - "components": { - "org.keycloak.keys.KeyProvider": [ - { - "name": "fallback-PS512", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "keySize": [ - "4096" - ], - "active": [ - "true" - ], - "priority": [ - "-100" - ], - "enabled": [ - "true" - ], - "algorithm": [ - "PS512" - ] - } - } - ] - } - } -# yamllint enable rule:line-length +################################# +# HEALTH & MONITORING +################################# +livenessProbe: | + httpGet: + path: / + port: http + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 +readinessProbe: | + httpGet: + path: /realms/master + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 +startupProbe: | + httpGet: + path: / + port: http + initialDelaySeconds: 15 + periodSeconds: 5 + timeoutSeconds: 1 + failureThreshold: 60 +cache: + stack: kubernetes diff --git a/argocd/applications/configs/secrets-config.yaml b/argocd/applications/configs/secrets-config.yaml index 68e1da9fc..3395d97f8 100644 --- a/argocd/applications/configs/secrets-config.yaml +++ b/argocd/applications/configs/secrets-config.yaml @@ -6,6 +6,8 @@ auth: orchSvcs: roleMaxTTL: 1h oidc: - idPAddr: "http://platform-keycloak.orch-platform.svc" - idPDiscoveryURL: "http://platform-keycloak.orch-platform.svc/realms/master" + # Use fully-qualified cluster DNS name to avoid any lookup ambiguity + # Use the actual HTTP service name created by the Keycloak chart + idPAddr: "http://platform-keycloak.orch-platform.svc.cluster.local:8080" + idPDiscoveryURL: "http://platform-keycloak.orch-platform.svc.cluster.local:8080/realms/master" roleMaxTTL: 1h diff --git a/argocd/applications/custom/keycloak-tenant-controller.tpl b/argocd/applications/custom/keycloak-tenant-controller.tpl index bacd77237..8ef280cba 100644 --- a/argocd/applications/custom/keycloak-tenant-controller.tpl +++ b/argocd/applications/custom/keycloak-tenant-controller.tpl @@ -9,7 +9,7 @@ image: proxy: httpProxy: {{.Values.argo.proxy.httpProxy}} httpsProxy: {{.Values.argo.proxy.httpsProxy}} - noProxy: {{.Values.argo.proxy.noProxy}} + noProxy: {{.Values.argo.proxy.noProxy}},*.svc,*.svc.cluster.local,platform-keycloak.orch-platform.svc,vault.orch-platform.svc imagePullSecrets: {{- with .Values.argo.imagePullSecrets }} {{- toYaml . | nindent 2 }} diff --git a/argocd/applications/custom/platform-keycloak.tpl b/argocd/applications/custom/platform-keycloak.tpl index b053f6132..770a479f0 100644 --- a/argocd/applications/custom/platform-keycloak.tpl +++ b/argocd/applications/custom/platform-keycloak.tpl @@ -2,14 +2,16 @@ # # SPDX-License-Identifier: Apache-2.0 -## Cluster-Specific values -## These values are not part of bitnami helm chart and are used to parameterize substrings in -## the larger keycloakConfigCli.configuration.realm-master.json value. -## @param clusterSpecific.webuiClientRootUrl The Keycloak Master realm UI Client's rootUrl value as a quoted JSON string -## @param clusterSpecific.webuiRedirectUrls The Keycloak Master realm UI Client's reirectUrl values as a JSON array of quoted JSON strings -## @param clusterSpecific.registryClientRootUrl The Keycloak Master realm Harbor Client's rootUrl value as a quoted JSON string -## @param clusterSpecific.telemetryClientRootUrl The Keycloak Master realm Grafana Client's rootUrl value as a quoted JSON string -## @param clusterSpecific.telemetryRedirectUrls The Keycloak Master realm Grafana Client's reirectUrl values as a JSON array of quoted JSON strings +# CodeCentric Keycloak Chart Template +# Updated for CodeCentric keycloakx chart instead of Bitnami chart + +## Cluster-Specific values for realm configuration +## These values parameterize the realm configuration for different environments +## @param clusterSpecific.webuiClientRootUrl The Keycloak Master realm UI Client's rootUrl value +## @param clusterSpecific.webuiRedirectUrls The Keycloak Master realm UI Client's redirectUrl values +## @param clusterSpecific.registryClientRootUrl The Keycloak Master realm Harbor Client's rootUrl value +## @param clusterSpecific.telemetryClientRootUrl The Keycloak Master realm Grafana Client's rootUrl value +## @param clusterSpecific.telemetryRedirectUrls The Keycloak Master realm Grafana Client's redirectUrl values clusterSpecific: webuiClientRootUrl: "https://web-ui.{{ .Values.argo.clusterDomain }}" webuiRedirectUrls: ["https://web-ui.{{ .Values.argo.clusterDomain }}", "https://app-service-proxy.{{ .Values.argo.clusterDomain }}/app-service-proxy-index.html*", "https://vnc.{{ .Values.argo.clusterDomain }}/*", "https://{{ .Values.argo.clusterDomain }}"{{- if index .Values.argo "platform-keycloak" "extraUiRedirects" -}}, {{- index .Values.argo "platform-keycloak" "extraUiRedirects" -}}{{- end -}}] @@ -17,49 +19,66 @@ clusterSpecific: telemetryClientRootUrl: "https://observability-ui.{{ .Values.argo.clusterDomain }}" telemetryRedirectUrls: ["https://observability-admin.{{ .Values.argo.clusterDomain }}/login/generic_oauth", "https://observability-ui.{{ .Values.argo.clusterDomain }}/login/generic_oauth"] -## External PostgreSQL configuration -## All of these values are only used when postgresql.enabled is set to false -## @param externalDatabase.existingSecret Name of an existing secret resource containing the database credentials -## @param externalDatabase.existingSecretHostKey Name of an existing secret key containing the database host name -## @param externalDatabase.existingSecretPortKey Name of an existing secret key containing the database port -## @param externalDatabase.existingSecretUserKey Name of an existing secret key containing the database user -## @param externalDatabase.existingSecretDatabaseKey Name of an existing secret key containing the database name -## @param externalDatabase.existingSecretPasswordKey Name of an existing secret key containing the database credentials -externalDatabase: - existingSecret: platform-keycloak-{{.Values.argo.database.type}}-postgresql - existingSecretHostKey: PGHOST - existingSecretPortKey: PGPORT - existingSecretUserKey: PGUSER - existingSecretDatabaseKey: PGDATABASE - existingSecretPasswordKey: PGPASSWORD +## Database configuration is defined in the base config file (platform-keycloak.yaml) +## This template only provides cluster-specific overrides -# Use index to handle values with hyphen +## Storage configuration (if local registry is used) {{- if index .Values.argo "platform-keycloak" "localRegistrySize"}} persistence: - persistentVolumeClaim: - registry: - size: {{index .Values.argo "platform-keycloak" "localRegistrySize"}} + storageClass: "" + size: {{index .Values.argo "platform-keycloak" "localRegistrySize"}} {{- end}} -extraEnvVars: - - name: HTTPS_PROXY - value: {{.Values.argo.proxy.httpsProxy}} - - name: HTTP_PROXY - value: {{.Values.argo.proxy.httpProxy}} - - name: NO_PROXY - value: {{.Values.argo.proxy.noProxy}} - {{ if index .Values.argo "platform-keycloak" "db" }} - - name: KC_DB_POOL_INITIAL_SIZE - value: {{ index .Values.argo "platform-keycloak" "db" "poolInitSize" | default "5" | quote}} - - name: KC_DB_POOL_MIN_SIZE - value: {{ index .Values.argo "platform-keycloak" "db" "poolMinSize" | default "5" | quote}} - - name: KC_DB_POOL_MAX_SIZE - value: {{ index .Values.argo "platform-keycloak" "db" "poolMaxSize" | default "100" | quote}} - {{ end }} - - name: KC_PROXY_HEADERS - value: "xforwarded" +## Environment variables are defined in the base config file (platform-keycloak.yaml) +## This template only provides cluster-specific overrides +## Resource configuration {{- with .Values.argo.resources.platformKeycloak }} resources: {{- toYaml . | nindent 2}} {{- end }} + +## Service configuration for compatibility +service: + type: ClusterIP + httpPort: 8080 + +## Network policy (typically disabled for simplicity) +networkPolicy: + enabled: false + +## Pod labels to avoid sidecar injection +podLabels: + sidecar.istio.io/inject: "false" + +## Additional volumes for realm configuration +extraVolumes: | + - name: keycloak-config + configMap: + name: platform-keycloak-config + +## Health probes configuration +livenessProbe: | + httpGet: + path: / + port: http + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + +readinessProbe: | + httpGet: + path: /realms/master + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + +## Enable metrics and health endpoints +metrics: + enabled: true + +health: + enabled: true diff --git a/argocd/applications/custom/secrets-config.tpl b/argocd/applications/custom/secrets-config.tpl index 5166aaff5..df66a2698 100644 --- a/argocd/applications/custom/secrets-config.tpl +++ b/argocd/applications/custom/secrets-config.tpl @@ -15,4 +15,11 @@ image: imagePullSecrets: {{- with .Values.argo.imagePullSecrets }} {{- toYaml . | nindent 2 }} - {{- end }} \ No newline at end of file + {{- end }} +# Disable Istio sidecar injection for the secrets-config job pods so +# they can talk to Keycloak instances that intentionally have injection +# disabled (prevents mTLS/sidecar mismatch issues). +podAnnotations: + sidecar.istio.io/inject: "false" +podLabels: + sidecar.istio.io/inject: "false" \ No newline at end of file diff --git a/argocd/applications/custom/traefik-extra-objects.tpl b/argocd/applications/custom/traefik-extra-objects.tpl index 084effd48..fc2118d3c 100644 --- a/argocd/applications/custom/traefik-extra-objects.tpl +++ b/argocd/applications/custom/traefik-extra-objects.tpl @@ -6,7 +6,7 @@ # Revisit this once the porting is done. orchSecretName: tls-orch # internal keycloak JWKS URL should be static but providing a way to modify it here -keycloakJwksUrl: http://platform-keycloak.orch-platform.svc +keycloakJwksUrl: http://platform-keycloak.orch-platform.svc.cluster.local:8080 # internal keycloak JWKS Path should be static but providing a way to modify it here keycloakJwksPath: /realms/master/protocol/openid-connect/certs keycloakServicePort: 8080 diff --git a/argocd/applications/templates/keycloak-admin-cli-config-job.yaml b/argocd/applications/templates/keycloak-admin-cli-config-job.yaml new file mode 100644 index 000000000..31bbf1eee --- /dev/null +++ b/argocd/applications/templates/keycloak-admin-cli-config-job.yaml @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +{{- $appName := "keycloak-admin-cli-config-job" }} +{{- $namespace := "orch-platform" }} +{{- $syncWave := "161" }} +--- +{{- if (index .Values.argo.enabled "platform-keycloak") }} +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + annotations: + argocd.argoproj.io/sync-wave: "{{ $syncWave }}" + name: {{$appName}} + namespace: {{ required "A valid namespace entry required!" .Values.argo.namespace }} + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: {{ required "A valid projectName entry required!" .Values.argo.project }} + sources: + - repoURL: {{ required "A valid deployRepoURL entry required!" .Values.argo.deployRepoURL }} + path: argocd/applications/configs + targetRevision: {{ required "A valid deployRepoRevision entry required!" .Values.argo.deployRepoRevision | quote }} + directory: + include: "keycloak-admin-cli-config-job.yaml" + destination: + namespace: {{$namespace}} + server: {{ required "A valid targetServer entry required!" .Values.argo.targetServer }} + syncPolicy: + {{- if .Values.argo.autosync }} + automated: + prune: true + selfHeal: true + retry: + limit: 5 + backoff: + duration: 5s + maxDuration: 3m0s + factor: 2 + {{- end }} + syncOptions: + - CreateNamespace=true + - ApplyOutOfSyncOnly=true +{{- end }} \ No newline at end of file diff --git a/argocd/applications/templates/keycloak-system-client-setup-job.yaml b/argocd/applications/templates/keycloak-system-client-setup-job.yaml new file mode 100644 index 000000000..a2ed6efd5 --- /dev/null +++ b/argocd/applications/templates/keycloak-system-client-setup-job.yaml @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +{{- $appName := "keycloak-system-client-setup-job" }} +{{- $namespace := "orch-platform" }} +{{- $syncWave := "165" }} +--- +{{- if (index .Values.argo.enabled "platform-keycloak") }} +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + annotations: + argocd.argoproj.io/sync-wave: "{{ $syncWave }}" + name: {{$appName}} + namespace: {{ required "A valid namespace entry required!" .Values.argo.namespace }} + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: {{ required "A valid projectName entry required!" .Values.argo.project }} + sources: + - repoURL: {{ required "A valid deployRepoURL entry required!" .Values.argo.deployRepoURL }} + path: argocd/applications/configs + targetRevision: {{ required "A valid deployRepoRevision entry required!" .Values.argo.deployRepoRevision | quote }} + directory: + include: "keycloak-system-client-setup-job.yaml" + destination: + namespace: {{$namespace}} + server: {{ required "A valid targetServer entry required!" .Values.argo.targetServer }} + syncPolicy: + {{- if .Values.argo.autosync }} + automated: + prune: true + selfHeal: true + retry: + limit: 3 + backoff: + duration: 5s + maxDuration: 2m0s + factor: 2 + {{- end }} + syncOptions: + - CreateNamespace=true +{{- end }} \ No newline at end of file diff --git a/argocd/applications/templates/platform-keycloak-compat-service.yaml b/argocd/applications/templates/platform-keycloak-compat-service.yaml new file mode 100644 index 000000000..a75ff7ec3 --- /dev/null +++ b/argocd/applications/templates/platform-keycloak-compat-service.yaml @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +{{- $appName := "platform-keycloak-compat-service" }} +{{- $namespace := "orch-platform" }} +{{- $syncWave := "151" }} +--- +{{- if (index .Values.argo.enabled "platform-keycloak") }} +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + annotations: + argocd.argoproj.io/sync-wave: "{{ $syncWave }}" + name: {{$appName}} + namespace: {{ required "A valid namespace entry required!" .Values.argo.namespace }} + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: {{ required "A valid projectName entry required!" .Values.argo.project }} + sources: + - repoURL: {{ required "A valid deployRepoURL entry required!" .Values.argo.deployRepoURL }} + path: argocd/applications/configs + targetRevision: {{ required "A valid deployRepoRevision entry required!" .Values.argo.deployRepoRevision | quote }} + directory: + include: "platform-keycloak-compat-service.yaml" + destination: + namespace: {{$namespace}} + server: {{ required "A valid targetServer entry required!" .Values.argo.targetServer }} + syncPolicy: + {{- if .Values.argo.autosync }} + automated: + prune: true + selfHeal: true + retry: + limit: 5 + backoff: + duration: 5s + maxDuration: 3m0s + factor: 2 + {{- end }} + syncOptions: + - CreateNamespace=true + - ApplyOutOfSyncOnly=true +{{- end }} \ No newline at end of file diff --git a/argocd/applications/templates/platform-keycloak-config-job.yaml b/argocd/applications/templates/platform-keycloak-config-job.yaml new file mode 100644 index 000000000..99b8206f7 --- /dev/null +++ b/argocd/applications/templates/platform-keycloak-config-job.yaml @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +{{- $appName := "platform-keycloak-config-job" }} +{{- $namespace := "orch-platform" }} +{{- $syncWave := "160" }} +--- +{{- if (index .Values.argo.enabled "platform-keycloak") }} +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + annotations: + argocd.argoproj.io/sync-wave: "{{ $syncWave }}" + name: {{$appName}} + namespace: {{ required "A valid namespace entry required!" .Values.argo.namespace }} + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: {{ required "A valid projectName entry required!" .Values.argo.project }} + sources: + - repoURL: {{ required "A valid deployRepoURL entry required!" .Values.argo.deployRepoURL }} + path: argocd/applications/configs + targetRevision: {{ required "A valid deployRepoRevision entry required!" .Values.argo.deployRepoRevision | quote }} + directory: + include: "platform-keycloak-config-job.yaml" + destination: + namespace: {{$namespace}} + server: {{ required "A valid targetServer entry required!" .Values.argo.targetServer }} + syncPolicy: + {{- if .Values.argo.autosync }} + automated: + prune: true + selfHeal: true + retry: + limit: 5 + backoff: + duration: 5s + maxDuration: 3m0s + factor: 2 + {{- end }} + syncOptions: + - CreateNamespace=true + - ApplyOutOfSyncOnly=true +{{- end }} \ No newline at end of file diff --git a/argocd/applications/templates/platform-keycloak-config.yaml b/argocd/applications/templates/platform-keycloak-config.yaml new file mode 100644 index 000000000..a8eead40a --- /dev/null +++ b/argocd/applications/templates/platform-keycloak-config.yaml @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +{{- $appName := "platform-keycloak-config" }} +{{- $namespace := "orch-platform" }} +{{- $syncWave := "140" }} +--- +{{- if (index .Values.argo.enabled "platform-keycloak") }} +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + annotations: + argocd.argoproj.io/sync-wave: "{{ $syncWave }}" + name: {{$appName}} + namespace: {{ required "A valid namespace entry required!" .Values.argo.namespace }} + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: {{ required "A valid projectName entry required!" .Values.argo.project }} + sources: + - repoURL: {{ required "A valid deployRepoURL entry required!" .Values.argo.deployRepoURL }} + path: argocd/applications/configs + targetRevision: {{ required "A valid deployRepoRevision entry required!" .Values.argo.deployRepoRevision | quote }} + directory: + include: "platform-keycloak-realm-config.yaml" + destination: + namespace: {{$namespace}} + server: {{ required "A valid targetServer entry required!" .Values.argo.targetServer }} + syncPolicy: + {{- if .Values.argo.autosync }} + automated: + prune: true + selfHeal: true + retry: + limit: 5 + backoff: + duration: 5s + maxDuration: 3m0s + factor: 2 + {{- end }} + syncOptions: + - CreateNamespace=true + - ApplyOutOfSyncOnly=true +{{- end }} \ No newline at end of file diff --git a/argocd/applications/templates/platform-keycloak.yaml b/argocd/applications/templates/platform-keycloak.yaml index fbf98e61c..e4f00c48a 100644 --- a/argocd/applications/templates/platform-keycloak.yaml +++ b/argocd/applications/templates/platform-keycloak.yaml @@ -19,9 +19,9 @@ metadata: spec: project: {{ required "A valid projectName entry required!" .Values.argo.project }} sources: - - repoURL: "registry-1.docker.io/bitnamicharts" - chart: keycloak - targetRevision: 24.4.12 + - repoURL: "https://codecentric.github.io/helm-charts" + chart: keycloakx + targetRevision: 7.1.3 helm: releaseName: {{$appName}} valuesObject: diff --git a/argocd/root-app/values.yaml b/argocd/root-app/values.yaml index 706240ef9..2e23e4e0c 100644 --- a/argocd/root-app/values.yaml +++ b/argocd/root-app/values.yaml @@ -15,7 +15,7 @@ argo: clusterDomain: "" deployRepoURL: "" - deployRepoRevision: "" + deployRepoRevision: "bitnami-to-redhat-keycloak" targetServer: "" autosync: true