Skip to content

Commit 0ab4633

Browse files
vakwetuclaude
authored andcommitted
[multiple] Fix SKMO federation CA bundle handling and SSL trust
Refactor how the CA bundle secret is managed across federation hooks to avoid relying on kustomize timing and make the logic self-healing: - federation/hook_controlplane_config.yml: Dynamically resolve the CA bundle secret name by reading the live OSCP state (using the existing caBundleSecretName if set, falling back to cifmw_custom_ca_certs_secret_name or 'custom-ca-certs'). Create or update the secret with the Keycloak CA, and patch the OSCP to set caBundleSecretName only when it is not yet set. - federation/run_openstack_auth_setup.yml: Build the full CA list used for auth testing by fetching the openstackclient pod's own system CA bundle as the base (which already trusts RHOSO internal CAs), then appending the ingress-operator CA. This avoids trust mismatches between controller-0 and the pod. - federation/defaults/main.yml: Rename cifmw_federation_ca_bundle_secret_name to cifmw_custom_ca_certs_secret_name to reflect that the variable is not federation-specific. - hooks/playbooks/skmo/update-central-ca-bundle.yaml: Merge the two stage-6 post-deploy playbooks (trust-leaf-ca.yaml and ensure-central-ca-bundle.yaml) into a single idempotent playbook that resolves the secret name dynamically, creates or updates the bundle with leaf region root CAs, patches the OSCP when caBundleSecretName is unset, and waits for the leaf CA fingerprint to appear in combined-ca-bundle before continuing. - kustomize_deploy/execute_step.yml: Add | string filters to OSDPD suffix handling so that YAML integer interpretation does not cause a TypeError when the timestamp suffix is checked or concatenated. Signed-off-by: Ade Lee <alee@redhat.com> Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 79aaded commit 0ab4633

7 files changed

Lines changed: 235 additions & 195 deletions

File tree

hooks/playbooks/skmo/ensure-central-ca-bundle.yaml

Lines changed: 0 additions & 28 deletions
This file was deleted.

