Skip to content

Commit 8511e7c

Browse files
Merge pull request #1061 from xek/federation_adoption
federation adoption
2 parents 9f9dab5 + f54ac47 commit 8511e7c

6 files changed

Lines changed: 205 additions & 1 deletion

File tree

tests/roles/development_environment/defaults/main.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,47 @@ run_pre_adoption_validation: true
1919
os_cloud_name: standalone
2020
source_osp_ssh_user: root
2121
use_hugepages: false
22+
# Enable federation tests that exercise OIDC authentication
23+
enable_federation: false
24+
# Command used to retrieve an OIDC-issued Keystone token from the source cloud.
25+
get_oidc_token_command: >-
26+
ssh -i {{ edpm_privatekey_path }} -o StrictHostKeyChecking=no {{ source_osp_ssh_user }}@{{ standalone_ip | default(edpm_node_ip) }} "source {{ federation_oidc_cloudrc_remote_path }} && openstack token issue -f value -c id"
27+
# Path on the source node where the rendered cloudrc file should be stored.
28+
federation_oidc_cloudrc_remote_path: /home/{{ source_osp_ssh_user }}/ci-framework-data/tmp/{{ federation_oidc_cloudrc_filename }}
29+
# Name of the cloudrc file rendered for OIDC authentication.
30+
federation_oidc_cloudrc_filename: kctestuser1
31+
federation_oidc_cloudrc_template: kctestuser1.j2
32+
# Location of the ingress operator CA used to seed the Keycloak trust bundle.
33+
federation_ingress_ca_path: ~/ci-framework-data/tmp/ingress-operator-ca.crt
34+
35+
# Federation defaults aligned with ci-framework
36+
cifmw_federation_keycloak_url: https://keycloak-openstack.apps-crc.testing
37+
cifmw_federation_keystone_url: https://keystone-public-openstack.apps-crc.testing
38+
cifmw_federation_horizon_url: https://horizon-openstack.apps-crc.testing
39+
cifmw_federation_keycloak_realm: openstack
40+
cifmw_federation_project_name: SSOproject
41+
cifmw_federation_domain: SSO
42+
cifmw_federation_idp_name: kcIDP
43+
cifmw_federation_keycloak_client_id: rhoso
44+
cifmw_federation_keycloak_client_secret: COX8bmlKAWn56XCGMrKQJj7dgHNAOl6f
45+
cifmw_federation_keycloak_testuser1_username: kctestuser1
46+
cifmw_federation_keycloak_testuser1_password: nomoresecrets1
47+
48+
cifmw_keystone_oidc_claim_prefix: "OIDC-"
49+
cifmw_keystone_oidc_response_type: "id_token"
50+
cifmw_keystone_oidc_scope: "openid profile email"
51+
cifmw_keystone_oidc_claim_delimiter: ";"
52+
cifmw_keystone_oidc_pass_user_info_as: "claims"
53+
cifmw_keystone_oidc_pass_claims_as: "both"
54+
cifmw_keystone_oidc_provider_metadata_url: "{{ cifmw_federation_keycloak_url }}/auth/realms/{{ cifmw_federation_keycloak_realm }}/.well-known/openid-configuration"
55+
cifmw_keystone_oidc_client_id: "{{ cifmw_federation_keycloak_client_id }}"
56+
cifmw_keystone_oidc_client_secret: "{{ cifmw_federation_keycloak_client_secret }}"
57+
cifmw_keystone_oidc_crypto_passphrase: supersecret
58+
cifmw_keystone_oidc_oauth_client_id: "{{ cifmw_federation_keycloak_client_id }}"
59+
cifmw_keystone_oidc_oauth_client_secret: "{{ cifmw_federation_keycloak_client_secret }}"
60+
cifmw_keystone_oidc_oauth_introspection_endpoint: "{{ cifmw_federation_keycloak_url }}/auth/realms/{{ cifmw_federation_keycloak_realm }}/protocol/openid-connect/token/introspect"
61+
cifmw_keystone_oidc_provider_name: "{{ cifmw_federation_idp_name }}"
62+
2263
# Supported storage backends for Cinder of the source cloud
2364
# must match those configured for the target cloud
2465
supported_volume_backends: []

tests/roles/development_environment/tasks/main.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,30 @@
7575
{{ openstack_command }} token issue -f value -c id
7676
register: before_adoption_token
7777

