diff --git a/admin-tools/get-credentials.yaml b/admin-tools/get-credentials.yaml index fc7fc8818..2f8828370 100644 --- a/admin-tools/get-credentials.yaml +++ b/admin-tools/get-credentials.yaml @@ -114,7 +114,7 @@ block: - name: Get Keycloak DSO user credentials kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" kind: Secret name: dso-admin-user-secret register: keycloak_user_creds @@ -128,7 +128,7 @@ kubernetes.core.k8s_info: kind: Secret name: keycloak - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" register: keycloak_admin_creds tags: - keycloak @@ -136,7 +136,7 @@ - name: Display Keycloak credentials ansible.builtin.debug: msg: - - "URL : https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }} " + - "URL : https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }} " - "Admin username: dsoadmin " - "Admin password: {{ keycloak_admin_creds.resources[0].data['admin-password'] | b64decode }} " tags: diff --git a/admin-tools/get-versions.yaml b/admin-tools/get-versions.yaml index f2a6edeb6..45afb15c6 100644 --- a/admin-tools/get-versions.yaml +++ b/admin-tools/get-versions.yaml @@ -248,7 +248,7 @@ - name: Retrieve Keycloak infos kubernetes.core.helm_info: name: keycloak - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" register: keycloak_infos - name: Display Keycloak version diff --git a/admin-tools/keycloak-admin-password-reset.yaml b/admin-tools/keycloak-admin-password-reset-isolated-pod.yaml similarity index 50% rename from admin-tools/keycloak-admin-password-reset.yaml rename to admin-tools/keycloak-admin-password-reset-isolated-pod.yaml index 2cc436c1b..25a241fe3 100644 --- a/admin-tools/keycloak-admin-password-reset.yaml +++ b/admin-tools/keycloak-admin-password-reset-isolated-pod.yaml @@ -2,7 +2,14 @@ - name: Reset Keycloak admin password hosts: localhost gather_facts: false + vars: + post_conf_job: true + argo_infra_ns_check: + failed: true tasks: + - name: "Déclaration du clone GitOps local" + ansible.builtin.set_fact: + gitops_local_repo: "{{ lookup('ansible.builtin.env', 'GITOPS_REPO_PATH') }}" - name: Set Keycloak password reset flag ansible.builtin.set_fact: keycloak_reset_password: true @@ -33,18 +40,6 @@ - "Rappel : le présent playbook lancé seul, sans extra vars, utilisera la configuration dsc par défaut (conf-dso)." - "Il réinitialisera donc le mot de passe de l'administrateur Keycloak du namespace associé." - - name: Get Keycloak pods - kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" - kind: Pod - label_selectors: - - app.kubernetes.io/name=keycloak - register: kc_pods - - - name: Set kc_pod fact - ansible.builtin.set_fact: - kc_pod: "{{ kc_pods.resources[0].metadata.name }}" - - name: Set tmp_adm_pass fact ansible.builtin.set_fact: tmp_adm_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}" @@ -53,23 +48,97 @@ ansible.builtin.set_fact: kc_adm_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}" - - name: Create temporary admin user - kubernetes.core.k8s_exec: - pod: "{{ kc_pod }}" - namespace: "{{ dsc.keycloak.namespace }}" - command: > - bash -c "JAVA_OPTS_APPEND='-Djgroups.dns.query=keycloak-headless.{{ dsc.keycloak.namespace }}.svc.cluster.local -Djgroups.bind.port=7900'; - export PASS_VAR='{{ tmp_adm_pass }}'; - kc.sh bootstrap-admin user --username tmpadm --password:env PASS_VAR" - register: tmp_adm + - name: Bootstrap temporary admin via isolated pod + block: + - name: Get keycloak StatefulSet spec + kubernetes.core.k8s_info: + namespace: "{{ dsc.keycloakx.namespace }}" + kind: StatefulSet + name: keycloak + register: kc_statefulset + + - name: Set kc_container_spec fact + ansible.builtin.set_fact: + kc_container_spec: "{{ kc_statefulset.resources[0].spec.template.spec.containers | selectattr('name', 'equalto', 'keycloak') | first }}" + kc_pod_security_context: "{{ kc_statefulset.resources[0].spec.template.spec.securityContext | default({}) }}" + kc_service_account: "{{ kc_statefulset.resources[0].spec.template.spec.serviceAccountName | default(omit) }}" + + - name: Set bootstrap pod name and temp admin username facts + ansible.builtin.set_fact: + bootstrap_pod_name: "keycloakx-bootstrap-admin-{{ now(fmt='%Y%m%d%H%M%S') }}" + tmp_admin_username: "tmpadm-{{ now(fmt='%Y%m%d%H%M%S') }}" + + - name: Create isolated bootstrap-admin pod + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Pod + metadata: + name: "{{ bootstrap_pod_name }}" + namespace: "{{ dsc.keycloakx.namespace }}" + labels: + app.kubernetes.io/name: keycloakx-bootstrap-admin + spec: + restartPolicy: Never + serviceAccountName: "{{ kc_service_account | default(omit) }}" + securityContext: "{{ kc_pod_security_context }}" + containers: + - name: bootstrap-admin + image: "{{ kc_container_spec.image }}" + securityContext: "{{ kc_container_spec.securityContext | default({}) }}" + command: + - /opt/keycloak/bin/kc.sh + args: + - bootstrap-admin + - user + - --username + - "{{ tmp_admin_username }}" + - --password:env + - PASS_VAR + - --no-prompt + env: "{{ bootstrap_env }}" + vars: + base_env: "{{ (kc_container_spec.env | default([])) | rejectattr('name', 'equalto', 'KC_CACHE') | list }}" + bootstrap_env: "{{ base_env + [{'name': 'KC_CACHE', 'value': 'local'}, {'name': 'PASS_VAR', 'value': tmp_adm_pass}] }}" + + - name: Wait for bootstrap-admin pod to finish + kubernetes.core.k8s_info: + namespace: "{{ dsc.keycloakx.namespace }}" + kind: Pod + name: "{{ bootstrap_pod_name }}" + register: bootstrap_pod_status + until: bootstrap_pod_status.resources[0].status.phase in ['Succeeded', 'Failed'] + retries: 50 + delay: 5 + + - name: Get bootstrap-admin pod logs + kubernetes.core.k8s_log: + namespace: "{{ dsc.keycloakx.namespace }}" + name: "{{ bootstrap_pod_name }}" + register: bootstrap_pod_logs + + - name: Fail if bootstrap-admin pod did not succeed + ansible.builtin.fail: + msg: "{{ bootstrap_pod_logs.log_lines | default([bootstrap_pod_logs.log | default('no logs')]) }}" + when: bootstrap_pod_status.resources[0].status.phase != 'Succeeded' + always: + - name: Delete bootstrap-admin pod + kubernetes.core.k8s: + state: absent + namespace: "{{ dsc.keycloakx.namespace }}" + kind: Pod + name: "{{ bootstrap_pod_name }}" + when: bootstrap_pod_name is defined + ignore_errors: true - name: Update dsoadmin user community.general.keycloak_user: validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli - auth_keycloak_url: https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }} + auth_keycloak_url: https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }} auth_realm: master - auth_username: tmpadm + auth_username: "{{ tmp_admin_username }}" auth_password: "{{ tmp_adm_pass }}" state: present realm: master @@ -91,12 +160,12 @@ - name: Update keycloak secret kubernetes.core.k8s: kind: Secret - name: keycloak - namespace: "{{ dsc.keycloak.namespace }}" + name: keycloakx-admin-secret + namespace: "{{ dsc.keycloakx.namespace }}" state: patched definition: data: - admin-password: "{{ kc_adm_pass | b64encode }}" + KEYCLOAK_ADMIN_PASSWORD: "{{ kc_adm_pass | b64encode }}" - name: Update console inventory when: not dsc.global.gitOps.deploymentEnabled @@ -113,16 +182,25 @@ community.general.keycloak_user: validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli - auth_keycloak_url: https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }} + auth_keycloak_url: https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }} auth_realm: master auth_username: dsoadmin auth_password: "{{ kc_adm_pass }}" state: absent realm: master - username: tmpadm + username: "{{ tmp_admin_username }}" + # NB: a leftover "tmpadm" (or "tmpadm-" from an earlier + # interrupted run of this playbook) is not cleaned up here - each run + # now uses a unique temp username, so nothing depends on removing old + # ones, and their passwords were random and never recorded anywhere. + # Remove them by hand from the master realm's user list if you want + # the account list tidy. - name: Update new password in infra-vault - when: dsc.global.gitOps.deploymentEnabled + # No `when: dsc.global.gitOps.deploymentEnabled` guard here: the + # keycloakx-admin-secret Secret is AVP-rendered from this same Vault + # path on every ArgoCD sync, so skipping the write would let the next + # sync silently revert this reset. block: - name: Load variables for the vault-secrets post-install role ansible.builtin.include_vars: @@ -131,6 +209,8 @@ - name: Post-install vault-secrets run ansible.builtin.import_role: name: "gitops/vault-secrets" + vars: + post_vault_update: true - name: Get DSO Console server deployment kubernetes.core.k8s_info: @@ -164,8 +244,8 @@ ansible.builtin.debug: msg: - "Réinitialisation du mot de passe administrateur de l'instance Keycloak suivante effectuée :" - - " URL : https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }}" - - " Namespace : {{ dsc.keycloak.namespace }}" + - " URL : https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }}" + - " Namespace : {{ dsc.keycloakx.namespace }}" - "" - "Nouveaux identifiants :" - " Utilisateur : dsoadmin " diff --git a/admin-tools/keycloak-user-unlock.yaml b/admin-tools/keycloak-user-unlock.yaml index 761ce4d76..bacaff7d1 100644 --- a/admin-tools/keycloak-user-unlock.yaml +++ b/admin-tools/keycloak-user-unlock.yaml @@ -57,10 +57,10 @@ - name: Get Keycloak pods kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" kind: Pod label_selectors: - - app.kubernetes.io/name=keycloak + - app.kubernetes.io/name=keycloakx register: kc_pods - name: Set kc_pod fact @@ -75,16 +75,16 @@ - name: Create temporary admin user kubernetes.core.k8s_exec: pod: "{{ kc_pod }}" - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" command: > - bash -c "JAVA_OPTS_APPEND='-Djgroups.dns.query=keycloak-headless.{{ dsc.keycloak.namespace }}.svc.cluster.local -Djgroups.bind.port=7900'; + bash -c "JAVA_OPTS_APPEND='-Djgroups.dns.query=keycloak-headless.{{ dsc.keycloakx.namespace }}.svc.cluster.local -Djgroups.bind.port=7900'; export PASS_VAR='{{ tmp_admin_pass }}'; - kc.sh bootstrap-admin user --username {{ tmp_admin }} --password:env PASS_VAR" + /opt/keycloak/bin/kc.sh bootstrap-admin user --username {{ tmp_admin }} --password:env PASS_VAR" register: tmp_adm - name: Get Keycloak API token ansible.builtin.uri: - url: https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }}/realms/master/protocol/openid-connect/token + url: https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }}/realms/master/protocol/openid-connect/token method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -99,7 +99,7 @@ - name: Retrieve users from API ansible.builtin.uri: - url: https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }}/admin/realms/master/users + url: https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }}/admin/realms/master/users method: GET status_code: [200, 204] return_content: true @@ -118,7 +118,7 @@ - name: Unlock user ansible.builtin.uri: - url: https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }}/admin/realms/master/attack-detection/brute-force/users/{{ user_id }} + url: https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }}/admin/realms/master/attack-detection/brute-force/users/{{ user_id }} method: DELETE status_code: [200, 204] return_content: true @@ -131,7 +131,7 @@ community.general.keycloak_user: validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli - auth_keycloak_url: https://{{ dsc.keycloak.subDomain }}{{ dsc.global.rootDomain }} + auth_keycloak_url: https://{{ dsc.keycloakx.subDomain }}{{ dsc.global.rootDomain }} auth_realm: master auth_username: "{{ tmp_admin }}" auth_password: "{{ tmp_admin_pass }}" diff --git a/admin-tools/pgrestore.yaml b/admin-tools/pgrestore.yaml index 79eb2d2f2..e18b67fcd 100644 --- a/admin-tools/pgrestore.yaml +++ b/admin-tools/pgrestore.yaml @@ -16,8 +16,8 @@ vars: pgdump_cnpg_clusters: - - name: "{{ dsc.keycloak.subDomain }}" - namespace: "{{ dsc.keycloak.namespace }}" + - name: "{{ dsc.keycloakx.subDomain }}" + namespace: "{{ dsc.keycloakx.namespace }}" db: keycloak - name: "{{ dsc.sonarqube.subDomain }}" namespace: "{{ dsc.sonarqube.namespace }}" diff --git a/post-install/awx-oidc.yaml b/post-install/awx-oidc.yaml index 62cacc844..5e2a24832 100644 --- a/post-install/awx-oidc.yaml +++ b/post-install/awx-oidc.yaml @@ -14,7 +14,7 @@ - name: Get awx client secret kubernetes.core.k8s_info: kind: Secret - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" name: keycloak-client-secret-awx-client register: awx_secret failed_when: awx_secret.resources | length == 0 diff --git a/post-install/keycloak.yaml b/post-install/keycloakx.yaml similarity index 96% rename from post-install/keycloak.yaml rename to post-install/keycloakx.yaml index 3e5a64447..16b37a78a 100644 --- a/post-install/keycloak.yaml +++ b/post-install/keycloakx.yaml @@ -22,7 +22,7 @@ envs: - name: "{{ dsc_name }}" apps: - - argocd_app: keycloak + - argocd_app: keycloakx vault_values: global: userTmpPassword: "itDoesNotMatterWhatWeWriteHere" @@ -33,7 +33,7 @@ - name: Import keycloak role ansible.builtin.import_role: - name: gitops/post-install/keycloak + name: gitops/post-install/keycloakx - name: Update vault-secrets for oidc block: @@ -49,7 +49,7 @@ - argocd_app: gitlab vault_values: oidcProvider: "{{ gitlab_oidc_provider | b64encode | default('') }}" - - argocd_app: keycloak + - argocd_app: keycloakx vault_values: client: argo: diff --git a/roles/admin-tools/keycloak-enforce-mfa/tasks/main.yml b/roles/admin-tools/keycloak-enforce-mfa/tasks/main.yml index a09f9bd20..6304706b4 100644 --- a/roles/admin-tools/keycloak-enforce-mfa/tasks/main.yml +++ b/roles/admin-tools/keycloak-enforce-mfa/tasks/main.yml @@ -1,7 +1,7 @@ --- - name: Get Keycloak admin password kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" kind: Secret name: keycloak register: kc_adm_pass @@ -13,7 +13,7 @@ - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -29,7 +29,7 @@ - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -50,7 +50,7 @@ page_size: 100 first_index: "{{ item }}" ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloak.applicationRealm }}/users?first={{ first_index }}&max={{ page_size }}" + url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloakx.applicationRealm }}/users?first={{ first_index }}&max={{ page_size }}" method: GET headers: Authorization: "Bearer {{ kc_access_token }}" @@ -67,7 +67,7 @@ - name: Force CONFIGURE_TOTP for all users except admin ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloak.applicationRealm }}/users/{{ item.id }}" + url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloakx.applicationRealm }}/users/{{ item.id }}" method: PUT status_code: [200, 204] body_format: json diff --git a/roles/admin-tools/keycloak-extract-users/tasks/main.yml b/roles/admin-tools/keycloak-extract-users/tasks/main.yml index dd9ed34c6..47074e221 100644 --- a/roles/admin-tools/keycloak-extract-users/tasks/main.yml +++ b/roles/admin-tools/keycloak-extract-users/tasks/main.yml @@ -1,7 +1,7 @@ --- - name: Get Keycloak admin password kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" kind: Secret name: keycloak register: kc_adm_pass @@ -13,7 +13,7 @@ - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -29,7 +29,7 @@ - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -50,7 +50,7 @@ page_size: 100 first_index: "{{ item }}" ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloak.applicationRealm }}/users?first={{ first_index }}&max={{ page_size }}" + url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloakx.applicationRealm }}/users?first={{ first_index }}&max={{ page_size }}" method: GET headers: Authorization: "Bearer {{ kc_access_token }}" diff --git a/roles/gitops/post-install/harbor/tasks/main.yaml b/roles/gitops/post-install/harbor/tasks/main.yaml index 454e1db98..c6186e8a8 100644 --- a/roles/gitops/post-install/harbor/tasks/main.yaml +++ b/roles/gitops/post-install/harbor/tasks/main.yaml @@ -15,7 +15,7 @@ - name: Get harbor client secret kubernetes.core.k8s_info: kind: Secret - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" name: keycloak-client-secret-harbor-client register: harbor_secret failed_when: harbor_secret.resources | length == 0 @@ -28,7 +28,7 @@ oidc_admin_group: /admin oidc_auto_onboard: true oidc_client_id: "{{ harbor_secret.resources[0].data.CLIENT_ID | b64decode }}" - oidc_endpoint: https://{{ keycloak_domain }}/realms/{{ dsc.keycloak.applicationRealm }} + oidc_endpoint: https://{{ keycloak_domain }}/realms/{{ dsc.keycloakx.applicationRealm }} oidc_extra_redirect_parms: "{}" oidc_group_filter: "" oidc_groups_claim: groups diff --git a/roles/gitops/post-install/keycloak/files/generic-client-scope-protocolMappers.yaml b/roles/gitops/post-install/keycloakx/files/generic-client-scope-protocolMappers.yaml similarity index 100% rename from roles/gitops/post-install/keycloak/files/generic-client-scope-protocolMappers.yaml rename to roles/gitops/post-install/keycloakx/files/generic-client-scope-protocolMappers.yaml diff --git a/roles/gitops/post-install/keycloak/files/group-client-scope-protocolMappers.yaml b/roles/gitops/post-install/keycloakx/files/group-client-scope-protocolMappers.yaml similarity index 100% rename from roles/gitops/post-install/keycloak/files/group-client-scope-protocolMappers.yaml rename to roles/gitops/post-install/keycloakx/files/group-client-scope-protocolMappers.yaml diff --git a/roles/gitops/post-install/keycloak/tasks/client.yaml b/roles/gitops/post-install/keycloakx/tasks/client.yaml similarity index 90% rename from roles/gitops/post-install/keycloak/tasks/client.yaml rename to roles/gitops/post-install/keycloakx/tasks/client.yaml index eb55f0fa8..e3826fd00 100644 --- a/roles/gitops/post-install/keycloak/tasks/client.yaml +++ b/roles/gitops/post-install/keycloakx/tasks/client.yaml @@ -4,11 +4,11 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: present - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" clientId: "{{ item.clientId }}" clientAuthenticatorType: "{{ item.clientAuthenticatorType | default(omit) }}" standardFlowEnabled: "{{ item.standardFlowEnabled }}" @@ -24,10 +24,10 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" clientId: "{{ item.clientId }}" register: kc_clients_secrets @@ -43,7 +43,7 @@ CLIENT_SECRET: "{{ kc_clients_secrets.clientsecret_info.value | b64encode }}" metadata: name: keycloak-client-secret-{{ item.clientId }} - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" type: Opaque - name: Set Keycloak clients secrets in Keycloak namespace @@ -57,7 +57,7 @@ CLIENT_ID: "{{ item.clientId | b64encode }}" metadata: name: keycloak-client-secret-{{ item.clientId }} - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" type: Opaque - name: Set facts for vault-secret update diff --git a/roles/gitops/post-install/keycloak/tasks/main.yml b/roles/gitops/post-install/keycloakx/tasks/main.yml similarity index 86% rename from roles/gitops/post-install/keycloak/tasks/main.yml rename to roles/gitops/post-install/keycloakx/tasks/main.yml index 476690106..3f7c3c820 100644 --- a/roles/gitops/post-install/keycloak/tasks/main.yml +++ b/roles/gitops/post-install/keycloakx/tasks/main.yml @@ -3,19 +3,19 @@ - name: Get Keycloak admin password kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" kind: Secret - name: keycloak + name: keycloakx-admin-secret register: kc_adm_pass - name: Set Keycloak admin facts ansible.builtin.set_fact: - keycloak_admin_password: "{{ kc_adm_pass.resources[0].data['admin-password'] | b64decode }}" + keycloak_admin_password: "{{ kc_adm_pass.resources[0].data['KEYCLOAK_ADMIN_PASSWORD'] | b64decode }}" keycloak_admin: admin - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -31,7 +31,7 @@ - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -47,7 +47,7 @@ - name: Get keycloak master realm users from API ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloak.managementRealm }}/users" + url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloakx.managementRealm }}/users" method: GET status_code: [200, 202] return_content: true @@ -74,20 +74,20 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" name: admin - realm: "{{ dsc.keycloak.managementRealm }}" + realm: "{{ dsc.keycloakx.managementRealm }}" state: present - name: Map admin realm role from admin group community.general.keycloak_realm_rolemapping: validate_certs: "{{ dsc.exposedCA.type == 'none' }}" - realm: "{{ dsc.keycloak.managementRealm }}" + realm: "{{ dsc.keycloakx.managementRealm }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: present @@ -100,11 +100,11 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: present - realm: "{{ dsc.keycloak.managementRealm }}" + realm: "{{ dsc.keycloakx.managementRealm }}" credentials: - temporary: false type: password @@ -136,18 +136,18 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: absent - realm: "{{ dsc.keycloak.managementRealm }}" + realm: "{{ dsc.keycloakx.managementRealm }}" username: admin # Ensure we will use permanent admin for subsequent tasks - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -163,7 +163,7 @@ - name: Get Keycloak API token ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloak.managementRealm }}/protocol/openid-connect/token" + url: "{{ keycloak_auth_url }}/realms/{{ dsc.keycloakx.managementRealm }}/protocol/openid-connect/token" method: POST status_code: [200, 202] validate_certs: "{{ dsc.exposedCA.type == 'none' }}" @@ -213,12 +213,12 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: present - id: "{{ dsc.keycloak.applicationRealm }}" - realm: "{{ dsc.keycloak.applicationRealm }}" + id: "{{ dsc.keycloakx.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" display_name: Dso Realm loginWithEmailAllowed: true registration_email_as_username: false @@ -253,16 +253,16 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: present - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" name: admin - name: Get keycloak dso realm users from API ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloak.applicationRealm }}/users" + url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloakx.applicationRealm }}/users" method: GET status_code: [200, 202] return_content: true @@ -274,7 +274,7 @@ - name: Find dso admin secret kubernetes.core.k8s_info: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" kind: Secret name: dso-admin-user-secret register: dso_admin_secret @@ -293,7 +293,7 @@ definition: kind: Secret metadata: - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" name: dso-admin-user-secret data: ADMIN_USER: "{{ 'admin@example.com' | b64encode }}" @@ -305,11 +305,11 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: absent - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" username: admin@example.com - name: Create dso admin user @@ -317,11 +317,11 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" state: present - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" credentials: - temporary: false type: password @@ -339,7 +339,7 @@ - name: Get dso keycloak client scopes from API ansible.builtin.uri: - url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloak.applicationRealm }}/client-scopes" + url: "{{ keycloak_auth_url }}/admin/realms/{{ dsc.keycloakx.applicationRealm }}/client-scopes" method: GET status_code: [200, 202] return_content: true @@ -355,11 +355,11 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" name: generic - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" description: Generic client scope protocol: openid-connect attributes: @@ -375,11 +375,11 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" name: group - realm: "{{ dsc.keycloak.applicationRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" description: Group client scope protocol: openid-connect attributes: @@ -399,22 +399,22 @@ validate_certs: "{{ dsc.exposedCA.type == 'none' }}" auth_client_id: admin-cli auth_keycloak_url: "{{ keycloak_auth_url }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" realm: "{{ item }}" brute_force_protected: true failure_factor: 10 with_items: - - "{{ dsc.keycloak.managementRealm }}" - - "{{ dsc.keycloak.applicationRealm }}" + - "{{ dsc.keycloakx.managementRealm }}" + - "{{ dsc.keycloakx.applicationRealm }}" - name: Set GitLab OIDC provider fact block: - name: Get Gitlab client secret kubernetes.core.k8s_info: kind: Secret - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" name: keycloak-client-secret-gitlab-client register: gitlab_secret failed_when: gitlab_secret.resources | length == 0 @@ -430,7 +430,7 @@ - openid - generic response_type: code - issuer: https://{{ keycloak_domain }}/realms/{{ dsc.keycloak.applicationRealm }} + issuer: https://{{ keycloak_domain }}/realms/{{ dsc.keycloakx.applicationRealm }} client_auth_method: query discovery: true uid_field: email @@ -440,6 +440,6 @@ redirect_uri: https://{{ gitlab_domain }}/users/auth/openid_connect/callback - name: Reconcile keycloak users - when: dsc.keycloak.usersGitOpsEnabled + when: dsc.keycloakx.usersGitOpsEnabled ansible.builtin.include_tasks: file: sync_users.yml diff --git a/roles/gitops/post-install/keycloak/tasks/sync_users.yml b/roles/gitops/post-install/keycloakx/tasks/sync_users.yml similarity index 91% rename from roles/gitops/post-install/keycloak/tasks/sync_users.yml rename to roles/gitops/post-install/keycloakx/tasks/sync_users.yml index fd01e4d1b..745e394d0 100644 --- a/roles/gitops/post-install/keycloak/tasks/sync_users.yml +++ b/roles/gitops/post-install/keycloakx/tasks/sync_users.yml @@ -19,8 +19,8 @@ auth_keycloak_url: "{{ keycloak_auth_url }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" - realm: "{{ dsc.keycloak.applicationRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" username: "{{ item.value.username }}" firstName: "{{ item.value.name | capitalize }}" lastName: "{{ item.value.surname | capitalize }}" @@ -56,8 +56,8 @@ auth_keycloak_url: "{{ keycloak_auth_url }}" auth_username: "{{ keycloak_admin }}" auth_password: "{{ keycloak_admin_password }}" - auth_realm: "{{ dsc.keycloak.managementRealm }}" - realm: "{{ dsc.keycloak.applicationRealm }}" + auth_realm: "{{ dsc.keycloakx.managementRealm }}" + realm: "{{ dsc.keycloakx.applicationRealm }}" username: "{{ item.username }}" state: absent validate_certs: "{{ dsc.exposedCA.type == 'none' }}" diff --git a/roles/gitops/post-install/keycloak/templates/argocd-redirectUris.yaml.j2 b/roles/gitops/post-install/keycloakx/templates/argocd-redirectUris.yaml.j2 similarity index 100% rename from roles/gitops/post-install/keycloak/templates/argocd-redirectUris.yaml.j2 rename to roles/gitops/post-install/keycloakx/templates/argocd-redirectUris.yaml.j2 diff --git a/roles/gitops/post-install/keycloak/templates/argocd-webOrigins.yaml.j2 b/roles/gitops/post-install/keycloakx/templates/argocd-webOrigins.yaml.j2 similarity index 100% rename from roles/gitops/post-install/keycloak/templates/argocd-webOrigins.yaml.j2 rename to roles/gitops/post-install/keycloakx/templates/argocd-webOrigins.yaml.j2 diff --git a/roles/gitops/post-install/keycloak/templates/console-redirectUris.yaml.j2 b/roles/gitops/post-install/keycloakx/templates/console-redirectUris.yaml.j2 similarity index 100% rename from roles/gitops/post-install/keycloak/templates/console-redirectUris.yaml.j2 rename to roles/gitops/post-install/keycloakx/templates/console-redirectUris.yaml.j2 diff --git a/roles/gitops/post-install/keycloak/templates/console-webOrigins.yaml.j2 b/roles/gitops/post-install/keycloakx/templates/console-webOrigins.yaml.j2 similarity index 100% rename from roles/gitops/post-install/keycloak/templates/console-webOrigins.yaml.j2 rename to roles/gitops/post-install/keycloakx/templates/console-webOrigins.yaml.j2 diff --git a/roles/gitops/post-install/keycloak/vars/main.yaml b/roles/gitops/post-install/keycloakx/vars/main.yaml similarity index 96% rename from roles/gitops/post-install/keycloak/vars/main.yaml rename to roles/gitops/post-install/keycloakx/vars/main.yaml index 1111297bf..3abac2fa7 100644 --- a/roles/gitops/post-install/keycloak/vars/main.yaml +++ b/roles/gitops/post-install/keycloakx/vars/main.yaml @@ -1,5 +1,5 @@ --- -keycloak_auth_url: "http://{{ dsc.keycloak.subDomain }}.{{ dsc.keycloak.namespace }}.svc.cluster.local" +keycloak_auth_url: "http://{{ dsc.keycloakx.subDomain }}-http.{{ dsc.keycloakx.namespace }}.svc.cluster.local" keycloak_clients: - clientId: gitlab-client clientAuthenticatorType: client-secret diff --git a/roles/gitops/post-install/pgdump/vars/main.yml b/roles/gitops/post-install/pgdump/vars/main.yml index 2fbfde2d0..30b49212c 100644 --- a/roles/gitops/post-install/pgdump/vars/main.yml +++ b/roles/gitops/post-install/pgdump/vars/main.yml @@ -1,6 +1,6 @@ pgdump_cnpg_clusters: - name: keycloak - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" db: keycloak - name: sonar namespace: "{{ dsc.sonarqube.namespace }}" diff --git a/roles/gitops/post-install/vault/tasks/main.yml b/roles/gitops/post-install/vault/tasks/main.yml index 5d508355b..ebecf602b 100644 --- a/roles/gitops/post-install/vault/tasks/main.yml +++ b/roles/gitops/post-install/vault/tasks/main.yml @@ -229,7 +229,7 @@ - name: Get vault client secret kubernetes.core.k8s_info: kind: Secret - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" name: keycloak-client-secret-vault-client register: vault_secret @@ -259,7 +259,7 @@ - name: Get Vault client secret kubernetes.core.k8s_info: kind: Secret - namespace: "{{ dsc.keycloak.namespace }}" + namespace: "{{ dsc.keycloakx.namespace }}" name: keycloak-client-secret-vault-client register: vault_secret failed_when: vault_secret.resources | length == 0 @@ -273,7 +273,7 @@ headers: "X-Vault-Token": "{{ vault_token }}" body: - "oidc_discovery_url": "https://{{ keycloak_domain }}/realms/{{ dsc.keycloak.applicationRealm }}" + "oidc_discovery_url": "https://{{ keycloak_domain }}/realms/{{ dsc.keycloakx.applicationRealm }}" "oidc_discovery_ca_pem": "{{ exposed_ca_pem }}" "oidc_client_id": "{{ vault_secret.resources[0].data.CLIENT_ID | b64decode }}" "oidc_client_secret": "{{ vault_secret.resources[0].data.CLIENT_SECRET | b64decode }}" diff --git a/roles/gitops/rendering-apps-files/tasks/template.yml b/roles/gitops/rendering-apps-files/tasks/template.yml index 668b02e02..f8dccbbec 100644 --- a/roles/gitops/rendering-apps-files/tasks/template.yml +++ b/roles/gitops/rendering-apps-files/tasks/template.yml @@ -61,13 +61,15 @@ state: directory mode: "0775" - - name: Check if keycloak/templates/users.yaml exists + # users.yaml is maintained by hand in the GitOps repo (one commit per ticket): + # never overwrite an existing one with the example users from the template. + - name: Check if {{ item.1.argocd_app }}/templates/users.yaml exists ansible.builtin.stat: - path: "{{ gitops_local_repo }}/{{ dsc.global.gitOps.repo.path }}/envs/{{ item.0.name }}/apps/keycloak/templates/users.yaml" - register: keycloak_users_file_stat + path: "{{ dest_path }}/templates/users.yaml" + register: app_users_file_stat - name: Render "{{ item.1.argocd_app }}" templates and write yaml files to destination - when: not (my_template | basename == 'users.yaml.j2' and keycloak_users_file_stat.stat.exists) + when: not (my_template | basename == 'users.yaml.j2' and app_users_file_stat.stat.exists) vars: rendered_content: "{{ lookup('ansible.builtin.template', my_template) }}" dest_filename: "{{ my_template | basename | regex_replace('\\.j2$', '') }}" diff --git a/roles/gitops/rendering-apps-files/templates/awx/templates/post-conf-job.yaml.j2 b/roles/gitops/rendering-apps-files/templates/awx/templates/post-conf-job.yaml.j2 index 1798c19b8..ac414725a 100644 --- a/roles/gitops/rendering-apps-files/templates/awx/templates/post-conf-job.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/awx/templates/post-conf-job.yaml.j2 @@ -32,7 +32,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: awx-oidc-post-conf-rb - namespace: {{ dsc.keycloak.namespace }} + namespace: {{ dsc.keycloakx.namespace }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/roles/gitops/rendering-apps-files/templates/console/values/00-main.j2 b/roles/gitops/rendering-apps-files/templates/console/values/00-main.j2 index 7ec064075..edc31d575 100644 --- a/roles/gitops/rendering-apps-files/templates/console/values/00-main.j2 +++ b/roles/gitops/rendering-apps-files/templates/console/values/00-main.j2 @@ -21,8 +21,8 @@ console: HARBOR_RULE_COUNT: "100" {% endif %} KEYCLOAK_ADMIN: "dsoadmin" - KEYCLOAK_ADMIN_PASSWORD: - KEYCLOAK_URL: "http://{{ dsc.keycloak.subDomain }}.{{ dsc.keycloak.namespace }}.svc.cluster.local/realms/{{ dsc.keycloak.applicationRealm }}/.well-known/openid-configuration" + KEYCLOAK_ADMIN_PASSWORD: + KEYCLOAK_URL: "http://{{ dsc.keycloakx.subDomain }}-http.{{ dsc.keycloakx.namespace }}.svc.cluster.local/realms/{{ dsc.keycloakx.applicationRealm }}/.well-known/openid-configuration" NEXUS_ADMIN: admin NEXUS_ADMIN_PASSWORD: NEXUS_URL: "https:///" @@ -38,14 +38,14 @@ console: NODE_ENV: "production" keycloak: domain: - backend: "{{ dsc.keycloak.subDomain }}.{{ dsc.keycloak.namespace }}.svc.cluster.local" + backend: "{{ dsc.keycloakx.subDomain }}-http.{{ dsc.keycloakx.namespace }}.svc.cluster.local" frontend: "" - realm: {{ dsc.keycloak.applicationRealm }} + realm: {{ dsc.keycloakx.applicationRealm }} clientIds: backend: "console-backend" frontend: "console-frontend" clientSecrets: - backend: "" + backend: "" redirectUri: "https://" sessionSecret: "a-very-strong-secret-with-more-than-32-char" devRealm: false diff --git a/roles/gitops/rendering-apps-files/templates/global/templates/cluster-role-binding.yml.j2 b/roles/gitops/rendering-apps-files/templates/global/templates/cluster-role-binding.yml.j2 index 7e682cc03..ebb54edc9 100644 --- a/roles/gitops/rendering-apps-files/templates/global/templates/cluster-role-binding.yml.j2 +++ b/roles/gitops/rendering-apps-files/templates/global/templates/cluster-role-binding.yml.j2 @@ -10,7 +10,7 @@ roleRef: subjects: - kind: ServiceAccount name: cpn-ansible-job - namespace: {{ dsc.keycloak.namespace }} + namespace: {{ dsc.keycloakx.namespace }} - kind: ServiceAccount name: cpn-ansible-job namespace: {{ dsc.gitlab.namespace }} diff --git a/roles/gitops/rendering-apps-files/templates/harbor/templates/post-conf-job-role.yaml.j2 b/roles/gitops/rendering-apps-files/templates/harbor/templates/post-conf-job-role.yaml.j2 index c22923778..8e2cc4ed0 100644 --- a/roles/gitops/rendering-apps-files/templates/harbor/templates/post-conf-job-role.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/harbor/templates/post-conf-job-role.yaml.j2 @@ -13,7 +13,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: get-keycloak-client-secret-role-binding - namespace: {{ dsc.keycloak.namespace }} + namespace: {{ dsc.keycloakx.namespace }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/templates/secret-admin.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/templates/secret-admin.yaml.j2 deleted file mode 100644 index 64a4501c9..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/templates/secret-admin.yaml.j2 +++ /dev/null @@ -1,9 +0,0 @@ -kind: Secret -apiVersion: v1 -type: Opaque -metadata: - name: keycloak - annotations: - avp.kubernetes.io/remove-missing: "true" -data: - admin-password: diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/00-main.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/values/00-main.j2 deleted file mode 100644 index e6b8b4cbd..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/00-main.j2 +++ /dev/null @@ -1,235 +0,0 @@ -keycloak: - fullnameOverride: {{ dsc.keycloak.subDomain }} - - auth: - adminUser: "admin" - existingSecret: "keycloak" - passwordSecretKey: "admin-password" - - tls: - enabled: false - - production: true - proxyHeaders: xforwarded - httpRelativePath: "/" - configuration: "" - existingConfigmap: "" - extraStartupArgs: "" - initdbScriptsConfigMap: "" - command: [] - args: [] - extraEnvVarsCM: "" - extraEnvVarsSecret: "" - replicaCount: 3 - - containerPorts: - http: 8080 - https: 8443 - infinispan: 7800 - - resources: - limits: - memory: "2048Mi" - requests: - memory: "1024Mi" - - livenessProbe: - enabled: true - initialDelaySeconds: 300 - periodSeconds: 1 - timeoutSeconds: 5 - failureThreshold: 3 - successThreshold: 1 - - readinessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 1 - failureThreshold: 3 - successThreshold: 1 - - startupProbe: - enabled: false - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 1 - failureThreshold: 60 - successThreshold: 1 - - service: - type: "ClusterIP" - http: - enabled: true - ports: - http: 80 - https: 443 - nodePorts: - http: "" - https: "" - sessionAffinity: "None" - sessionAffinityConfig: - clusterIP: "" - loadBalancerIP: "" - loadBalancerSourceRanges: [] - externalTrafficPolicy: "Cluster" - annotations: - extraPorts: [] - extraHeadlessPorts: [] - headless: - annotations: - extraPorts: [] - - ingress: - enabled: true - ingressClassName: - pathType: "Prefix" - apiVersion: "" - hostname: - path: / - servicePort: "http" - annotations: -{% for key, val in dsc.ingress.annotations.items() %} - {{ key }}: "{{ val }}" -{% endfor %} - route.openshift.io/termination: "edge" - labels: - app: "keycloak" -{% for key, val in dsc.ingress.labels.items() %} - {{ key }}: "{{ val }}" -{% endfor %} - tls: true - selfSigned: false - extraHosts: [] -{% if dsc.global.environment == "production" %} - extraPaths: - - path: /admin/ - pathType: Prefix - backend: - service: - name: forbidden - port: - name: http - - path: /realms/{{ dsc.keycloak.managementRealm }}/ - pathType: Prefix - backend: - service: - name: forbidden - port: - name: http -{% endif %} - secrets: [] - extraRules: [] - - networkPolicy: - enabled: false - allowExternal: true - additionalRules: {} - - serviceAccount: - create: true - name: "" - automountServiceAccountToken: true - annotations: - extraLabels: - - rbac: - create: false - rules: [] - - pdb: - create: false - - autoscaling: - enabled: false - - metrics: - enabled: {{ dsc.global.metrics.enabled }} - serviceMonitor: - enabled: {{ dsc.global.metrics.enabled }} -{% if dsc.global.metrics.additionalLabels is defined %} - labels: {{ dsc.global.metrics.additionalLabels }} -{% endif %} - - keycloakConfigCli: - enabled: false - - postgresql: - enabled: false - # auth: - # postgresPassword: "" - # username: bn_keycloak - # password: "" - # database: bitnami_keycloak - # existingSecret: "" - # architecture: standalone - - ## External PostgreSQL configuration - ## All of these values are only used when postgresql.enabled is set to false - ## @param externalDatabase.host Database host - ## @param externalDatabase.port Database port number - ## @param externalDatabase.user Non-root username for Keycloak - ## @param externalDatabase.password Password for the non-root username for Keycloak - ## @param externalDatabase.database Keycloak database name - ## @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: - host: pg-cluster-keycloak-rw - port: 5432 - # user: "" - database: keycloak - # password: "" - existingSecret: pg-cluster-keycloak-app - # existingSecretHostKey: host - # existingSecretPortKey: port - existingSecretUserKey: username - # existingSecretDatabaseKey: database - existingSecretPasswordKey: password - - cache: - enabled: true - stackName: "kubernetes" - stackFile: "" - - logging: - output: "default" - level: "INFO" - - extraEnvVars: - - name: DSFR_THEME_HOME_URL - value: https:// - - name: DSFR_THEME_SERVICE_TITLE - value: Cloud Pi Native - - name: DSFR_THEME_BRAND_TOP - value: "Ministere
de l'interieur" - - name: DSFR_THEME_CONTACT_EMAIL - value: cloudpinative-relations@interieur.gouv.fr - initContainers: - - name: realm-ext-provider - image: "/curlimages/curl:8.12.1" - imagePullPolicy: IfNotPresent - command: - - sh - args: - - -c - - | - mkdir -p /emptydir/app-providers-dir && \ - curl -k -fsSL -o /emptydir/app-providers-dir/keycloak-theme-dsfr.jar && \ - curl -k -fsSL -o /emptydir/app-providers-dir/keycloak-franceconnect.jar - volumeMounts: - - name: empty-dir - mountPath: /emptydir -{% if dsc.proxy.enabled %} - env: - - name: HTTP_PROXY - value: - - name: HTTPS_PROXY - value: - - name: NO_PROXY - value: -{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-affinity.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/values/10-affinity.j2 deleted file mode 100644 index cd48ceb77..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-affinity.j2 +++ /dev/null @@ -1,2 +0,0 @@ -keycloak: - podAntiAffinityPreset: soft diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-platform.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/values/10-platform.j2 deleted file mode 100644 index bf2ec634d..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-platform.j2 +++ /dev/null @@ -1,12 +0,0 @@ -{% if dsc.global.platform == "openshift" %} -keycloak: - podSecurityContext: - enabled: false - - containerSecurityContext: - enabled: false - -cpn-ansible-job: - global: - platform: openshift -{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-proxy.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/values/10-proxy.j2 deleted file mode 100644 index 90d27235e..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-proxy.j2 +++ /dev/null @@ -1,10 +0,0 @@ -{% if dsc.proxy.enabled %} -keycloak: - extraEnvVars: - - name: HTTP_PROXY - value: - - name: HTTPS_PROXY - value: - - name: NO_PROXY - value: -{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-registry.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/values/10-registry.j2 deleted file mode 100644 index cf255ecf9..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-registry.j2 +++ /dev/null @@ -1,11 +0,0 @@ -keycloak: - global: - security: - allowInsecureImages: true -{% if dsc.global.imagePullSecrets is defined %} - imagePullSecrets: {{ dsc.global.imagePullSecrets | to_json }} -{% endif %} - image: - registry: - repository: bitnamilegacy/keycloak - pullPolicy: "IfNotPresent" \ No newline at end of file diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-tls.j2 b/roles/gitops/rendering-apps-files/templates/keycloak/values/10-tls.j2 deleted file mode 100644 index 1b03b36a3..000000000 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/10-tls.j2 +++ /dev/null @@ -1,8 +0,0 @@ -{% if dsc.ingress.tls.type == "tlsSecret" %} -keycloak: - ingress: - extraTls: - - hosts: - - - secretName: "{{ dsc.ingress.tls.tlsSecret.name }}" -{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/Chart.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/Chart.yaml.j2 similarity index 69% rename from roles/gitops/rendering-apps-files/templates/keycloak/Chart.yaml.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/Chart.yaml.j2 index 57eca402d..946b37010 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/Chart.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/Chart.yaml.j2 @@ -1,24 +1,27 @@ --- apiVersion: v2 -name: keycloak +name: keycloakx type: application -version: {{ dsc.keycloak.chartVersion }} +version: {{ dsc.keycloakx.chartVersion }} dependencies: - name: cluster alias: cluster version: {{ dsc.cloudnativepg.cluster.chartVersion }} repository: {{ dsc.cloudnativepg.cluster.helmRepoUrl }} -- name: keycloak - alias: keycloak - version: {{ dsc.keycloak.chartVersion }} - repository: "{{ dsc.keycloak.helmRepoUrl if 'oci://' in dsc.keycloak.helmRepoUrl else dsc.keycloak.helmRepoUrl ~ '/keycloak' }}" + condition: cluster.enabled +- name: keycloakx + alias: keycloakx + version: {{ dsc.keycloakx.chartVersion }} + repository: {{ dsc.keycloakx.helmRepoUrl }} - name: cpn-job alias: cpn-ansible-job version: {{ dsc.cpnAnsibleJob.chartVersion | quote }} repository: {{ dsc.cpnAnsibleJob.helmRepoUrl }} + condition: cpn-ansible-job.enabled {% if dsc.global.backup.velero.enabled | default(false) %} - name: dso-backup alias: dso-backup version: {{ dsc.global.backup.dsoBackup.chartVersion | default('1.0.0') | quote }} repository: {{ dsc.global.backup.dsoBackup.helmRepoUrl | default(dsc.cpnAnsibleJob.helmRepoUrl) }} + condition: dso-backup.enabled {% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/templates/post-conf-job.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/post-conf-job.yaml.j2 similarity index 76% rename from roles/gitops/rendering-apps-files/templates/keycloak/templates/post-conf-job.yaml.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/templates/post-conf-job.yaml.j2 index a2d4f567f..0aaea96be 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/templates/post-conf-job.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/post-conf-job.yaml.j2 @@ -1,9 +1,10 @@ +{% if dsc.keycloakx.ansibleJobEnabled %} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: keycloak-secret-access-role - namespace: {{ dsc.keycloak.namespace }} + name: keycloakx-secret-access-role + namespace: {{ dsc.keycloakx.namespace }} rules: # The "create" verb cannot apply to resourceNames, hence this first rule. # See: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-resources @@ -13,7 +14,7 @@ rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list"] - resourceNames: ["keycloak"] + resourceNames: ["keycloakx-admin-secret"] - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "update", "patch"] @@ -22,13 +23,14 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: keycloak-secret-access-role-binding - namespace: {{ dsc.keycloak.namespace }} + name: keycloakx-secret-access-role-binding + namespace: {{ dsc.keycloakx.namespace }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: keycloak-secret-access-role + name: keycloakx-secret-access-role subjects: - kind: ServiceAccount name: cpn-ansible-job - namespace: {{ dsc.keycloak.namespace }} + namespace: {{ dsc.keycloakx.namespace }} +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/templates/secret-admin.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/secret-admin.yaml.j2 new file mode 100644 index 000000000..bdce6e0b8 --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/secret-admin.yaml.j2 @@ -0,0 +1,10 @@ +kind: Secret +apiVersion: v1 +type: Opaque +metadata: + name: keycloakx-admin-secret + annotations: + avp.kubernetes.io/remove-missing: "true" +data: + KEYCLOAK_ADMIN: YWRtaW4= + KEYCLOAK_ADMIN_PASSWORD: diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/templates/secret-ansible.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/secret-ansible.yaml.j2 similarity index 88% rename from roles/gitops/rendering-apps-files/templates/keycloak/templates/secret-ansible.yaml.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/templates/secret-ansible.yaml.j2 index 8859f1366..cd85b64f2 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/templates/secret-ansible.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/secret-ansible.yaml.j2 @@ -1,7 +1,8 @@ +{% if dsc.keycloakx.ansibleJobEnabled %} apiVersion: v1 kind: Secret metadata: - name: ansible-secret + name: keycloakx-ansible-secret annotations: avp.kubernetes.io/remove-missing: "true" type: Opaque @@ -12,3 +13,4 @@ stringData: HTTPS_PROXY: NO_PROXY: {% endif %} +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/templates/service-compat.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/service-compat.yaml.j2 new file mode 100644 index 000000000..960cc35fc --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/service-compat.yaml.j2 @@ -0,0 +1,13 @@ +{% if dsc.keycloakx.subDomain != "keycloakx" %} +# Temporary alias after cutover: the codecentric chart always names its Service +# "-http", while in-cluster consumers still target the bare legacy name. +# Remove once every consumer points at "-http" (runbook §5/§9). +apiVersion: v1 +kind: Service +metadata: + name: {{ dsc.keycloakx.subDomain }} + namespace: {{ dsc.keycloakx.namespace }} +spec: + type: ExternalName + externalName: {{ dsc.keycloakx.subDomain }}-http.{{ dsc.keycloakx.namespace }}.svc.cluster.local +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/templates/users.yaml.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/users.yaml.j2 similarity index 77% rename from roles/gitops/rendering-apps-files/templates/keycloak/templates/users.yaml.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/templates/users.yaml.j2 index 5b6c33cdb..5febfa76c 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/templates/users.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/templates/users.yaml.j2 @@ -1,11 +1,13 @@ +{% if dsc.keycloakx.ansibleJobEnabled %} apiVersion: v1 kind: ConfigMap metadata: name: keycloak-users - namespace: {{ dsc.keycloak.namespace }} + namespace: {{ dsc.keycloakx.namespace }} data: users.csv: | username,surname,name,email,status admin@example.com,Admin,Admin,admin@example.com,active testuser@example.com,Test,User,testuser@example.com,active secondtestuser@example.com,SecondTest,User,secondtestuser@example.com,active +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/values/00-main.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/00-main.j2 new file mode 100644 index 000000000..39a30ecb4 --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/00-main.j2 @@ -0,0 +1,132 @@ +keycloakx: + # subDomain drives the codecentric chart's HTTP service name ("-http"). + # Parallel phase: "keycloakx" (temporary). Cutover: the legacy live name (on + # dso-integ the legacy fullnameOverride is "sso", NOT "keycloak" - check the + # live CR), aliased by templates/service-compat.yaml.j2 until consumers are + # repointed to "-http". + fullnameOverride: {{ dsc.keycloakx.subDomain }} + replicas: {{ dsc.keycloakx.replicas }} + command: + - /opt/keycloak/bin/kc.sh + args: + - start + image: + pullPolicy: IfNotPresent + http: + relativePath: "/" + proxy: + enabled: true + mode: xforwarded + http: + enabled: true + cache: + stack: default + metrics: + enabled: {{ dsc.global.metrics.enabled | lower }} + health: + enabled: true + resources: + limits: + memory: "2048Mi" + requests: + memory: "1024Mi" + networkPolicy: + enabled: false + + database: + vendor: postgres + hostname: pg-cluster-keycloak-rw + port: 5432 + database: keycloak + # Chart 7.2.3 only sets KC_DB_USERNAME from `username` (no existingSecretUserKey + # support). Without it JDBC falls back to the OS user, which only happens to be + # "keycloak" when running as UID 1000 - not under OpenShift's random UID. + username: keycloak + existingSecret: pg-cluster-keycloak-app + existingSecretKey: password + + extraEnvFrom: | + - secretRef: + name: keycloakx-admin-secret + + extraEnv: | + - name: KC_LOG_LEVEL + value: INFO + - name: KC_HOSTNAME + # Parallel phase: temporary host ({.keycloakx}). Switch to the production host at cutover. + value: https:// + - name: DSFR_THEME_HOME_URL + value: https:// + - name: DSFR_THEME_SERVICE_TITLE + value: Cloud Pi Native + - name: DSFR_THEME_BRAND_TOP + value: "Ministere
de l'interieur" + - name: DSFR_THEME_CONTACT_EMAIL + value: cloudpinative-relations@interieur.gouv.fr + + extraInitContainers: | + - name: realm-ext-provider + image: "/curlimages/curl:8.12.1" + imagePullPolicy: IfNotPresent + command: + - sh + args: + - -c + - | + mkdir -p /providers && \ + curl -k -fsSL -o /providers/keycloak-theme-dsfr.jar && \ + curl -k -fsSL -o /providers/keycloak-franceconnect.jar + volumeMounts: + - name: providers + mountPath: /providers +{% if dsc.proxy.enabled %} + env: + - name: HTTP_PROXY + value: + - name: HTTPS_PROXY + value: + - name: NO_PROXY + value: +{% endif %} + + extraVolumes: | + - name: providers + emptyDir: {} + + extraVolumeMounts: | + - name: providers + mountPath: /opt/keycloak/providers + + ingress: + enabled: true + ingressClassName: + servicePort: http + annotations: +{% for key, val in dsc.ingress.annotations.items() %} + {{ key }}: "{{ val }}" +{% endfor %} + route.openshift.io/termination: "edge" + labels: + app: keycloakx +{% for key, val in dsc.ingress.labels.items() %} + {{ key }}: "{{ val }}" +{% endfor %} + rules: + # Parallel phase: temporary host ({.keycloakx}). Switch to the production host at cutover. + - host: + paths: + - path: / + pathType: Prefix +{% if dsc.global.environment == "production" %} + - path: /admin/ + pathType: Prefix + serviceName: forbidden + servicePort: http + - path: /realms/{{ dsc.keycloakx.managementRealm }}/ + pathType: Prefix + serviceName: forbidden + servicePort: http +{% endif %} +{% if dsc.global.imagePullSecrets is defined %} + imagePullSecrets: {{ dsc.global.imagePullSecrets | to_json }} +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-affinity.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-affinity.j2 new file mode 100644 index 000000000..63b89a6ac --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-affinity.j2 @@ -0,0 +1,12 @@ +keycloakx: + affinity: | + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: +{% raw %} + {{- include "keycloak.selectorLabels" . | nindent 16 }} +{% endraw %} + topologyKey: kubernetes.io/hostname diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-platform.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-platform.j2 new file mode 100644 index 000000000..4c64310b8 --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-platform.j2 @@ -0,0 +1,13 @@ +{% if dsc.global.platform == "openshift" %} +keycloakx: + # `{}` does not drop the chart defaults (Helm merges maps): null the keys + # explicitly so restricted-v2 SCC can assign the namespace UID/fsGroup range. + podSecurityContext: + fsGroup: null + securityContext: + runAsUser: null + +cpn-ansible-job: + global: + platform: openshift +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-registry.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-registry.j2 new file mode 100644 index 000000000..e72036fdf --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-registry.j2 @@ -0,0 +1,4 @@ +keycloakx: + image: + repository: /keycloak/keycloak + tag: "{{ dsc.keycloakx.imageVersion }}" diff --git a/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-tls.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-tls.j2 new file mode 100644 index 000000000..06f2c3612 --- /dev/null +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/10-tls.j2 @@ -0,0 +1,13 @@ +keycloakx: + ingress: +{% if dsc.ingress.tls.type == "tlsSecret" %} + tls: + - hosts: + - + secretName: "{{ dsc.ingress.tls.tlsSecret.name }}" +{% else %} + tls: + - hosts: + - + secretName: keycloakx-tls +{% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/100-cnpg.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/100-cnpg.j2 similarity index 64% rename from roles/gitops/rendering-apps-files/templates/keycloak/values/100-cnpg.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/values/100-cnpg.j2 index d454bb8e1..35d76b809 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/100-cnpg.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/100-cnpg.j2 @@ -1,31 +1,39 @@ cluster: + # Adopted from the legacy `keycloak` app (step 7, 2026-10-06): legacy app removed + # first and Cluster confirmed alive (same UID, pods, PVCs) before enabling here. + # Prune=false,Delete=false below stays as a safety net. + enabled: true + nameOverride: "pg-cluster-keycloak" fullnameOverride: "pg-cluster-keycloak" cluster: + # Prune=false: no prune on ownership change. Delete=false: no cascade delete if + # the Application is removed (runbook §7). Same value as the legacy app. + annotations: + argocd.argoproj.io/sync-options: Prune=false,Delete=false primaryUpdateMethod: restart enablePDB: false - imageName: "/{{ dsc.keycloak.cnpg.imageName }}" + imageName: "/{{ dsc.keycloakx.cnpg.imageName }}" {% if dsc.global.imagePullSecrets is defined %} imagePullSecrets: {{ dsc.global.imagePullSecrets | to_json }} {% endif %} initdb: owner: "keycloak" database: "keycloak" - - # Require 1Gi of space per instance using default storage class + storage: - size: {{ dsc.keycloak.postgresPvcSize }} -{% if dsc.keycloak.postgresWalPvcSize is defined %} + size: {{ dsc.keycloakx.postgresPvcSize }} +{% if dsc.keycloakx.postgresWalPvcSize is defined %} walStorage: enabled: true - size: {{ dsc.keycloak.postgresWalPvcSize }} + size: {{ dsc.keycloakx.postgresWalPvcSize }} {% endif %} - + postgresql: parameters: max_worker_processes: "60" -{% if dsc.keycloak.postgresWalMaxSlotKeepSize is defined %} - max_slot_wal_keep_size: {{ dsc.keycloak.postgresWalMaxSlotKeepSize }} +{% if dsc.keycloakx.postgresWalMaxSlotKeepSize is defined %} + max_slot_wal_keep_size: {{ dsc.keycloakx.postgresWalMaxSlotKeepSize }} {% endif %} pg_hba: - host keycloak keycloak all md5 @@ -35,17 +43,19 @@ cluster: enabled: {{ dsc.global.metrics.enabled }} {% if dsc.global.backup.cnpg.enabled %} - backups: + # Same destination as the legacy app: on adoption the Cluster spec must not + # change (a different backup path here = real drift on the live Cluster). + backups: destinationPath: s3:///cnpg enabled: true endpointURL: retentionPolicy: 14d - s3: + s3: accessKey: secretKey: scheduledBackups: - name: pg-cluster-keycloak - schedule: 0 0 */6 * * * + schedule: 0 0 */6 * * * backupOwnerReference: self method: barmanObjectStore {% if dsc.global.backup.s3.endpointCA is defined %} diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/200-ansible-job.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/200-ansible-job.j2 similarity index 64% rename from roles/gitops/rendering-apps-files/templates/keycloak/values/200-ansible-job.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/values/200-ansible-job.j2 index 54fadfa38..9a53bcd9b 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/200-ansible-job.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/200-ansible-job.j2 @@ -1,4 +1,5 @@ cpn-ansible-job: + enabled: {{ dsc.keycloakx.ansibleJobEnabled | lower }} job: image: repository: "/cloud-pi-native/git-ansible" @@ -7,12 +8,12 @@ cpn-ansible-job: - /bin/sh - -c - | - git clone {{ dsc.keycloak.repoSocle.url }} -b {{ dsc.keycloak.repoSocle.revision }} socle && \ + git clone {{ dsc.keycloakx.repoSocle.url }} -b chore/migrate-keycloakx-dso-integ socle && \ cd socle && \ - ansible-playbook post-install/keycloak.yaml + ansible-playbook post-install/keycloakx.yaml extraEnvFrom: - - secretRef: - name: ansible-secret + - secretRef: + name: keycloakx-ansible-secret extraVolumes: - name: users-csv configMap: diff --git a/roles/gitops/rendering-apps-files/templates/keycloak/values/300-dso-backup.j2 b/roles/gitops/rendering-apps-files/templates/keycloakx/values/300-dso-backup.j2 similarity index 63% rename from roles/gitops/rendering-apps-files/templates/keycloak/values/300-dso-backup.j2 rename to roles/gitops/rendering-apps-files/templates/keycloakx/values/300-dso-backup.j2 index 0ddfaec1f..65cd69d04 100644 --- a/roles/gitops/rendering-apps-files/templates/keycloak/values/300-dso-backup.j2 +++ b/roles/gitops/rendering-apps-files/templates/keycloakx/values/300-dso-backup.j2 @@ -1,7 +1,8 @@ {% if dsc.global.backup.velero.enabled | default(false) %} dso-backup: + enabled: false global: - appName: keycloak + appName: keycloakx strategy: cnpg velero: backupNamePrefix: socle @@ -10,11 +11,10 @@ dso-backup: application: workloads: - type: statefulset - name: {{ dsc.keycloak.subDomain }} - replicas: 3 + name: {{ dsc.keycloakx.subDomain }} + replicas: {{ dsc.keycloakx.replicas }} podLabelSelector: - app.kubernetes.io/component: keycloak - app.kubernetes.io/instance: {{ dsc.global.gitOps.envName }}-{{ dsc.keycloak.namespace }} - app.kubernetes.io/name: keycloak + app.kubernetes.io/instance: {{ dsc.global.gitOps.envName }}-{{ dsc.keycloakx.namespace }} + app.kubernetes.io/name: keycloakx shutdownTimeout: 300 {% endif %} diff --git a/roles/gitops/rendering-apps-files/templates/kyverno/templates/cis.yml.j2 b/roles/gitops/rendering-apps-files/templates/kyverno/templates/cis.yml.j2 index 31df6413f..9405a3328 100644 --- a/roles/gitops/rendering-apps-files/templates/kyverno/templates/cis.yml.j2 +++ b/roles/gitops/rendering-apps-files/templates/kyverno/templates/cis.yml.j2 @@ -85,7 +85,7 @@ spec: - StatefulSet - Job namespaces: - - "{{ dsc.keycloak.namespace }}" + - "{{ dsc.keycloakx.namespace }}" - "{{ dsc.keycloakInfra.namespace }}" exclude: all: @@ -93,7 +93,7 @@ spec: kinds: - Job namespaces: - - "{{ dsc.keycloak.namespace }}" + - "{{ dsc.keycloakx.namespace }}" - "{{ dsc.keycloakInfra.namespace }}" names: - "pg-cluster-*" diff --git a/roles/gitops/rendering-apps-files/templates/observability/values/00-main.j2 b/roles/gitops/rendering-apps-files/templates/observability/values/00-main.j2 index d4424c97b..4529f249c 100644 --- a/roles/gitops/rendering-apps-files/templates/observability/values/00-main.j2 +++ b/roles/gitops/rendering-apps-files/templates/observability/values/00-main.j2 @@ -31,7 +31,7 @@ observatorium: groups: [/admin] # Default oidc config clientID: "account" - issuerURL: https:///realms/{{ dsc.keycloak.applicationRealm }} + issuerURL: https:///realms/{{ dsc.keycloakx.applicationRealm }} usernameClaim: "preferred_username" groupClaim: "groups" {% if dsc.exposedCA.type == "configmap" or dsc.exposedCA.type == "secret" %} @@ -79,9 +79,9 @@ grafana: grafanaNamespace: "{{ dsc.grafana.namespace }}" oauth: enabled: true - url: https:///realms/{{ dsc.keycloak.applicationRealm }} - id: - secret: + url: https:///realms/{{ dsc.keycloakx.applicationRealm }} + id: + secret: aud: grafana scopes: profile, email, openid, group groups_attribute_path: group diff --git a/roles/gitops/rendering-apps-files/templates/sonarqube/values/00-main.j2 b/roles/gitops/rendering-apps-files/templates/sonarqube/values/00-main.j2 index ae07a9443..1a051e797 100644 --- a/roles/gitops/rendering-apps-files/templates/sonarqube/values/00-main.j2 +++ b/roles/gitops/rendering-apps-files/templates/sonarqube/values/00-main.j2 @@ -59,9 +59,9 @@ sonarqube: sonar.auth.oidc.groupsSync: "true" sonar.auth.oidc.scopes: "openid generic" sonar.auth.oidc.loginStrategy.customClaim.name: "upn" - sonar.auth.oidc.clientId.secured: - sonar.auth.oidc.clientSecret.secured: - sonar.auth.oidc.issuerUri: "https:///realms/{{ dsc.keycloak.applicationRealm }}" + sonar.auth.oidc.clientId.secured: + sonar.auth.oidc.clientSecret.secured: + sonar.auth.oidc.issuerUri: "https:///realms/{{ dsc.keycloakx.applicationRealm }}" sonar.core.serverBaseURL: https:// sonar.plugins.risk.consent: "ACCEPTED" diff --git a/roles/gitops/rendering-apps-files/templates/tests/templates/secret-playwright.yaml.j2 b/roles/gitops/rendering-apps-files/templates/tests/templates/secret-playwright.yaml.j2 index c6ec8be53..69fba2ed2 100644 --- a/roles/gitops/rendering-apps-files/templates/tests/templates/secret-playwright.yaml.j2 +++ b/roles/gitops/rendering-apps-files/templates/tests/templates/secret-playwright.yaml.j2 @@ -45,8 +45,8 @@ stringData: KEYCLOAK_REDIRECT_URI: https:// KEYCLOAK_PROTOCOL: https KEYCLOAK_ADMIN_USERNAME: dsoadmin - KEYCLOAK_ADMIN_PASSWORD: - KEYCLOAK_REALM: {{ dsc.keycloak.applicationRealm }} + KEYCLOAK_ADMIN_PASSWORD: + KEYCLOAK_REALM: {{ dsc.keycloakx.applicationRealm }} KEYCLOAK_CLIENT_FRONTEND: console-frontend KEYCLOAK_CLIENT_BACKEND: console-backend {% if dsc.proxy.enabled %} diff --git a/roles/gitops/rendering-apps-files/vars/main.yaml b/roles/gitops/rendering-apps-files/vars/main.yaml index 47fb2519d..8241a9e78 100644 --- a/roles/gitops/rendering-apps-files/vars/main.yaml +++ b/roles/gitops/rendering-apps-files/vars/main.yaml @@ -67,11 +67,11 @@ values: return hs # We need this to be last so rootCA_block will be a sublevel of oidc.config oidc.config: | - issuer: https:///realms/{{ dsc.keycloak.applicationRealm }} + issuer: https:///realms/{{ dsc.keycloakx.applicationRealm }} requestedScopes: ["openid", "generic"] name: Keycloak - clientID: - clientSecret: + clientID: + clientSecret: rootCA_block: | rootCA: | diff --git a/roles/gitops/vault-secrets/tasks/main.yaml b/roles/gitops/vault-secrets/tasks/main.yaml index aa2691dc3..8cd738c1c 100644 --- a/roles/gitops/vault-secrets/tasks/main.yaml +++ b/roles/gitops/vault-secrets/tasks/main.yaml @@ -67,8 +67,8 @@ - name: Get Keycloak admin Secret from keycloak namespace kubernetes.core.k8s_info: kind: Secret - name: keycloak - namespace: "{{ dsc.keycloak.namespace }}" + name: keycloakx-admin-secret + namespace: "{{ dsc.keycloakx.namespace }}" register: keycloak_admin_secret # Set Argo CD admin password when required @@ -143,4 +143,4 @@ when: vault_secrets_post_install and keycloak_reset_password and not argo_infra_ns_check.failed ansible.builtin.include_tasks: argocd.yml loop: - - "{{ dsc.keycloak.namespace }}" + - "{{ dsc.keycloakx.namespace }}" diff --git a/roles/gitops/vault-secrets/vars/keycloak-admin-password.yaml b/roles/gitops/vault-secrets/vars/keycloak-admin-password.yaml index 61a6b122a..9920060d4 100644 --- a/roles/gitops/vault-secrets/vars/keycloak-admin-password.yaml +++ b/roles/gitops/vault-secrets/vars/keycloak-admin-password.yaml @@ -3,7 +3,7 @@ vault_secrets_post_install: true envs: - name: "{{ dsc_name }}" apps: - - argocd_app: "keycloak" + - argocd_app: "keycloakx" vault_values: auth: adminPassword: "{{ kc_adm_pass }}" diff --git a/roles/infra/keycloak-infra/templates/values/00-main.j2 b/roles/infra/keycloak-infra/templates/values/00-main.j2 index 4d22f80a3..50421f36d 100644 --- a/roles/infra/keycloak-infra/templates/values/00-main.j2 +++ b/roles/infra/keycloak-infra/templates/values/00-main.j2 @@ -318,7 +318,7 @@ initContainers: - sh args: - -c - - mkdir -p /emptydir/app-providers-dir && curl -k -L -f -S -o /emptydir/app-providers-dir/keycloak-theme-dsfr.jar {{ dsc.keycloak.pluginDownloadUrl }} + - mkdir -p /emptydir/app-providers-dir && curl -k -L -f -S -o /emptydir/app-providers-dir/keycloak-theme-dsfr.jar {{ dsc.keycloakx.pluginDownloadUrl }} volumeMounts: - name: empty-dir mountPath: /emptydir diff --git a/roles/kyverno/templates/cis.yml.j2 b/roles/kyverno/templates/cis.yml.j2 index 70c382fde..931085258 100644 --- a/roles/kyverno/templates/cis.yml.j2 +++ b/roles/kyverno/templates/cis.yml.j2 @@ -146,7 +146,7 @@ spec: - StatefulSet - Job namespaces: - - "{{ dsc.keycloak.namespace }}" + - "{{ dsc.keycloakx.namespace }}" - "{{ dsc.keycloakInfra.namespace }}" exclude: all: @@ -154,7 +154,7 @@ spec: kinds: - Job namespaces: - - "{{ dsc.keycloak.namespace }}" + - "{{ dsc.keycloakx.namespace }}" - "{{ dsc.keycloakInfra.namespace }}" names: - "pg-cluster-*" diff --git a/roles/socle-config/files/config.yaml b/roles/socle-config/files/config.yaml index 40790eb41..6d2ebd647 100644 --- a/roles/socle-config/files/config.yaml +++ b/roles/socle-config/files/config.yaml @@ -140,15 +140,18 @@ spec: cnpg: imageName: cloudnative-pg/postgresql:16.2 values: {} - keycloak: + keycloakx: installEnabled: true namespace: dso-keycloak + # Default host/fullname (dso-integ overrides it to "sso" in its CR). subDomain: keycloak - helmRepoUrl: oci://registry-1.docker.io/bitnamicharts + helmRepoUrl: https://codecentric.github.io/helm-charts repoSocle: url: https://github.com/cloud-pi-native/socle.git revision: main - postgresPvcSize: 1Gi + # Aligned on the live dso-integ CR (keycloak.postgresPvcSize/postgresWalPvcSize). + postgresPvcSize: 10Gi + postgresWalPvcSize: 10Gi pluginDownloadUrl: https://github.com/codegouvfr/keycloak-theme-dsfr/releases/download/v2.1.4/keycloak-theme-for-kc-26-and-above.jar providerDownloadUrl: https://github.com/InseeFr/Keycloak-FranceConnect/releases/download/7.5.0/keycloak-franceconnect-7.5.0.jar cnpg: @@ -156,6 +159,8 @@ spec: managementRealm: master applicationRealm: dso usersGitOpsEnabled: false + replicas: 1 + ansibleJobEnabled: false values: {} keycloakInfra: installEnabled: false diff --git a/roles/socle-config/files/cr-conf-dso-default.yaml b/roles/socle-config/files/cr-conf-dso-default.yaml index 6f867b3f6..342f9630a 100644 --- a/roles/socle-config/files/cr-conf-dso-default.yaml +++ b/roles/socle-config/files/cr-conf-dso-default.yaml @@ -85,7 +85,7 @@ spec: route.openshift.io/termination: edge tls: type: none - keycloak: {} + keycloakx: {} keycloakInfra: {} kyverno: {} nexus: {} diff --git a/roles/socle-config/files/releases.yaml b/roles/socle-config/files/releases.yaml index c10c54f15..4ae0853cc 100644 --- a/roles/socle-config/files/releases.yaml +++ b/roles/socle-config/files/releases.yaml @@ -60,9 +60,11 @@ spec: harbor: # https://artifacthub.io/packages/helm/harbor/harbor chartVersion: 1.17.1 - keycloak: - # https://artifacthub.io/packages/helm/bitnami/keycloak - chartVersion: 24.4.11 + keycloakx: + # https://codecentric.github.io/helm-charts (keycloakx) + chartVersion: "7.2.3" + # 26.6.4 step done first (https://github.com/keycloak/keycloak/issues/51304) + imageVersion: "26.7.2" keycloakInfra: # https://artifacthub.io/packages/helm/bitnami/keycloak chartVersion: 24.4.11 diff --git a/roles/socle-config/tasks/envs.yaml b/roles/socle-config/tasks/envs.yaml index afd388311..30bbac5d1 100644 --- a/roles/socle-config/tasks/envs.yaml +++ b/roles/socle-config/tasks/envs.yaml @@ -47,6 +47,7 @@ harbor: "{{ harbor_domain }}" harborNotary: "{{ dsc.harbor.subDomain }}-notary{{ root_domain }}" keycloak: "{{ keycloak_domain }}" + keycloakx: "{{ keycloakx_domain }}" nexus: "{{ nexus_domain }}" nexusDockerProxy: "{{ dsc.nexus.subDomain }}-docker-proxy{{ root_domain }}" sonarqube: "{{ sonar_domain }}" @@ -100,18 +101,26 @@ nameSpace: "cloudnativepg" customNamespacePrefix: "" syncWave: 10 - - argocd_app: keycloak + - argocd_app: keycloakx clusterName: "" nameSpace: "keycloak" customNamespacePrefix: "" syncWave: 20 vault_values: auth: - adminPassword: "{{ lookup('ansible.builtin.password', '/dev/null', length=24, chars=['ascii_letters', 'digits']) }}" + # Reuse the existing Vault value if there is one - only + # fall back to generating fresh on true first-bootstrap. + # Keycloak only reads this once, ever, so regenerating it + # on every run just breaks admin login. + adminPassword: >- + {{ + (((current_keycloakx_vault_values.secret | default({})).auth | default({})).adminPassword | default('')) + or lookup('ansible.builtin.password', '/dev/null', length=24, chars=['ascii_letters', 'digits']) + }} userTmpPassword: "{{ lookup('ansible.builtin.password', '/dev/null', length=24, chars=['ascii_letters', 'digits', '!@#$%^&*()-_=+']) }}" initcontainers: - pluginDownloadUrl: "{{ dsc.keycloak.pluginDownloadUrl }}" - providerDownloadUrl: "{{ dsc.keycloak.providerDownloadUrl }}" + pluginDownloadUrl: "{{ dsc.keycloakx.pluginDownloadUrl }}" + providerDownloadUrl: "{{ dsc.keycloakx.providerDownloadUrl }}" - argocd_app: gitlab clusterName: "" nameSpace: "gitlab" diff --git a/roles/socle-config/tasks/main.yaml b/roles/socle-config/tasks/main.yaml index 58eb62170..13b82fa6a 100644 --- a/roles/socle-config/tasks/main.yaml +++ b/roles/socle-config/tasks/main.yaml @@ -200,7 +200,8 @@ gitlab_domain: "{{ dsc.gitlab.domain | default(dsc.gitlab.subDomain ~ root_domain) }}" grafana_domain: "{{ dsc.grafana.domain | default(dsc.grafana.subDomain ~ root_domain) }}" harbor_domain: "{{ dsc.harbor.domain | default(dsc.harbor.subDomain ~ root_domain) }}" - keycloak_domain: "{{ dsc.keycloak.domain | default(dsc.keycloak.subDomain ~ root_domain) }}" + keycloak_domain: "{{ dsc.keycloakx.domain | default(dsc.keycloakx.subDomain ~ root_domain) }}" + keycloakx_domain: "{{ dsc.keycloakx.domain | default(dsc.keycloakx.subDomain ~ root_domain) }}" keycloakinfra_domain: "{{ dsc.keycloakInfra.domain | default(dsc.keycloakInfra.subDomain ~ infra_root_domain) }}" nexus_domain: "{{ dsc.nexus.domain | default(dsc.nexus.subDomain ~ root_domain) }}" sonar_domain: "{{ dsc.sonarqube.domain | default(dsc.sonarqube.subDomain ~ root_domain) }}" @@ -264,6 +265,24 @@ ansible.builtin.import_role: name: ca +# Keycloak only ever reads its bootstrap admin password once, at first +# boot. Fetching the current Vault value here lets envs.yaml prefer it +# over generating a fresh one on every full deploy (which would silently +# break admin login going forward). +- name: Get current keycloakx admin password from Vault + when: post_conf_job is not defined + community.hashi_vault.vault_kv2_get: + url: "https://{{ vaultinfra_domain }}" + namespace: "{{ dsc.vaultInfra.namespace }}" + engine_mount_point: "{{ vaultinfra_kv_name }}" + path: "env/{{ dsc_name }}/apps/keycloakx/values" + validate_certs: "{{ vaultinfra_cert_valid }}" + environment: + VAULT_TOKEN: "{{ vault_infra_token }}" + register: current_keycloakx_vault_values + ignore_errors: true + no_log: true + - name: Set envs fact when: post_conf_job is not defined ansible.builtin.include_tasks: diff --git a/roles/socle-config/templates/crd-conf-dso.yaml b/roles/socle-config/templates/crd-conf-dso.yaml index 6fc90405a..3d9ef1dae 100644 --- a/roles/socle-config/templates/crd-conf-dso.yaml +++ b/roles/socle-config/templates/crd-conf-dso.yaml @@ -1310,38 +1310,28 @@ spec: - type type: object type: object - keycloak: - description: Configuration for Keycloak. + keycloakInfra: + description: Configuration for Keycloak infrastructure instance. properties: installEnabled: - default: true - description: Specifies whether we should install Keycloak instance. + default: false + description: Specifies whether we should install Keycloak infrastructure instance. type: boolean namespace: - description: The namespace for Keycloak. + description: The namespace for Keycloak infrastructure instance. type: string subDomain: - description: The subdomain for Keycloak. + description: The subdomain for Keycloak infrastructure instance. type: string domain: - description: The domain for Keycloak. + description: The domain for Keycloak infrastructure instance. type: string helmRepoUrl: description: Keycloak Bitnami helm repository url. type: string chartVersion: - description: Keycloak Bitnami chart version (e.g., "16.0.3"). + description: Keycloak Bitnami chart version (e.g., "19.3.4"). type: string - repoSocle: - type: object - description: Configuration for the socle Git repository used by Ansible jobs for post-installation tasks. - properties: - url: - type: string - description: URL of the socle Git repository containing the Keycloak post-installation Ansible playbook. - revision: - type: string - description: Branch, tag, or commit hash of the Git repository to clone for Ansible jobs. postgresPvcSize: description: Size for postgres data pvc. type: string @@ -1361,21 +1351,9 @@ spec: pluginDownloadUrl: description: Plugins download Url. type: string - providerDownloadUrl: - description: Provider's download Url. - type: string - managementRealm: - description: Keycloak management realm. - type: string - applicationRealm: - description: Keycloak application realm. - type: string - usersGitOpsEnabled: - description: Specifies whether we should manage users with GitOps. - type: boolean values: description: | - You can add custom values for keycloak, they will be merged with roles/keycloak/templates/values/ + You can add custom values for keycloakInfra, they will be merged with roles/infra/keycloak-infra/templates/values/ https://github.com/bitnami/charts/tree/main/bitnami/keycloak https://github.com/bitnami/charts/blob/main/bitnami/keycloak/values.yaml type: object @@ -1387,35 +1365,44 @@ spec: imageName: description: Name of the container image, supporting both tags (`:`) and digests for deterministic and repeatable deployments (`:@sha256:`). See. https://cloudnative-pg.io/documentation/1.24/operator_capability_levels/#override-of-operand-images-through-the-crd type: string - values: - description: Extra helm values for CNPG cluster. See https://github.com/cloudnative-pg/charts/blob/main/charts/cluster/values.yaml - type: object - x-kubernetes-preserve-unknown-fields: true required: - installEnabled type: object - keycloakInfra: - description: Configuration for Keycloak infrastructure instance. + keycloakx: + description: Configuration for Keycloak (keycloakx / codecentric chart, official Keycloak image). properties: installEnabled: - default: false - description: Specifies whether we should install Keycloak infrastructure instance. + default: true + description: Specifies whether we should install the Keycloak (keycloakx) instance. type: boolean namespace: - description: The namespace for Keycloak infrastructure instance. + description: The namespace for Keycloak (keycloakx). type: string subDomain: - description: The subdomain for Keycloak infrastructure instance. + description: The subdomain for Keycloak (keycloakx). type: string domain: - description: The domain for Keycloak infrastructure instance. + description: The domain for Keycloak (keycloakx). type: string helmRepoUrl: - description: Keycloak Bitnami helm repository url. + description: Keycloak (keycloakx / codecentric) helm repository url. type: string chartVersion: - description: Keycloak Bitnami chart version (e.g., "19.3.4"). + description: Keycloak (keycloakx / codecentric) chart version (e.g., "7.2.3"). + type: string + imageVersion: + description: Keycloak (official quay.io/keycloak/keycloak image) version (e.g., "26.7.2"). type: string + repoSocle: + type: object + description: Configuration for the socle Git repository used by Ansible jobs for post-installation tasks. + properties: + url: + type: string + description: URL of the socle Git repository containing the Keycloak (keycloakx) post-installation Ansible playbook. + revision: + type: string + description: Branch, tag, or commit hash of the Git repository to clone for Ansible jobs. postgresPvcSize: description: Size for postgres data pvc. type: string @@ -1435,11 +1422,29 @@ spec: pluginDownloadUrl: description: Plugins download Url. type: string + providerDownloadUrl: + description: Provider's download Url. + type: string + managementRealm: + description: Keycloak (keycloakx) management realm. + type: string + applicationRealm: + description: Keycloak (keycloakx) application realm. + type: string + usersGitOpsEnabled: + description: Specifies whether we should manage users with GitOps. + type: boolean + ansibleJobEnabled: + description: Specifies whether the post-install Ansible job (realm/users config) is enabled. + type: boolean + replicas: + description: Number of Keycloak (keycloakx) replicas. + type: integer values: description: | - You can add custom values for keycloakInfra, they will be merged with roles/infra/keycloak-infra/templates/values/ - https://github.com/bitnami/charts/tree/main/bitnami/keycloak - https://github.com/bitnami/charts/blob/main/bitnami/keycloak/values.yaml + You can add custom values for keycloakx, they will be merged with roles/gitops/rendering-apps-files/templates/keycloakx/values/ + https://github.com/codecentric/helm-charts/tree/master/charts/keycloakx + https://github.com/codecentric/helm-charts/blob/master/charts/keycloakx/values.yaml type: object x-kubernetes-preserve-unknown-fields: true cnpg: @@ -1449,6 +1454,10 @@ spec: imageName: description: Name of the container image, supporting both tags (`:`) and digests for deterministic and repeatable deployments (`:@sha256:`). See. https://cloudnative-pg.io/documentation/1.24/operator_capability_levels/#override-of-operand-images-through-the-crd type: string + values: + description: Extra helm values for CNPG cluster. See https://github.com/cloudnative-pg/charts/blob/main/charts/cluster/values.yaml + type: object + x-kubernetes-preserve-unknown-fields: true required: - installEnabled type: object diff --git a/uninstall.yaml b/uninstall.yaml index c5bdc72ad..025a3d027 100644 --- a/uninstall.yaml +++ b/uninstall.yaml @@ -130,7 +130,7 @@ - name: "Suppression de l'instance Keycloak" kubernetes.core.helm: name: keycloak - release_namespace: "{{ dsc.keycloak.namespace }}" + release_namespace: "{{ dsc.keycloakx.namespace }}" state: absent wait: true tags: @@ -140,7 +140,7 @@ kubernetes.core.k8s: state: absent kind: Namespace - name: "{{ dsc.keycloak.namespace }}" + name: "{{ dsc.keycloakx.namespace }}" tags: - keycloak