hooks/playbooks/skmo/trust-leaf-ca.yaml

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
---
2+
- name: Update central CA bundle with leaf region CAs and wait for reconciliation
3+
hosts: localhost
4+
gather_facts: false
5+
vars:
6+
central_namespace: openstack
7+
leaf_namespace: openstack2
8+
controlplane_name: controlplane
9+
leaf_rootca_secret: rootca-public
10+
leaf_rootca_internal_secret: rootca-internal
11+
tasks:
12+
# -------------------------------------------------------------------------
13+
# Step 1 - determine which secret holds the central CA bundle.
14+
#
15+
# Priority:
16+
# 1. spec.tls.caBundleSecretName already set on the OSCP.
17+
# 2. cifmw_custom_ca_certs_secret_name variable (if set by caller).
18+
# 3. Hard default: "custom-ca-certs".
19+
# -------------------------------------------------------------------------
20+
- name: Read current OpenStackControlPlane state
21+
kubernetes.core.k8s_info:
22+
api_version: core.openstack.org/v1beta1
23+
kind: OpenStackControlPlane
24+
name: "{{ controlplane_name }}"
25+
namespace: "{{ central_namespace }}"
26+
register: _central_oscp_info
27+
28+
- name: Resolve CA bundle secret name
29+
ansible.builtin.set_fact:
30+
_ca_bundle_secret_name: >-
31+
{{
32+
((_central_oscp_info.resources | first).spec.tls | default({})).caBundleSecretName
33+
| default(cifmw_custom_ca_certs_secret_name | default('custom-ca-certs'))
34+
| default('custom-ca-certs')
35+
}}
36+
_oscp_has_ca_bundle: >-
37+
{{
38+
(
39+
((_central_oscp_info.resources | first).spec.tls | default({})).caBundleSecretName
40+
| default('')
41+
) | length > 0
42+
}}
43+
44+
# -------------------------------------------------------------------------
45+
# Step 2 - fetch the leaf region CA certs
46+
# -------------------------------------------------------------------------
47+
- name: Get leaf region rootca certs
48+
kubernetes.core.k8s_info:
49+
api_version: v1
50+
kind: Secret
51+
namespace: "{{ leaf_namespace }}"
52+
name: "{{ item }}"
53+
register: _leaf_certs
54+
loop:
55+
- "{{ leaf_rootca_secret }}"
56+
- "{{ leaf_rootca_internal_secret }}"
57+
58+
# -------------------------------------------------------------------------
59+
# Step 3 - get existing central CA bundle data (if secret already exists)
60+
# -------------------------------------------------------------------------
61+
- name: Look up existing central CA bundle secret
62+
kubernetes.core.k8s_info:
63+
api_version: v1
64+
kind: Secret
65+
namespace: "{{ central_namespace }}"
66+
name: "{{ _ca_bundle_secret_name }}"
67+
register: _existing_bundle
68+
69+
- name: Capture existing CA bundle secret data
70+
ansible.builtin.set_fact:
71+
_existing_bundle_data: >-
72+
{{
73+
(_existing_bundle.resources | first).data
74+
if _existing_bundle.resources | length > 0
75+
else {}
76+
}}
77+
78+
# -------------------------------------------------------------------------
79+
# Step 4 - create or update the secret, merging in the leaf CAs
80+
# -------------------------------------------------------------------------
81+
- name: Create or update central CA bundle secret with leaf region CAs
82+
kubernetes.core.k8s:
83+
state: present
84+
definition:
85+
apiVersion: v1
86+
kind: Secret
87+
metadata:
88+
name: "{{ _ca_bundle_secret_name }}"
89+
namespace: "{{ central_namespace }}"
90+
data: >-
91+
{{
92+
_existing_bundle_data | combine({
93+
'skmo-leaf-rootca.crt':
94+
_leaf_certs.results[0].resources[0].data['tls.crt'],
95+
'skmo-leaf-rootca-internal.crt':
96+
_leaf_certs.results[1].resources[0].data['tls.crt']
97+
})
98+
}}
99+
100+
# -------------------------------------------------------------------------
101+
# Step 5 - patch the OSCP to reference the secret when not already set
102+
# -------------------------------------------------------------------------
103+
- name: Patch OpenStackControlPlane to set caBundleSecretName (when unset)
104+
when: not _oscp_has_ca_bundle | bool
105+
kubernetes.core.k8s:
106+
state: patched
107+
definition:
108+
apiVersion: core.openstack.org/v1beta1
109+
kind: OpenStackControlPlane
110+
metadata:
111+
name: "{{ controlplane_name }}"
112+
namespace: "{{ central_namespace }}"
113+
spec:
114+
tls:
115+
caBundleSecretName: "{{ _ca_bundle_secret_name }}"
116+
117+
# -------------------------------------------------------------------------
118+
# Step 6 - wait for RHOSO to reconcile combined-ca-bundle.
119+
#
120+
# We compare the fingerprint of the leaf rootca cert we just added against
121+
# every cert in combined-ca-bundle, retrying until it appears.
122+
# -------------------------------------------------------------------------
123+
- name: Wait for leaf region CA to appear in combined-ca-bundle
124+
ansible.builtin.shell: |
125+
set -euo pipefail
126+
TMPDIR=$(mktemp -d)
127+
trap "rm -rf $TMPDIR" EXIT
128+
129+
echo "{{ _leaf_certs.results[0].resources[0].data['tls.crt'] }}" | \
130+
base64 -d > "$TMPDIR/leaf-ca.crt"
131+
FINGERPRINT=$(openssl x509 -noout -fingerprint -in "$TMPDIR/leaf-ca.crt" \
132+
| cut -d= -f2)
133+
134+
oc get secret combined-ca-bundle \
135+
-n {{ central_namespace }} \
136+
-o jsonpath='{.data.tls-ca-bundle\.pem}' \
137+
| base64 -d > "$TMPDIR/bundle.pem"
138+
139+
python3 - "$FINGERPRINT" "$TMPDIR/bundle.pem" <<'PYEOF'
140+
import sys, subprocess, re
141+
target, bundle_file = sys.argv[1], sys.argv[2]
142+
bundle = open(bundle_file).read()
143+
certs = re.findall(
144+
r'-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----',
145+
bundle, re.DOTALL
146+
)
147+
for cert in certs:
148+
r = subprocess.run(
149+
['openssl', 'x509', '-noout', '-fingerprint'],
150+
input=cert.encode(), capture_output=True
151+
)
152+
if target in r.stdout.decode():
153+
sys.exit(0)
154+
sys.exit(1)
155+
PYEOF
156+
args:
157+
executable: /bin/bash
158+
register: _ca_reconciled
159+
until: _ca_reconciled.rc == 0
160+
retries: 30
161+
delay: 10
162+
changed_when: false

roles/federation/defaults/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ cifmw_federation_deploy_multirealm: false
5353
# When left empty (the default) the original behaviour is preserved: a dedicated
5454
# 'keycloakca' secret is created and the kustomization patch sets
5555
# spec.tls.caBundleSecretName to 'keycloakca'.
56-
cifmw_federation_ca_bundle_secret_name: ""
56+
cifmw_custom_ca_certs_secret_name: ""
5757

5858
# =============================================================================
5959
# KEYCLOAK TEST USERS AND GROUPS - REALM 1

0 commit comments

Comments
 (0)