diff --git a/roles/hosted_engine_setup/files/keycloak_he_pause_host.sh b/roles/hosted_engine_setup/files/keycloak_he_pause_host.sh new file mode 100644 index 00000000..27282229 --- /dev/null +++ b/roles/hosted_engine_setup/files/keycloak_he_pause_host.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# This file is a part of the hosted-engine deployment process +# The goal is to add a temporary URI to the ovirt-engine-internal client, and return the original value on the second pass. + +# KEYCLOAK_URL get from ENV: "https://{{ he_fqdn }}/ovirt-engine-auth" +# HOST_FQDN get from ENV: "{{ he_host_name }}" +# PASSWORD get from ENV: "{{ he_admin_password }}" + +KEYCLOAK_REALM=ovirt-internal +KEYCLOAK_CLIENT_ID=ovirt-engine-internal +USERNAME="admin" +REDIRECT_URIS_TMPFILE=/tmp/keycloak_redirect_uris.tmp + +TKN=$(curl --insecure --silent -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \ + --header "content-type: application/x-www-form-urlencoded" \ + --data-urlencode "client_id=admin-cli" \ + --data-urlencode "username=${USERNAME}" \ + --data-urlencode "password=${PASSWORD}" \ + --data-urlencode "grant_type=password" | jq --raw-output '.access_token' ) + +CLIENT_DATA=$(curl --insecure --silent -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients?clientId=${KEYCLOAK_CLIENT_ID}" \ + --header "Accept: application/json" \ + --header "Authorization: Bearer $TKN") + +CLIENT_ID=$(echo $CLIENT_DATA | jq -r '.[0].id') + +if [ -f "$REDIRECT_URIS_TMPFILE" ]; then + # Second pass + # Restore original redirectUris parameters + NEW_URI=$(<$REDIRECT_URIS_TMPFILE) + UPDATED_CLIENT_DATA=$(echo $CLIENT_DATA | jq --argjson new_uri "$NEW_URI" '.[0] | .redirectUris = $new_uri') + rm -rf $REDIRECT_URIS_TMPFILE +else + # First pass + # Save original redirectUris parameters + REDIRECT_URIS=$(echo $CLIENT_DATA | jq -r '.[0].redirectUris') + echo "$REDIRECT_URIS" > $REDIRECT_URIS_TMPFILE + + # Add a temporary URI to redirectUris + NEW_URI="https://${HOST_FQDN}:6900*" + UPDATED_CLIENT_DATA=$(echo $CLIENT_DATA | jq --arg new_uri "$NEW_URI" '.[0] | .redirectUris += [$new_uri]') +fi + +# Update client data +curl --insecure --silent --http1.0 -X PUT "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients/${CLIENT_ID}" \ + --header "Authorization: Bearer $TKN" \ + --header "Content-Type: application/json" \ + --data-raw "$UPDATED_CLIENT_DATA" diff --git a/roles/hosted_engine_setup/tasks/bootstrap_local_vm/05_add_host.yml b/roles/hosted_engine_setup/tasks/bootstrap_local_vm/05_add_host.yml index 3d40368e..6cf49a12 100644 --- a/roles/hosted_engine_setup/tasks/bootstrap_local_vm/05_add_host.yml +++ b/roles/hosted_engine_setup/tasks/bootstrap_local_vm/05_add_host.yml @@ -121,6 +121,13 @@ loop_control: loop_var: after_add_host_item register: include_after_add_host_results + - name: Configure the Keycloak to be accessed over the first host + block: + - include_tasks: ../keycloak_config_for_he_pause_host.yml + when: + - he_pause_host|bool + - he_enable_keycloak|bool + delegate_to: "{{ groups.engine[0] }}" - name: Pause the execution to let the user interactively reconfigure the host block: - name: Let the user connect to the bootstrap engine VM to manually fix host configuration @@ -130,6 +137,13 @@ eventually remediate it, please continue only when the host is listed as 'up' - include_tasks: ../pause_execution.yml when: he_pause_host|bool + - name: Configure the Keycloak to be accessed over the Engine FQDN + block: + - include_tasks: ../keycloak_restore_after_he_pause_host.yml + when: + - he_pause_host|bool + - he_enable_keycloak|bool + delegate_to: "{{ groups.engine[0] }}" # refresh the auth token after a long operation to avoid having it expired - include_tasks: ../auth_revoke.yml - include_tasks: ../auth_sso.yml diff --git a/roles/hosted_engine_setup/tasks/keycloak_config_for_he_pause_host.yml b/roles/hosted_engine_setup/tasks/keycloak_config_for_he_pause_host.yml new file mode 100644 index 00000000..cc37854d --- /dev/null +++ b/roles/hosted_engine_setup/tasks/keycloak_config_for_he_pause_host.yml @@ -0,0 +1,40 @@ +--- +- name: Configure Apache + block: + - name: Replace OIDCProviderMetadataURL value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCProviderMetadataURL https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_host_address }}:6900\g<2>' + - name: Replace OIDCRedirectURI value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCRedirectURI https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_host_address }}:6900\g<2>' + - name: Replace OIDCDefaultURL value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCDefaultURL https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_host_address }}:6900\g<2>' + - name: Replace OIDCOAuthIntrospectionEndpoint value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCOAuthIntrospectionEndpoint https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_host_address }}:6900\g<2>' +- name: Configure Keycloak + block: + - name: Copy keycloak_he_pause_host.sh + ansible.builtin.copy: + src: /usr/share/ansible/collections/ansible_collections/ovirt/ovirt/roles/hosted_engine_setup/files/keycloak_he_pause_host.sh + dest: /tmp/keycloak_he_pause_host.sh + mode: '0644' + - name: Run keycloak_he_pause_host.sh + shell: /bin/bash /tmp/keycloak_he_pause_host.sh + environment: + KEYCLOAK_URL: "https://{{ he_fqdn }}/ovirt-engine-auth" + HOST_FQDN: "{{ he_host_name }}" + PASSWORD: "{{ he_admin_password }}" +- name: Restart httpd service + ansible.builtin.service: + name: httpd + state: restarted diff --git a/roles/hosted_engine_setup/tasks/keycloak_restore_after_he_pause_host.yml b/roles/hosted_engine_setup/tasks/keycloak_restore_after_he_pause_host.yml new file mode 100644 index 00000000..14735ea6 --- /dev/null +++ b/roles/hosted_engine_setup/tasks/keycloak_restore_after_he_pause_host.yml @@ -0,0 +1,40 @@ +--- +- name: Configure Apache + block: + - name: Restore original OIDCProviderMetadataURL value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCProviderMetadataURL https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_fqdn }}\g<2>' + - name: Restore original OIDCRedirectURI value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCRedirectURI https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_fqdn }}\g<2>' + - name: Restore original OIDCDefaultURL value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCDefaultURL https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_fqdn }}\g<2>' + - name: Restore original OIDCOAuthIntrospectionEndpoint value + ansible.builtin.replace: + path: /etc/httpd/conf.d/internalsso-openidc.conf + regexp: '(^\s+OIDCOAuthIntrospectionEndpoint https:\/\/).+(\/ovirt-engine.*)' + replace: '\g<1>{{ he_fqdn }}\g<2>' +- name: Configure Keycloak + block: + - name: Copy keycloak_he_pause_host.sh + ansible.builtin.copy: + src: /usr/share/ansible/collections/ansible_collections/ovirt/ovirt/roles/hosted_engine_setup/files/keycloak_he_pause_host.sh + dest: /tmp/keycloak_he_pause_host.sh + mode: '0644' + - name: Run keycloak_he_pause_host.sh + shell: /bin/bash /tmp/keycloak_he_pause_host.sh + environment: + KEYCLOAK_URL: "https://{{ he_fqdn }}/ovirt-engine-auth" + HOST_FQDN: "{{ he_host_name }}" + PASSWORD: "{{ he_admin_password }}" +- name: Restart httpd service + ansible.builtin.service: + name: httpd + state: restarted