78+
- name: Render OIDC cloudrc
79+
when: enable_federation | default(false) | bool
80+
ansible.builtin.template:
81+
src: "{{ federation_oidc_cloudrc_template | default('tests/roles/development_environment/templates/kctestuser1.j2') }}"
82+
dest: "/tmp/{{ federation_oidc_cloudrc_filename }}"
83+
mode: "0600"
84+
85+
- name: Upload OIDC cloudrc to source cloud
86+
when: enable_federation | default(false) | bool
87+
ansible.builtin.shell:
88+
cmd: |
89+
{{ shell_header }}
90+
scp -o StrictHostKeyChecking=no -i {{ edpm_privatekey_path }} /tmp/{{ federation_oidc_cloudrc_filename }} {{ source_osp_ssh_user }}@{{ standalone_ip | default(edpm_node_ip) }}:{{ federation_oidc_cloudrc_remote_path }}
91+
92+
- name: Issue OIDC token
93+
no_log: "{{ use_no_log }}"
94+
when:
95+
- enable_federation | default(false) | bool
96+
ansible.builtin.shell:
97+
cmd: |
98+
{{ shell_header }}
99+
{{ get_oidc_token_command }}
100+
register: before_adoption_oidc_token
101+
78102
- name: Create credential for sanity checking its value after adoption
79103
no_log: "{{ use_no_log }}"
80104
ansible.builtin.shell:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
unset OS_CLOUD
2+
export OS_CACERT=/home/cloud-admin/full-ca-list.crt
3+
export OS_PROJECT_NAME="{{ cifmw_federation_project_name }}"
4+
export OS_PROJECT_DOMAIN_NAME="{{ cifmw_federation_domain }}"
5+
export OS_AUTH_URL="{{ cifmw_federation_keystone_url }}/v3"
6+
export OS_IDENTITY_API_VERSION=3
7+
export OS_AUTH_PLUGIN=openid
8+
export OS_AUTH_TYPE=v3oidcpassword
9+
export OS_USERNAME="{{ cifmw_federation_keycloak_testuser1_username }}"
10+
export OS_PASSWORD="{{ cifmw_federation_keycloak_testuser1_password }}"
11+
export OS_IDENTITY_PROVIDER="{{ cifmw_federation_idp_name }}"
12+
export OS_CLIENT_ID="{{ cifmw_federation_keycloak_client_id }}"
13+
export OS_CLIENT_SECRET="{{ cifmw_federation_keycloak_client_secret }}"
14+
export OS_OPENID_SCOPE="openid profile email"
15+
export OS_PROTOCOL=openid
16+
export OS_ACCESS_TOKEN_TYPE=access_token
17+
export OS_DISCOVERY_ENDPOINT="{{ cifmw_federation_keycloak_url }}/auth/realms/{{ cifmw_federation_keycloak_realm }}/.well-known/openid-configuration"

tests/roles/keystone_adoption/defaults/main.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,46 @@ keystone_patch: |
2727
type: LoadBalancer
2828
databaseInstance: openstack
2929
secret: osp-secret
30+
31+
keystone_patch_federation: |
32+
spec:
33+
tls:
34+
caBundleSecretName: keycloakca
35+
keystone:
36+
enabled: true
37+
apiOverride:
38+
route: {}
39+
template:
40+
customServiceConfig: |
41+
[token]
42+
expiration = 360000
43+
[federation]
44+
trusted_dashboard={{ cifmw_federation_horizon_url }}/dashboard/auth/websso/
45+
sso_callback_template=/etc/keystone/sso_callback_template.html
46+
[openid]
47+
remote_id_attribute=HTTP_OIDC_ISS
48+
[auth]
49+
methods = password,token,oauth1,mapped,application_credential,openid
50+
[trusted_ip]
51+
trusted_forwarded_for_header=True
52+
httpdCustomization:
53+
customConfigSecret: keystone-httpd-override
54+
override:
55+
service:
56+
internal:
57+
metadata:
58+
annotations:
59+
metallb.universe.tf/address-pool: internalapi
60+
metallb.universe.tf/allow-shared-ip: internalapi
61+
{% if ipv6_enabled | default(false) -%}
62+
metallb.universe.tf/loadBalancerIPs: {{ internalapi_prefix_ipv6 | default('2620:cf:cf:bbbb') }}::50
63+
{%- else -%}
64+
metallb.universe.tf/loadBalancerIPs: {{ internalapi_prefix | default('172.17.0') }}.80
65+
{%- endif %}
66+
67+
spec:
68+
type: LoadBalancer
69+
databaseInstance: openstack
70+
secret: osp-secret
71+
3072
keystone_retry_delay: 30

