|
9 | 9 | block: |
10 | 10 | # ── Namespace ────────────────────────────────────────────────────────────── |
11 | 11 | - name: Ensure Keycloak namespace exists |
12 | | - ansible.builtin.command: |
13 | | - cmd: >- |
14 | | - k3s kubectl create namespace {{ keycloak_namespace }} |
15 | | - --dry-run=client -o yaml |
16 | | - environment: |
17 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
18 | | - register: _keycloak_namespace_yaml |
19 | | - changed_when: false |
20 | | - when: not ansible_check_mode |
21 | | - |
22 | | - - name: Apply Keycloak namespace manifest |
23 | | - ansible.builtin.command: |
24 | | - cmd: k3s kubectl apply -f - |
25 | | - stdin: "{{ _keycloak_namespace_yaml.stdout }}" |
26 | | - environment: |
27 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
28 | | - register: _keycloak_namespace_apply |
29 | | - changed_when: >- |
30 | | - 'created' in (_keycloak_namespace_apply.stdout | default('')) |
| 12 | + kubernetes.core.k8s: |
| 13 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 14 | + state: present |
| 15 | + definition: |
| 16 | + apiVersion: v1 |
| 17 | + kind: Namespace |
| 18 | + metadata: |
| 19 | + name: "{{ keycloak_namespace }}" |
31 | 20 | when: not ansible_check_mode |
32 | 21 |
|
33 | 22 | # ── OpenBao: generate + persist credentials ───────────────────────────────── |
|
155 | 144 | when: not ansible_check_mode |
156 | 145 |
|
157 | 146 | # The Secret must exist before the Keycloak CR is applied: the operator reads |
158 | | - # spec.bootstrapAdmin.user.secret at first creation. Render via kubectl |
159 | | - # dry-run|apply so the credentials never touch the host filesystem. |
160 | | - - name: Generate master bootstrap-admin Secret manifest |
161 | | - ansible.builtin.command: |
162 | | - cmd: >- |
163 | | - k3s kubectl create secret generic {{ keycloak_bootstrap_admin_secret_name }} |
164 | | - --namespace {{ keycloak_namespace }} |
165 | | - --from-literal=username={{ keycloak_bootstrap_admin_username }} |
166 | | - --from-literal=password={{ _keycloak_bootstrap_admin_password }} |
167 | | - --dry-run=client -o yaml |
168 | | - environment: |
169 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
170 | | - register: _keycloak_bootstrap_admin_secret_yaml |
171 | | - changed_when: false |
172 | | - no_log: "{{ not (armory_log_nolog | default(false) | bool) }}" |
173 | | - when: not ansible_check_mode |
174 | | - |
| 147 | + # spec.bootstrapAdmin.user.secret at first creation. |
175 | 148 | - name: Apply master bootstrap-admin Secret in the Keycloak namespace |
176 | | - ansible.builtin.command: |
177 | | - cmd: k3s kubectl apply -f - |
178 | | - stdin: "{{ _keycloak_bootstrap_admin_secret_yaml.stdout }}" |
179 | | - environment: |
180 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
181 | | - register: _keycloak_bootstrap_admin_secret_apply |
182 | | - changed_when: >- |
183 | | - 'configured' in (_keycloak_bootstrap_admin_secret_apply.stdout | default('')) or |
184 | | - 'created' in (_keycloak_bootstrap_admin_secret_apply.stdout | default('')) |
| 149 | + kubernetes.core.k8s: |
| 150 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 151 | + state: present |
| 152 | + definition: |
| 153 | + apiVersion: v1 |
| 154 | + kind: Secret |
| 155 | + metadata: |
| 156 | + name: "{{ keycloak_bootstrap_admin_secret_name }}" |
| 157 | + namespace: "{{ keycloak_namespace }}" |
| 158 | + type: Opaque |
| 159 | + stringData: |
| 160 | + username: "{{ keycloak_bootstrap_admin_username }}" |
| 161 | + password: "{{ _keycloak_bootstrap_admin_password }}" |
185 | 162 | no_log: "{{ not (armory_log_nolog | default(false) | bool) }}" |
186 | 163 | when: not ansible_check_mode |
187 | 164 |
|
|
198 | 175 | when: not (use_declarative_ca_distribution | default(false) | bool) |
199 | 176 |
|
200 | 177 | - name: Apply Keycloak VaultConnection and VaultAuth resources |
201 | | - ansible.builtin.command: |
202 | | - cmd: k3s kubectl apply -f - |
203 | | - stdin: "{{ lookup('template', 'vaultconnection.yaml.j2') }}\n---\n{{ lookup('template', 'vaultauth.yaml.j2') }}" |
204 | | - environment: |
205 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
206 | | - register: _keycloak_vault_auth_apply |
207 | | - changed_when: >- |
208 | | - 'configured' in (_keycloak_vault_auth_apply.stdout | default('')) or |
209 | | - 'created' in (_keycloak_vault_auth_apply.stdout | default('')) |
| 178 | + kubernetes.core.k8s: |
| 179 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 180 | + state: present |
| 181 | + definition: >- |
| 182 | + {{ (lookup('template', 'vaultconnection.yaml.j2') | from_yaml_all | list) |
| 183 | + + (lookup('template', 'vaultauth.yaml.j2') | from_yaml_all | list) }} |
210 | 184 | when: not ansible_check_mode |
211 | 185 |
|
212 | 186 | - name: Apply Keycloak VaultStaticSecret (DB credentials) |
213 | | - ansible.builtin.command: |
214 | | - cmd: k3s kubectl apply -f - |
215 | | - stdin: "{{ lookup('template', 'vaultstaticsecret.yaml.j2') }}" |
216 | | - environment: |
217 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
218 | | - register: _keycloak_vss_apply |
219 | | - changed_when: >- |
220 | | - 'configured' in (_keycloak_vss_apply.stdout | default('')) or |
221 | | - 'created' in (_keycloak_vss_apply.stdout | default('')) |
| 187 | + kubernetes.core.k8s: |
| 188 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 189 | + state: present |
| 190 | + definition: "{{ lookup('template', 'vaultstaticsecret.yaml.j2') | from_yaml_all | list }}" |
222 | 191 | when: not ansible_check_mode |
223 | 192 |
|
224 | 193 | - name: Apply Keycloak VaultStaticSecret (realm-admin login mirror) |
225 | | - ansible.builtin.command: |
226 | | - cmd: k3s kubectl apply -f - |
227 | | - stdin: "{{ lookup('template', 'vaultstaticsecret_realm_admin.yaml.j2') }}" |
228 | | - environment: |
229 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
230 | | - register: _keycloak_realm_admin_vss_apply |
231 | | - changed_when: >- |
232 | | - 'configured' in (_keycloak_realm_admin_vss_apply.stdout | default('')) or |
233 | | - 'created' in (_keycloak_realm_admin_vss_apply.stdout | default('')) |
| 194 | + kubernetes.core.k8s: |
| 195 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 196 | + state: present |
| 197 | + definition: "{{ lookup('template', 'vaultstaticsecret_realm_admin.yaml.j2') | from_yaml_all | list }}" |
234 | 198 | when: not ansible_check_mode |
235 | 199 |
|
236 | 200 | - name: Wait for keycloak-db-secret to be synced by VSO |
|
268 | 232 |
|
269 | 233 | # ── PostgreSQL StatefulSet ────────────────────────────────────────────────── |
270 | 234 | - name: Apply PostgreSQL StatefulSet and Service |
271 | | - ansible.builtin.command: |
272 | | - cmd: k3s kubectl apply -f - |
273 | | - stdin: "{{ lookup('template', 'postgres.yaml.j2') }}" |
274 | | - environment: |
275 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
276 | | - register: _keycloak_pg_apply |
277 | | - changed_when: >- |
278 | | - 'configured' in (_keycloak_pg_apply.stdout | default('')) or |
279 | | - 'created' in (_keycloak_pg_apply.stdout | default('')) |
| 235 | + kubernetes.core.k8s: |
| 236 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 237 | + state: present |
| 238 | + definition: "{{ lookup('template', 'postgres.yaml.j2') | from_yaml_all | list }}" |
280 | 239 | when: |
281 | 240 | - not ansible_check_mode |
282 | 241 | - keycloak_postgresql_enabled | bool |
|
314 | 273 | - keycloak_postgresql_enabled | bool |
315 | 274 | - keycloak_pg_tls_enabled | bool |
316 | 275 |
|
317 | | - - name: Create Keycloak Postgres CA ConfigMap manifest |
318 | | - ansible.builtin.command: |
319 | | - cmd: >- |
320 | | - k3s kubectl create configmap {{ keycloak_pg_tls_ca_configmap_name }} |
321 | | - --namespace {{ keycloak_namespace }} |
322 | | - --from-file={{ keycloak_pg_tls_ca_file_name }}={{ keycloak_pg_tls_ca_bundle_path }} |
323 | | - --dry-run=client -o yaml |
324 | | - environment: |
325 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
326 | | - register: _keycloak_pg_ca_configmap_yaml |
327 | | - changed_when: false |
| 276 | + # The bundle is written root-owned by the common prepare task (under become), |
| 277 | + # so it must be read by a module that runs on the target under become — a |
| 278 | + # controller-side lookup('file', …) runs as the unprivileged user and is |
| 279 | + # denied. slurp reads it as root; b64decode inlines the PEM into the ConfigMap. |
| 280 | + - name: Read Postgres CA bundle for ConfigMap (privileged read under become) |
| 281 | + ansible.builtin.slurp: |
| 282 | + src: "{{ keycloak_pg_tls_ca_bundle_path }}" |
| 283 | + register: _keycloak_pg_ca_bundle |
328 | 284 | when: |
329 | 285 | - not ansible_check_mode |
330 | 286 | - keycloak_postgresql_enabled | bool |
331 | 287 | - keycloak_pg_tls_enabled | bool |
332 | 288 |
|
333 | 289 | - name: Apply Keycloak Postgres CA ConfigMap |
334 | | - ansible.builtin.command: |
335 | | - cmd: k3s kubectl apply -f - |
336 | | - stdin: "{{ _keycloak_pg_ca_configmap_yaml.stdout }}" |
337 | | - environment: |
338 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
339 | | - register: _keycloak_pg_ca_configmap_apply |
340 | | - changed_when: >- |
341 | | - 'configured' in (_keycloak_pg_ca_configmap_apply.stdout | default('')) or |
342 | | - 'created' in (_keycloak_pg_ca_configmap_apply.stdout | default('')) |
| 290 | + kubernetes.core.k8s: |
| 291 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 292 | + state: present |
| 293 | + definition: |
| 294 | + apiVersion: v1 |
| 295 | + kind: ConfigMap |
| 296 | + metadata: |
| 297 | + name: "{{ keycloak_pg_tls_ca_configmap_name }}" |
| 298 | + namespace: "{{ keycloak_namespace }}" |
| 299 | + # The data key is variable-named; build the dict in one Jinja |
| 300 | + # expression so the KEY is evaluated (Ansible does not template dict keys). |
| 301 | + data: "{{ {keycloak_pg_tls_ca_file_name: (_keycloak_pg_ca_bundle.content | b64decode)} }}" |
343 | 302 | when: |
344 | 303 | - not ansible_check_mode |
345 | 304 | - keycloak_postgresql_enabled | bool |
|
468 | 427 |
|
469 | 428 | # ── Keycloak custom resource ──────────────────────────────────────────────── |
470 | 429 | - name: Apply Keycloak custom resource |
471 | | - ansible.builtin.command: |
472 | | - cmd: k3s kubectl apply -f - |
473 | | - stdin: "{{ lookup('template', 'keycloak.yaml.j2') }}" |
474 | | - environment: |
475 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
476 | | - register: _keycloak_cr_apply |
477 | | - changed_when: >- |
478 | | - 'configured' in (_keycloak_cr_apply.stdout | default('')) or |
479 | | - 'created' in (_keycloak_cr_apply.stdout | default('')) |
| 430 | + kubernetes.core.k8s: |
| 431 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 432 | + state: present |
| 433 | + definition: "{{ lookup('template', 'keycloak.yaml.j2') | from_yaml_all | list }}" |
480 | 434 | when: not ansible_check_mode |
481 | 435 |
|
482 | 436 | - name: Wait for Keycloak custom resource to become Ready |
|
546 | 500 |
|
547 | 501 | # ── Realm import ──────────────────────────────────────────────────────────── |
548 | 502 | - name: Apply Keycloak realm import |
549 | | - ansible.builtin.command: |
550 | | - cmd: k3s kubectl apply -f - |
551 | | - stdin: "{{ lookup('template', 'realmimport.yaml.j2') }}" |
552 | | - environment: |
553 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
554 | | - register: _keycloak_realm_apply |
555 | | - changed_when: >- |
556 | | - 'configured' in (_keycloak_realm_apply.stdout | default('')) or |
557 | | - 'created' in (_keycloak_realm_apply.stdout | default('')) |
| 503 | + kubernetes.core.k8s: |
| 504 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 505 | + state: present |
| 506 | + definition: "{{ lookup('template', 'realmimport.yaml.j2') | from_yaml_all | list }}" |
558 | 507 | no_log: "{{ not (armory_log_nolog | default(false) | bool) }}" |
559 | 508 | when: not ansible_check_mode |
560 | 509 |
|
|
581 | 530 |
|
582 | 531 | # ── Ingress (edge TLS at nginx) ───────────────────────────────────────────── |
583 | 532 | - name: Apply Keycloak Ingress |
584 | | - ansible.builtin.command: |
585 | | - cmd: k3s kubectl apply -f - |
586 | | - stdin: "{{ lookup('template', 'ingress.yaml.j2') }}" |
587 | | - environment: |
588 | | - KUBECONFIG: "{{ keycloak_kubeconfig_path }}" |
589 | | - register: _keycloak_ingress_apply |
590 | | - changed_when: >- |
591 | | - 'configured' in (_keycloak_ingress_apply.stdout | default('')) or |
592 | | - 'created' in (_keycloak_ingress_apply.stdout | default('')) |
| 533 | + kubernetes.core.k8s: |
| 534 | + kubeconfig: "{{ keycloak_kubeconfig_path }}" |
| 535 | + state: present |
| 536 | + definition: "{{ lookup('template', 'ingress.yaml.j2') | from_yaml_all | list }}" |
593 | 537 | when: |
594 | 538 | - not ansible_check_mode |
595 | 539 | - keycloak_ingress_enabled | bool |
|
0 commit comments