tests/roles/keystone_adoption/tasks/main.yaml

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
ansible.builtin.shell: |
2121
{{ shell_header }}
2222
{{ oc_header }}
23-
oc patch openstackcontrolplane openstack --type=merge --patch '{{ keystone_patch }}'
23+
if {{ enable_federation | default(false) | lower }} == true; then
24+
oc patch openstackcontrolplane openstack --type=merge --patch '{{ keystone_patch_federation }}'
25+
else
26+
oc patch openstackcontrolplane openstack --type=merge --patch '{{ keystone_patch }}'
27+
fi
2428
2529
- name: wait for Keystone to start up
2630
ansible.builtin.shell: |
@@ -74,6 +78,64 @@
7478
${BASH_ALIASES[openstack]} service list | awk "/ $service /{ print \$2; }" | xargs -r ${BASH_ALIASES[openstack]} service delete || true
7579
done
7680
81+
- name: Ensure Keycloak CA secret exists when federation enabled
82+
when: enable_federation | default(false) | bool
83+
ansible.builtin.shell: |
84+
{{ shell_header }}
85+
{{ oc_header }}
86+
87+
if ! oc get secret keycloakca >/dev/null 2>&1; then
88+
oc create secret generic keycloakca --from-file=KeyCloakCA={{ federation_ingress_ca_path }}
89+
fi
90+
91+
- name: Ensure Keystone httpd override secret exists when federation enabled
92+
when:
93+
- enable_federation | default(false) | bool
94+
ansible.builtin.shell: |
95+
{{ shell_header }}
96+
{{ oc_header }}
97+
98+
cat <<EOF | oc apply -f -
99+
apiVersion: v1
100+
kind: Secret
101+
metadata:
102+
name: keystone-httpd-override
103+
namespace: openstack
104+
type: Opaque
105+
stringData:
106+
federation.conf: |
107+
OIDCClaimPrefix "{{ cifmw_keystone_oidc_claim_prefix }}"
108+
OIDCResponseType "{{ cifmw_keystone_oidc_response_type }}"
109+
OIDCScope "{{ cifmw_keystone_oidc_scope }}"
110+
OIDCClaimDelimiter "{{ cifmw_keystone_oidc_claim_delimiter }}"
111+
OIDCPassUserInfoAs "{{ cifmw_keystone_oidc_pass_user_info_as }}"
112+
OIDCPassClaimsAs "{{ cifmw_keystone_oidc_pass_claims_as }}"
113+
OIDCProviderMetadataURL "{{ cifmw_keystone_oidc_provider_metadata_url }}"
114+
OIDCClientID "{{ cifmw_keystone_oidc_client_id }}"
115+
OIDCClientSecret "{{ cifmw_keystone_oidc_client_secret }}"
116+
OIDCCryptoPassphrase "{{ cifmw_keystone_oidc_crypto_passphrase }}"
117+
OIDCOAuthClientID "{{ cifmw_keystone_oidc_oauth_client_id }}"
118+
OIDCOAuthClientSecret "{{ cifmw_keystone_oidc_oauth_client_secret }}"
119+
OIDCOAuthIntrospectionEndpoint "{{ cifmw_keystone_oidc_oauth_introspection_endpoint }}"
120+
OIDCRedirectURI "{{ cifmw_federation_keystone_url }}/v3/auth/OS-FEDERATION/identity_providers/{{ cifmw_keystone_oidc_provider_name }}/protocols/openid/websso/"
121+
LogLevel debug
122+
123+
<LocationMatch "/v3/auth/OS-FEDERATION/identity_providers/{{ cifmw_keystone_oidc_provider_name }}/protocols/openid/websso">
124+
AuthType "openid-connect"
125+
Require valid-user
126+
</LocationMatch>
127+
128+
<Location "/v3/OS-FEDERATION/identity_providers/{{ cifmw_keystone_oidc_provider_name }}/protocols/openid/auth">
129+
AuthType oauth20
130+
Require valid-user
131+
</Location>
132+
133+
<LocationMatch "/v3/auth/OS-FEDERATION/websso/openid">
134+
AuthType "openid-connect"
135+
Require valid-user
136+
</LocationMatch>
137+
EOF
138+
77139
- name: Print session test token
78140
ansible.builtin.debug:
79141
var: before_adoption_token
@@ -92,6 +154,21 @@
92154
fi
93155
register: adoption_token_result
94156

157+
- name: Verify that pre-adoption OIDC token still works
158+
when:
159+
- enable_federation | default(false) | bool
160+
- before_adoption_oidc_token is defined
161+
- before_adoption_oidc_token.stdout is defined
162+
ansible.builtin.shell:
163+
cmd: |
164+
{{ shell_header }}
165+
{{ oc_header }}
166+
167+
alias openstack="oc exec -t openstackclient -- env -u OS_CLOUD - OS_AUTH_URL={{ auth_url }} OS_AUTH_TYPE=v3oidcaccesstoken OS_ACCESS_TOKEN={{ before_adoption_oidc_token.stdout }} openstack"
168+
169+
${BASH_ALIASES[openstack]} token issue -f json
170+
register: adoption_oidc_token_result
171+
95172
- name: Print credentials test token
96173
ansible.builtin.debug:
97174
var: before_adoption_token

tests/vars.sample.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ enable_tlse: false
77
# This flag enables unique pod names for the adopted OpenStack services.
88
enable_unique_pod_names: false
99

10+
# Enable federation (OIDC) validation during adoption
11+
enable_federation: false
12+
1013
# Source MariaDB Galera cluster members {name:IP} pairs of addresses on internal_api network (also in additional cells) for pre-adoption checks.
1114
# Defaults provided for a single-cell case. Complete the lists for an HA multi-cell adoption.
1215
source_galera_members:

0 commit comments

Comments
 (0)