Vendor middleware_automation.keycloak collection
Needed for keycloak_authentication_v2, to manage Keycloak authentication flows (e.g. the CCCHH browser flow) as YAML. Chosen over community.general's own copy of the module (deprecated in favor of this collection, and limited to 4 sub-flow levels there vs. 10 here).
This commit is contained in:
parent
4540dc5516
commit
4832e5da5d
159 changed files with 34399 additions and 0 deletions
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
- name: Save ansible custom facts
|
||||
become: "{{ keycloak_quarkus_bootstrapped_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.template:
|
||||
src: keycloak.fact.j2
|
||||
dest: /etc/ansible/facts.d/keycloak.fact
|
||||
mode: '0644'
|
||||
vars:
|
||||
bootstrapped: true
|
||||
|
||||
- name: Refresh custom facts
|
||||
ansible.builtin.setup:
|
||||
filter: ansible_local
|
||||
|
||||
- name: Ensure that `KEYCLOAK_ADMIN[_PASSWORD]` get purged
|
||||
ansible.builtin.include_tasks: systemd.yml
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
- name: "Initialize configuration key store variables to be written"
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_store_items:
|
||||
- key: "kc.db-password"
|
||||
value: "{{ keycloak_quarkus_db_pass }}"
|
||||
|
||||
- name: "Initialize empty configuration key store"
|
||||
become: "{{ keycloak_quarkus_config_store_require_privilege_escalation | default(true) }}"
|
||||
# keytool doesn't allow creating an empty key store, so this is a hacky way around it
|
||||
ansible.builtin.shell: | # noqa blocked_modules shell is necessary here
|
||||
set -o nounset # abort on unbound variable
|
||||
set -o pipefail # do not hide errors within pipes
|
||||
set -o errexit # abort on nonzero exit status
|
||||
|
||||
echo dummy | keytool -noprompt -importpass -alias dummy -keystore {{ keycloak_quarkus_config_key_store_file | quote }} -storepass {{ keycloak_quarkus_config_key_store_password | quote }} -storetype PKCS12
|
||||
keytool -delete -alias dummy -keystore {{ keycloak_quarkus_config_key_store_file | quote }} -storepass {{ keycloak_quarkus_config_key_store_password | quote }}
|
||||
args:
|
||||
creates: "{{ keycloak_quarkus_config_key_store_file }}"
|
||||
|
||||
- name: "Set configuration key store using keytool"
|
||||
ansible.builtin.shell: | # noqa blocked_modules shell is necessary here
|
||||
set -o nounset # abort on unbound variable
|
||||
set -o pipefail # do not hide errors within pipes
|
||||
|
||||
keytool -list -alias {{ item.key | quote }} -keystore {{ keycloak_quarkus_config_key_store_file | quote }} -storepass {{ keycloak_quarkus_config_key_store_password | quote }}
|
||||
retVal=$?
|
||||
|
||||
set -o errexit # abort on nonzero exit status
|
||||
|
||||
if [ $retVal -eq 0 ]; then
|
||||
# value is already in keystore, but keytool has no replace function: delete and re-create instead
|
||||
# note that we can not read whether the value has changed either[^1], so we need to override it
|
||||
# [^1]: https://stackoverflow.com/a/37491400
|
||||
keytool -delete -alias {{ item.key | quote }} -keystore {{ keycloak_quarkus_config_key_store_file | quote }} -storepass {{ keycloak_quarkus_config_key_store_password | quote }}
|
||||
fi
|
||||
|
||||
echo {{ item.value | quote }} | keytool -noprompt -importpass -alias {{ item.key | quote }} -keystore {{ keycloak_quarkus_config_key_store_file | quote }} -storepass {{ keycloak_quarkus_config_key_store_password | quote }} -storetype PKCS12
|
||||
loop: "{{ keycloak_quarkus_store_items }}"
|
||||
no_log: true
|
||||
become: "{{ keycloak_quarkus_config_store_require_privilege_escalation | default(true) }}"
|
||||
changed_when: true
|
||||
notify:
|
||||
- restart keycloak
|
||||
|
||||
- name: "Set owner of configuration key store {{ keycloak_quarkus_config_key_store_file }}"
|
||||
ansible.builtin.file:
|
||||
path: "{{ keycloak_quarkus_config_key_store_file }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0400'
|
||||
become: "{{ keycloak_quarkus_config_store_require_privilege_escalation | default(true) }}"
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
- name: Include firewall config tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: iptables.yml
|
||||
apply:
|
||||
tags:
|
||||
- firewall
|
||||
when: keycloak_quarkus_configure_iptables
|
||||
tags:
|
||||
- firewall
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
---
|
||||
- name: Check deprecation keycloak_quarkus_key_store -> keycloak_quarkus_http_key_store
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
when:
|
||||
- keycloak_quarkus_https_key_store_enabled
|
||||
block:
|
||||
- name: Ensure backward compatibility for `keycloak_quarkus_key_store_file`, superseded by `keycloak_quarkus_https_key_store_file`
|
||||
when:
|
||||
- keycloak_quarkus_key_store_file is defined
|
||||
- keycloak_quarkus_key_store_file != ''
|
||||
- keycloak_quarkus_https_key_store_file == keycloak.home + "/conf/key_store.p12" # default value
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_https_key_store_file: "{{ keycloak_quarkus_key_store_file }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_key_store_file" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
- name: Flush handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Ensure backward compatibility for `keycloak_quarkus_key_store_password`, superseded by `keycloak_quarkus_https_key_store_password`
|
||||
when:
|
||||
- keycloak_quarkus_key_store_password is defined
|
||||
- keycloak_quarkus_key_store_password != ''
|
||||
- keycloak_quarkus_https_key_store_password == "" # default value
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_https_key_store_password: "{{ keycloak_quarkus_key_store_password }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_key_store_password" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
- name: Flush handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
# https://access.redhat.com/documentation/en-us/red_hat_build_of_keycloak/24.0/html-single/upgrading_guide/index#deprecated_literal_proxy_literal_option
|
||||
- name: Check deprecation of keycloak_quarkus_proxy_mode
|
||||
when:
|
||||
- keycloak_quarkus_proxy_mode is defined
|
||||
- keycloak_quarkus_proxy_headers is defined and keycloak_quarkus_proxy_headers | length == 0
|
||||
- keycloak_quarkus_version.split('.') | first | int >= 24
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_proxy_mode" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
# https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/26.0/html-single/upgrading_guide/index#new_hostname_options
|
||||
- name: Check deprecation of keycloak_quarkus_frontend_url -> keycloak_quarkus_hostname
|
||||
when:
|
||||
- keycloak_quarkus_hostname is not defined
|
||||
- keycloak_quarkus_frontend_url is defined
|
||||
- keycloak_quarkus_frontend_url != ''
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_hostname: "{{ keycloak_quarkus_frontend_url }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_frontend_url" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
# https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/26.0/html-single/upgrading_guide/index#new_hostname_options
|
||||
- name: Check deprecation of keycloak_quarkus_hostname_strict_https + keycloak_quarkus_host + keycloak_quarkus_port + keycloak_quarkus_path -> keycloak_quarkus_hostname
|
||||
when:
|
||||
- keycloak_quarkus_hostname is not defined
|
||||
- keycloak_quarkus_hostname_strict_https is defined or keycloak_quarkus_frontend_url is defined or keycloak_quarkus_port is defined or keycloak_quarkus_path is defined
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_hostname: >-
|
||||
{% set protocol = '' %}
|
||||
{% if keycloak_quarkus_hostname_strict_https %}
|
||||
{% set protocol = 'https://' %}
|
||||
{% elif keycloak_quarkus_hostname_strict_https is defined and keycloak_quarkus_hostname_strict_https is False %}
|
||||
{% set protocol = 'http://' %}
|
||||
{% endif %}
|
||||
{{ protocol }}{{ keycloak_quarkus_host }}:{{ keycloak_quarkus_port }}/{{ keycloak_quarkus_path }}
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_hostname_strict_https or keycloak_quarkus_frontend_url or keycloak_quarkus_frontend_url or keycloak_quarkus_hostname" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
# https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/26.0/html-single/upgrading_guide/index#new_hostname_options
|
||||
- name: Check deprecation of keycloak_quarkus_admin_url -> keycloak_quarkus_hostname_admin
|
||||
when:
|
||||
- keycloak_quarkus_hostname_admin is not defined
|
||||
- keycloak_quarkus_admin_url is defined
|
||||
- keycloak_quarkus_admin_url != ''
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_hostname_admin: "{{ keycloak_quarkus_admin_url }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_admin_url" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
# https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/26.0/html-single/upgrading_guide/index#new_hostname_options
|
||||
- name: Check deprecation of keycloak_quarkus_hostname_strict_backchannel -> keycloak_quarkus_hostname_backchannel_dynamic
|
||||
when:
|
||||
- keycloak_quarkus_hostname_backchannel_dynamic is not defined
|
||||
- keycloak_quarkus_hostname_strict_backchannel is defined
|
||||
- keycloak_quarkus_hostname_strict_backchannel != ''
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_hostname_backchannel_dynamic: "{{ keycloak_quarkus_hostname_strict_backchannel == False }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_hostname_backchannel_dynamic" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
# https://github.com/keycloak/keycloak/issues/30009
|
||||
- name: Check deprecation of keycloak_quarkus_admin_user -> keycloak_quarkus_bootstrap_admin_user
|
||||
when:
|
||||
- keycloak_quarkus_bootstrap_admin_user is not defined
|
||||
- keycloak_quarkus_admin_user is defined
|
||||
- keycloak_quarkus_admin_user != ''
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_bootstrap_admin_user: "{{ keycloak_quarkus_admin_user }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_admin_user" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
# https://github.com/keycloak/keycloak/issues/30009
|
||||
- name: Check deprecation of keycloak_quarkus_admin_pass -> keycloak_quarkus_bootstrap_admin_password
|
||||
when:
|
||||
- keycloak_quarkus_bootstrap_admin_password is not defined
|
||||
- keycloak_quarkus_admin_pass is defined
|
||||
- keycloak_quarkus_admin_pass != ''
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_bootstrap_admin_user: "{{ keycloak_quarkus_admin_pass }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_admin_pass" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
- name: Check deprecation of keycloak_quarkus_bind_address -> keycloak_quarkus_http_host
|
||||
when:
|
||||
- keycloak_quarkus_bind_address is defined
|
||||
- keycloak_quarkus_bind_address != '0.0.0.0'
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
changed_when: keycloak_quarkus_show_deprecation_warnings
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_http_host: "{{ keycloak_quarkus_bind_address }}"
|
||||
keycloak_quarkus_deprecated_variable: "keycloak_quarkus_bind_address" # read in deprecation handler
|
||||
notify:
|
||||
- print deprecation warning
|
||||
|
||||
- name: Flush handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
- name: "Check if packages are already installed" # noqa command-instead-of-module this runs faster
|
||||
ansible.builtin.command: "rpm -q {{ packages_list | join(' ') }}"
|
||||
register: keycloak_quarkus_rpm_info
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: ansible_facts.os_family == "RedHat"
|
||||
|
||||
- name: "Add missing packages to the yum install list"
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_packages_to_install: "{{ keycloak_quarkus_packages_to_install | default([]) + keycloak_quarkus_rpm_info.stdout_lines | \
|
||||
map('regex_findall', 'package (.+) is not installed$') | default([]) | flatten }}"
|
||||
when: ansible_facts.os_family == "RedHat"
|
||||
|
||||
- name: "Install packages: {{ keycloak_quarkus_packages_to_install }}"
|
||||
become: "{{ keycloak_quarkus_fastpackages_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ keycloak_quarkus_packages_to_install }}"
|
||||
state: present
|
||||
when:
|
||||
- keycloak_quarkus_packages_to_install | default([]) | length > 0
|
||||
- ansible_facts.os_family == "RedHat"
|
||||
|
||||
- name: "Install packages: {{ packages_list }}"
|
||||
become: "{{ keycloak_quarkus_fastpackages_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.package:
|
||||
name: "{{ packages_list }}"
|
||||
state: present
|
||||
when:
|
||||
- packages_list | default([]) | length > 0
|
||||
- ansible_facts.os_family == "Debian"
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
- name: Ensure required package firewalld are installed
|
||||
ansible.builtin.include_tasks: fastpackages.yml
|
||||
vars:
|
||||
packages_list:
|
||||
- firewalld
|
||||
|
||||
- name: Enable and start the firewalld service
|
||||
become: "{{ keycloak_quarkus_firewalld_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.systemd:
|
||||
name: firewalld
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: "Configure firewall for http port: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_firewalld_require_privilege_escalation | default(true) }}"
|
||||
ansible.posix.firewalld:
|
||||
port: "{{ item }}"
|
||||
permanent: true
|
||||
state: enabled
|
||||
immediate: true
|
||||
loop:
|
||||
- "{{ keycloak_quarkus_http_port }}/tcp"
|
||||
when: keycloak_quarkus_http_enabled | bool
|
||||
|
||||
- name: "Configure firewall for ports: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_firewalld_require_privilege_escalation | default(true) }}"
|
||||
ansible.posix.firewalld:
|
||||
port: "{{ item }}"
|
||||
permanent: true
|
||||
state: enabled
|
||||
immediate: true
|
||||
loop:
|
||||
- "{{ keycloak_quarkus_https_port }}/tcp"
|
||||
- "{{ keycloak_quarkus_http_management_port }}/tcp"
|
||||
- "{{ keycloak_quarkus_jgroups_port }}/tcp"
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
---
|
||||
- name: Validate parameters
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak.home is defined
|
||||
- keycloak_quarkus_service_user is defined
|
||||
- keycloak_quarkus_dest is defined
|
||||
- keycloak_quarkus_archive is defined
|
||||
- keycloak_quarkus_download_url is defined
|
||||
- keycloak_quarkus_version is defined
|
||||
- keycloak_quarkus_local_path is defined
|
||||
quiet: true
|
||||
|
||||
- name: Check for an existing deployment
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak.home }}"
|
||||
register: keycloak_quarkus_existing_deploy
|
||||
|
||||
- name: Stop and restart if existing deployment exists and install forced
|
||||
when: keycloak_quarkus_existing_deploy.stat.exists and keycloak_quarkus_force_install | bool
|
||||
block:
|
||||
- name: "Stop the old service: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
failed_when: false
|
||||
ansible.builtin.systemd:
|
||||
name: keycloak
|
||||
state: stopped
|
||||
- name: "Remove the old deployment: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.file:
|
||||
path: "{{ keycloak_quarkus_home }}"
|
||||
state: absent
|
||||
|
||||
- name: Check for an existing deployment after possible forced removal
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak_quarkus_home }}"
|
||||
register: keycloak_quarkus_existing_deploy
|
||||
|
||||
- name: "Create service user/group: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.user:
|
||||
name: "{{ keycloak.service_user }}"
|
||||
home: /opt/keycloak
|
||||
system: true
|
||||
create_home: false
|
||||
|
||||
- name: "Create install location: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.file:
|
||||
dest: "{{ keycloak_quarkus_dest }}"
|
||||
state: directory
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0750'
|
||||
|
||||
- name: Create directory for ansible custom facts
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
recurse: true
|
||||
path: /etc/ansible/facts.d
|
||||
|
||||
## check remote archive
|
||||
- name: Set download archive path
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_archive_full_path: "{{ keycloak_quarkus_dest }}/{{ keycloak.bundle }}"
|
||||
|
||||
- name: Check download archive path
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak_quarkus_archive_full_path }}"
|
||||
register: keycloak_quarkus_archive_path
|
||||
|
||||
## download to controller
|
||||
- name: Download keycloak archive
|
||||
ansible.builtin.get_url: # noqa risky-file-permissions delegated, uses controller host user
|
||||
url: "{{ keycloak_quarkus_download_url }}"
|
||||
dest: "{{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
mode: '0640'
|
||||
url_username: "{{ keycloak_quarkus_binary_download_user | default(omit) }}"
|
||||
url_password: "{{ keycloak_quarkus_binary_download_pass | default(omit) }}"
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
when:
|
||||
- keycloak_quarkus_archive_path is defined
|
||||
- keycloak_quarkus_archive_path.stat is defined
|
||||
- not keycloak_quarkus_archive_path.stat.exists
|
||||
- not keycloak.offline_install
|
||||
- not rhbk_enable is defined or not rhbk_enable
|
||||
|
||||
- name: Perform download from RHN using the Unified Downloads API
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
when:
|
||||
- keycloak_quarkus_archive_path is defined
|
||||
- keycloak_quarkus_archive_path.stat is defined
|
||||
- not keycloak_quarkus_archive_path.stat.exists
|
||||
- rhbk_enable is defined and rhbk_enable
|
||||
- not keycloak.offline_install
|
||||
- keycloak_quarkus_alternate_download_url is undefined
|
||||
block:
|
||||
- name: Retrieve product download using Unified Downloads API
|
||||
middleware_automation.common.product_search:
|
||||
client_id: "{{ rhn_username }}"
|
||||
client_secret: "{{ rhn_password }}"
|
||||
product_type: DISTRIBUTION
|
||||
product_version: "{{ rhbk_version }}"
|
||||
product_category: "{{ rhbk_product_category }}"
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
register: keycloak_quarkus_rhn_products
|
||||
no_log: "{{ omit_rhn_output | default(true) }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Determine install zipfile from search results
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_rhn_filtered_products: "{{ keycloak_quarkus_rhn_products.results | selectattr('file_name', 'match', '[^/]*/' + rhbk_archive + '$') }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Download Red Hat Build of Keycloak
|
||||
middleware_automation.common.product_download: # noqa risky-file-permissions delegated, uses controller host user
|
||||
client_id: "{{ rhn_username }}"
|
||||
client_secret: "{{ rhn_password }}"
|
||||
product_id: "{{ (keycloak_quarkus_rhn_filtered_products | first).id }}"
|
||||
dest: "{{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
mode: '0640'
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
no_log: "{{ omit_rhn_output | default(true) }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
become: false
|
||||
|
||||
- name: Perform download of RHBK from alternate download location
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
become: false
|
||||
when:
|
||||
- keycloak_quarkus_archive_path is defined
|
||||
- keycloak_quarkus_archive_path.stat is defined
|
||||
- not keycloak_quarkus_archive_path.stat.exists
|
||||
- rhbk_enable is defined and rhbk_enable
|
||||
- not keycloak.offline_install
|
||||
- keycloak_quarkus_alternate_download_url is defined
|
||||
ansible.builtin.get_url: # noqa risky-file-permissions delegated, uses controller host user
|
||||
url: "{{ keycloak_quarkus_alternate_download_url }}"
|
||||
dest: "{{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
mode: '0640'
|
||||
url_username: "{{ keycloak_quarkus_download_user | default(omit) }}"
|
||||
url_password: "{{ keycloak_quarkus_download_pass | default(omit) }}"
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
|
||||
- name: Check downloaded archive
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
register: keycloak_quarkus_local_archive_path
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
|
||||
## copy and unpack
|
||||
- name: Copy archive to target nodes
|
||||
ansible.builtin.copy:
|
||||
src: "{{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
dest: "{{ keycloak_quarkus_archive_full_path }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
register: keycloak_quarkus_new_version_downloaded
|
||||
when:
|
||||
- not keycloak_quarkus_archive_path.stat.exists
|
||||
- keycloak_quarkus_local_archive_path.stat is defined
|
||||
- keycloak_quarkus_local_archive_path.stat.exists
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: "Check target directory /bin/: {{ keycloak.home }}"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak.home }}/bin/"
|
||||
register: keycloak_quarkus_path_to_workdir
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: "Extract Keycloak archive on target" # noqa no-handler need to run this here
|
||||
ansible.builtin.unarchive:
|
||||
remote_src: true
|
||||
src: "{{ keycloak_quarkus_archive_full_path }}"
|
||||
dest: "{{ keycloak_quarkus_dest }}"
|
||||
creates: "{{ keycloak.home }}/bin/"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
when:
|
||||
- (not keycloak_quarkus_path_to_workdir.stat.exists) or keycloak_quarkus_new_version_downloaded.changed
|
||||
notify:
|
||||
- restart keycloak
|
||||
|
||||
- name: Inform decompression was not executed
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ keycloak.home }} already exists and version unchanged, skipping decompression"
|
||||
when:
|
||||
- (not keycloak_quarkus_new_version_downloaded.changed) and keycloak_quarkus_path_to_workdir.stat.exists
|
||||
|
||||
- name: "Copy private key to target"
|
||||
ansible.builtin.copy:
|
||||
content: "{{ keycloak_quarkus_key_content }}"
|
||||
dest: "{{ keycloak_quarkus_key_file }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
when:
|
||||
- keycloak_quarkus_https_key_file_enabled is defined and keycloak_quarkus_https_key_file_enabled
|
||||
- keycloak_quarkus_key_file_copy_enabled is defined and keycloak_quarkus_key_file_copy_enabled
|
||||
- keycloak_quarkus_key_content | length > 0
|
||||
|
||||
- name: "Copy certificate to target"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ keycloak_quarkus_cert_file_src }}"
|
||||
dest: "{{ keycloak_quarkus_cert_file }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0644'
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
when:
|
||||
- keycloak_quarkus_https_key_file_enabled is defined and keycloak_quarkus_https_key_file_enabled
|
||||
- keycloak_quarkus_cert_file_copy_enabled is defined and keycloak_quarkus_cert_file_copy_enabled
|
||||
- keycloak_quarkus_cert_file_src | length > 0
|
||||
|
||||
- name: "Install JDBC driver: {{ keycloak_quarkus_db_engine }}"
|
||||
ansible.builtin.include_tasks: jdbc_driver.yml
|
||||
when:
|
||||
- rhbk_enable is defined and rhbk_enable
|
||||
- keycloak_quarkus_default_jdbc[keycloak_quarkus_db_engine].driver_jar_url is defined
|
||||
|
||||
- name: "Download custom providers via http"
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ item.url }}"
|
||||
dest: "{{ keycloak.home }}/providers/{{ item.id }}.jar"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
checksum: "{{ item.checksum | default(omit) }}"
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
loop: "{{ keycloak_quarkus_providers }}"
|
||||
when: item.url is defined and item.url | length > 0
|
||||
no_log: "{{ item.maven.password is defined and item.maven.password | length > 0 | default(false) }}"
|
||||
notify: "{{ ['invalidate keycloak theme cache', 'rebuild keycloak config', 'restart keycloak'] if not item.restart is defined or item.restart else [] }}"
|
||||
|
||||
# this requires the `lxml` package to be installed; we redirect this step to localhost such that we do need to install it on the remote hosts
|
||||
- name: "Download custom providers to localhost using maven"
|
||||
middleware_automation.common.maven_artifact:
|
||||
repository_url: "{{ item.maven.repository_url }}"
|
||||
group_id: "{{ item.maven.group_id }}"
|
||||
artifact_id: "{{ item.maven.artifact_id }}"
|
||||
version: "{{ item.maven.version | default(omit) }}"
|
||||
username: "{{ item.maven.username | default(omit) }}"
|
||||
password: "{{ item.maven.password | default(omit) }}"
|
||||
dest: "{{ keycloak_quarkus_local_path.stat.path }}/{{ item.id }}.jar"
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
delegate_to: "localhost"
|
||||
run_once: true
|
||||
loop: "{{ keycloak_quarkus_providers }}"
|
||||
when: item.maven is defined
|
||||
no_log: "{{ item.maven.password is defined and item.maven.password | length > 0 | default(false) }}"
|
||||
|
||||
- name: "Copy maven providers"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ keycloak_quarkus_local_path.stat.path }}/{{ item.id }}.jar"
|
||||
dest: "{{ keycloak.home }}/providers/{{ item.id }}.jar"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
checksum: "{{ item.checksum | default(omit) }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
loop: "{{ keycloak_quarkus_providers }}"
|
||||
when: item.maven is defined
|
||||
no_log: "{{ item.maven.password is defined and item.maven.password | length > 0 | default(false) }}"
|
||||
notify: "{{ ['invalidate keycloak theme cache', 'rebuild keycloak config', 'restart keycloak'] if not item.restart is defined or item.restart else [] }}"
|
||||
|
||||
- name: "Copy local providers"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item.local_path }}"
|
||||
dest: "{{ keycloak.home }}/providers/{{ item.id }}.jar"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
remote_src: "{{ item.remote | default(false) }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
loop: "{{ keycloak_quarkus_providers }}"
|
||||
when: item.local_path is defined
|
||||
no_log: "{{ item.maven.password is defined and item.maven.password | length > 0 | default(false) }}"
|
||||
notify: "{{ ['invalidate keycloak theme cache', 'rebuild keycloak config', 'restart keycloak'] if not item.restart is defined or item.restart else [] }}"
|
||||
|
||||
- name: Ensure required folder structure for policies exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ keycloak.home }}/data/{{ item | lower }}"
|
||||
state: directory
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0750'
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
loop: "{{ keycloak_quarkus_supported_policy_types }}"
|
||||
|
||||
- name: "Install custom policies"
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ item.url }}"
|
||||
dest: "{{ keycloak.home }}/data/{{ item.type | default(keycloak_quarkus_supported_policy_types | first) | lower }}/{{ item.name }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
validate_certs: "{{ keycloak_quarkus_download_validate_certs | default(omit) }}"
|
||||
become: "{{ keycloak_quarkus_install_require_privilege_escalation | default(true) }}"
|
||||
loop: "{{ keycloak_quarkus_policies }}"
|
||||
when: item.url is defined and item.url | length > 0
|
||||
notify: "restart keycloak"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
# From https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/24.0/html/server_developer_guide/themes#creating_a_theme:
|
||||
# If you want to manually delete the content of the themes cache,
|
||||
# you can do so by deleting the data/tmp/kc-gzip-cache directory of the server distribution
|
||||
# It can be useful for instance if you redeployed custom providers or custom themes without
|
||||
# disabling themes caching in the previous server executions.
|
||||
- name: "Delete theme cache directory: {{ keycloak.service_name }}"
|
||||
ansible.builtin.file:
|
||||
path: "{{ keycloak.home }}/data/tmp/kc-gzip-cache"
|
||||
state: absent
|
||||
become: "{{ keycloak_quarkus_invalidate_theme_cache_require_privilege_escalation | default(true) }}"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
- name: Ensure required package iptables are installed
|
||||
ansible.builtin.include_tasks: fastpackages.yml
|
||||
vars:
|
||||
packages_list:
|
||||
- iptables
|
||||
|
||||
- name: "Configure firewall ports for {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_iptables_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.iptables:
|
||||
destination_port: "{{ item }}"
|
||||
action: "insert"
|
||||
rule_num: 6 # magic number I forget why
|
||||
chain: "INPUT"
|
||||
policy: "ACCEPT"
|
||||
protocol: tcp
|
||||
loop:
|
||||
- "{{ keycloak_quarkus_http_port }}"
|
||||
- "{{ keycloak_quarkus_https_port }}"
|
||||
- "{{ keycloak_quarkus_jgroups_port }}"
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
- name: "Verify valid parameters for download credentials when specified"
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
When JDBC driver download credentials are set, both the username and the password MUST be set
|
||||
when: >
|
||||
(keycloak_quarkus_jdbc_download_user is undefined and keycloak_quarkus_jdbc_download_pass is not undefined) or
|
||||
(keycloak_quarkus_jdbc_download_pass is undefined and keycloak_quarkus_jdbc_download_user is not undefined)
|
||||
|
||||
- name: "Retrieve JDBC Driver from {{ keycloak_jdbc_download_url | default(keycloak_quarkus_default_jdbc[keycloak_quarkus_db_engine].driver_jar_url) }}"
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ keycloak_quarkus_jdbc_download_url | default(keycloak_quarkus_default_jdbc[keycloak_quarkus_db_engine].driver_jar_url) }}"
|
||||
dest: "{{ keycloak.home }}/providers"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
url_username: "{{ keycloak_quarkus_jdbc_download_user | default(omit) }}"
|
||||
url_password: "{{ keycloak_quarkus_jdbc_download_pass | default(omit) }}"
|
||||
validate_certs: "{{ keycloak_quarkus_jdbc_download_validate_certs | default(omit) }}"
|
||||
mode: '0640'
|
||||
become: "{{ keycloak_quarkus_jdbc_driver_require_privilege_escalation | default(true) }}"
|
||||
notify:
|
||||
- restart keycloak
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
---
|
||||
# tasks file for keycloak
|
||||
- name: Check prerequisites
|
||||
ansible.builtin.include_tasks:
|
||||
file: prereqs.yml
|
||||
apply:
|
||||
tags:
|
||||
- prereqs
|
||||
tags:
|
||||
- prereqs
|
||||
- always
|
||||
|
||||
- name: Check for deprecations
|
||||
ansible.builtin.include_tasks:
|
||||
file: deprecations.yml
|
||||
apply:
|
||||
tags:
|
||||
- always
|
||||
tags:
|
||||
- always
|
||||
|
||||
- name: Distro specific tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: "{{ ansible_os_family | lower }}.yml"
|
||||
apply:
|
||||
tags:
|
||||
- unbound
|
||||
tags:
|
||||
- unbound
|
||||
|
||||
- name: Include install tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: install.yml
|
||||
apply:
|
||||
tags:
|
||||
- install
|
||||
tags:
|
||||
- install
|
||||
|
||||
- name: Include systemd tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: systemd.yml
|
||||
apply:
|
||||
tags:
|
||||
- systemd
|
||||
tags:
|
||||
- systemd
|
||||
|
||||
- name: Include configuration key store tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: config_store.yml
|
||||
apply:
|
||||
tags:
|
||||
- install
|
||||
when: keycloak.config_key_store_enabled
|
||||
tags:
|
||||
- install
|
||||
|
||||
- name: Create tcpping cluster node list
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_cluster_nodes: >
|
||||
{{ keycloak_quarkus_cluster_nodes | default([]) + [
|
||||
{
|
||||
"name": item,
|
||||
"address": 'jgroups-' + item,
|
||||
"inventory_host": hostvars[item].keycloak_quarkus_jgroups_ip | default(item) + '[' + (keycloak_quarkus_jgroups_port | string) + ']',
|
||||
"value": hostvars[item].keycloak_quarkus_jgroups_ip | default(item)
|
||||
}
|
||||
] }}
|
||||
loop: "{{ ansible_play_batch }}"
|
||||
when: keycloak_quarkus_ha_enabled and keycloak_quarkus_ha_discovery == 'TCPPING'
|
||||
|
||||
|
||||
- name: Determine the config files
|
||||
ansible.builtin.set_fact:
|
||||
keycloak_quarkus_config_files: "{{ ['keycloak.conf', 'quarkus.properties'] + (keycloak_quarkus_cache_managed_infinispan_config | ternary([keycloak_quarkus_cache_infinispan_template], [])) }}"
|
||||
|
||||
- name: "Configure config files for keycloak service"
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}.j2"
|
||||
dest: "{{ keycloak.home }}/conf/{{ item }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0640'
|
||||
become: "{{ keycloak_quarkus_require_privilege_escalation | default(true) }}"
|
||||
loop: "{{ keycloak_quarkus_config_files }}"
|
||||
notify:
|
||||
- rebuild keycloak config
|
||||
- restart keycloak
|
||||
|
||||
- name: Ensure logdirectory exists
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ keycloak.log.file | dirname }}"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0775'
|
||||
become: "{{ keycloak_quarkus_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: Ensure tmp-directory exists
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ keycloak.home }}/data/tmp"
|
||||
owner: "{{ keycloak.service_user }}"
|
||||
group: "{{ keycloak.service_group }}"
|
||||
mode: '0755'
|
||||
become: "{{ keycloak_quarkus_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: Flush pending handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: "Start and wait for keycloak service"
|
||||
ansible.builtin.include_tasks: start.yml
|
||||
|
||||
- name: Link default logs directory
|
||||
ansible.builtin.file:
|
||||
state: link
|
||||
src: "{{ keycloak.log.file | dirname }}"
|
||||
dest: "{{ keycloak_quarkus_log_target }}"
|
||||
force: true
|
||||
become: "{{ keycloak_quarkus_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: Check service status
|
||||
ansible.builtin.systemd_service:
|
||||
name: "{{ keycloak.service_name }}"
|
||||
register: keycloak_quarkus_service_status
|
||||
changed_when: false
|
||||
|
||||
- name: "Notify to remove `keycloak_quarkus_bootstrap_admin_user[_password]` env vars"
|
||||
when:
|
||||
- not ansible_local.keycloak.general.bootstrapped | default(false) | bool # it was not bootstrapped prior to the current role's execution
|
||||
- keycloak_quarkus_service_status.status.ActiveState == "active" # but it is now
|
||||
ansible.builtin.assert: { that: true, quiet: true }
|
||||
changed_when: true
|
||||
notify:
|
||||
- bootstrapped
|
||||
|
||||
- name: Flush pending handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
---
|
||||
- name: Validate admin console password
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak_quarkus_bootstrap_admin_password is defined
|
||||
- keycloak_quarkus_bootstrap_admin_password is not none
|
||||
- keycloak_quarkus_bootstrap_admin_password | length > 12
|
||||
quiet: true
|
||||
fail_msg: "The console administrator password is empty or invalid. Please set the keycloak_quarkus_bootstrap_admin_password to a 12+ char long string"
|
||||
success_msg: "{{ 'Console administrator password OK' }}"
|
||||
|
||||
- name: Validate http_relative_path
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak_quarkus_http_relative_path is regex('^/.*')
|
||||
quiet: true
|
||||
fail_msg: "The relative path for keycloak_quarkus_http_relative_path must begin with /"
|
||||
success_msg: "{{ 'Relative path OK' }}"
|
||||
|
||||
- name: Validate http_management_relative_path
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak_quarkus_http_management_relative_path is regex('^/.*')
|
||||
quiet: true
|
||||
fail_msg: "The relative path for keycloak_quarkus_http_management_relative_path must begin with /"
|
||||
success_msg: "{{ 'Relative mgmt path OK' }}"
|
||||
when: keycloak_quarkus_http_management_relative_path is defined
|
||||
|
||||
- name: Validate configuration
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (keycloak_quarkus_ha_enabled and keycloak_quarkus_db_enabled) or
|
||||
(not keycloak_quarkus_ha_enabled and keycloak_quarkus_db_enabled) or
|
||||
(not keycloak_quarkus_ha_enabled and not keycloak_quarkus_db_enabled)
|
||||
quiet: true
|
||||
fail_msg: "HA setup requires a backend database service. Check keycloak_quarkus_ha_enabled and keycloak_quarkus_db_enabled"
|
||||
success_msg: "{{ 'Configuring HA' if keycloak_quarkus_ha_enabled else 'Configuring standalone' }}"
|
||||
|
||||
- name: Validate OS family
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_os_family in ["RedHat", "Debian"]
|
||||
quiet: true
|
||||
fail_msg: "Can only install on RedHat or Debian OS families; found {{ ansible_os_family }}"
|
||||
success_msg: "Installing on {{ ansible_os_family }}"
|
||||
|
||||
- name: Load OS specific variables
|
||||
ansible.builtin.include_vars: "vars/{{ ansible_os_family | lower }}.yml"
|
||||
tags:
|
||||
- always
|
||||
|
||||
- name: Ensure required packages are installed
|
||||
ansible.builtin.include_tasks: fastpackages.yml
|
||||
vars:
|
||||
packages_list: "{{ keycloak_quarkus_prereq_package_list }}"
|
||||
|
||||
- name: Check local download archive path
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak_quarkus_download_path }}"
|
||||
register: keycloak_quarkus_local_path
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
become: false
|
||||
|
||||
- name: Validate local download path
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak_quarkus_local_path.stat.exists
|
||||
- keycloak_quarkus_local_path.stat.readable
|
||||
- keycloak_quarkus_offline_install or keycloak_quarkus_local_path.stat.writeable
|
||||
quiet: true
|
||||
fail_msg: "Defined controller path for downloading resources is incorrect or unreadable: {{ keycloak_quarkus_download_path }}"
|
||||
success_msg: "Will download resource to controller path: {{ keycloak_quarkus_download_path }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Check downloaded archive if offline
|
||||
ansible.builtin.stat:
|
||||
path: "{{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
when: keycloak_quarkus_offline_install
|
||||
register: keycloak_quarkus_local_archive_path_check
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Validate local downloaded archive if offline
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak_quarkus_local_archive_path_check.stat.exists
|
||||
- keycloak_quarkus_local_archive_path_check.stat.readable
|
||||
quiet: true
|
||||
fail_msg: "Configured for offline install but install archive not found at: {{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
success_msg: "Will install offline with expected archive: {{ keycloak_quarkus_local_path.stat.path }}/{{ keycloak.bundle }}"
|
||||
when: keycloak_quarkus_offline_install
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: "Validate keytool"
|
||||
when: keycloak_quarkus_config_key_store_password | length > 0
|
||||
block:
|
||||
- name: "Check run keytool"
|
||||
changed_when: false
|
||||
ansible.builtin.command: keytool -help
|
||||
register: keycloak_quarkus_keytool_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: "Fail when no keytool found"
|
||||
when: keycloak_quarkus_keytool_check.rc != 0
|
||||
ansible.builtin.fail:
|
||||
msg: "keytool NOT found in the PATH, but is required for setting up the configuration key store"
|
||||
|
||||
- name: "Validate providers"
|
||||
ansible.builtin.assert:
|
||||
that: >
|
||||
item.id is defined and item.id | length > 0 and
|
||||
( (item.spi is defined and item.spi | length > 0) or
|
||||
(item.url is defined and item.url | length > 0) or
|
||||
( item.maven is defined and item.maven.repository_url is defined and item.maven.repository_url | length > 0 and
|
||||
item.maven.group_id is defined and item.maven.group_id | length > 0 and
|
||||
item.maven.artifact_id is defined and item.maven.artifact_id | length > 0) or
|
||||
(item.local_path is defined and item.local_path | length > 0)
|
||||
)
|
||||
quiet: true
|
||||
fail_msg: >
|
||||
Providers definition incorrect; `id` and one of `spi`, `url`, `local_path`, or `maven` are mandatory. `key` and `value` are mandatory for each property
|
||||
loop: "{{ keycloak_quarkus_providers }}"
|
||||
no_log: "{{ item.maven.password is defined and item.maven.password | length > 0 | default(false) }}"
|
||||
|
||||
- name: "Validate policies"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.name is defined and item.name | length > 0
|
||||
- item.url is defined and item.url | length > 0
|
||||
- item.type is not defined or item.type | lower in keycloak_quarkus_supported_policy_types
|
||||
quiet: true
|
||||
fail_msg: >
|
||||
Policy definition is incorrect: `name` and one of `url` are mandatory, `type` needs to be left empty or one of {{ keycloak_quarkus_supported_policy_types }}.
|
||||
loop: "{{ keycloak_quarkus_policies }}"
|
||||
|
||||
- name: "Validate additional env variables"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.key is defined and item.key | length > 0
|
||||
- item.value is defined and item.value | length > 0
|
||||
quiet: true
|
||||
fail_msg: "Additional env variable definition is incorrect: `key` and `value` are mandatory."
|
||||
no_log: true
|
||||
loop: "{{ keycloak_quarkus_additional_env_vars }}"
|
||||
|
||||
- name: "Validate proxy-headers"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- keycloak_quarkus_proxy_headers | lower in ['', 'forwarded', 'xforwarded']
|
||||
quiet: true
|
||||
fail_msg: "keycloak_quarkus_proxy_headers must be either '', 'forwarded' or 'xforwarded'"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
# cf. https://www.keycloak.org/server/configuration#_optimize_the_keycloak_startup
|
||||
- name: "Rebuild config: {{ keycloak.service_name }}"
|
||||
ansible.builtin.shell: | # noqa blocked_modules shell is necessary here
|
||||
env -i bash -c "set -a ; source {{ keycloak_quarkus_sysconf_file }} ; {{ keycloak.home }}/bin/kc.sh build "
|
||||
become: "{{ keycloak_quarkus_rebuild_config_require_privilege_escalation | default(true) }}"
|
||||
changed_when: true
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
- name: Include firewall config tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: firewalld.yml
|
||||
apply:
|
||||
tags:
|
||||
- firewall
|
||||
when: keycloak_quarkus_configure_firewalld
|
||||
tags:
|
||||
- firewall
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
- name: "Restart and enable service: {{ keycloak.service_name }}"
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ keycloak.service_name }}"
|
||||
enabled: true
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
become: "{{ keycloak_quarkus_restart_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: "Wait until service becomes active: {{ keycloak.service_name }}"
|
||||
ansible.builtin.uri:
|
||||
url: "{{ keycloak.health_url }}"
|
||||
validate_certs: "{{ keycloak_quarkus_validate_certs }}"
|
||||
register: keycloak_quarkus_status
|
||||
until: keycloak_quarkus_status.status == 200
|
||||
retries: "{{ keycloak_quarkus_restart_health_check_retries }}"
|
||||
delay: "{{ keycloak_quarkus_restart_health_check_delay }}"
|
||||
when: internal_force_health_check | default(keycloak_quarkus_restart_health_check)
|
||||
|
||||
- name: Wait to give distributed ispn caches time to (re-)replicate back onto first host
|
||||
ansible.builtin.pause:
|
||||
seconds: "{{ keycloak_quarkus_restart_pause }}"
|
||||
when:
|
||||
- keycloak_quarkus_ha_enabled
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
- name: "Display message"
|
||||
ansible.builtin.debug:
|
||||
msg: "keycloak_quarkus_restart_strategy is none, skipping restart"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
- name: "Restart services in serial, with optional healtch check (keycloak_quarkus_restart_health_check)"
|
||||
throttle: 1
|
||||
block:
|
||||
- name: "Restart and enable service: {{ keycloak.service_name }}"
|
||||
ansible.builtin.include_tasks:
|
||||
file: restart.yml
|
||||
apply:
|
||||
delegate_to: "{{ item }}"
|
||||
run_once: true
|
||||
loop: "{{ ansible_play_hosts }}"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
- name: Verify first restarted service with health URL, then rest restart in parallel
|
||||
block:
|
||||
- name: "Restart and enable service on initial host: {{ keycloak.service_name }}"
|
||||
ansible.builtin.include_tasks:
|
||||
file: restart.yml
|
||||
apply:
|
||||
delegate_to: "{{ ansible_play_hosts | first }}"
|
||||
run_once: true
|
||||
vars:
|
||||
internal_force_health_check: true
|
||||
|
||||
- name: "Restart and enable service on other hosts: {{ keycloak.service_name }}"
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ keycloak.service_name }}"
|
||||
enabled: true
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
become: "{{ keycloak_quarkus_restart_require_privilege_escalation | default(true) }}"
|
||||
when: inventory_hostname != ansible_play_hosts | first
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
- name: "Start service: {{ keycloak.service_name }}"
|
||||
ansible.builtin.systemd:
|
||||
name: keycloak
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
become: "{{ keycloak_quarkus_start_require_privilege_escalation | default(true) }}"
|
||||
|
||||
- name: "Wait until service becomes active: {{ keycloak.service_name }}"
|
||||
ansible.builtin.uri:
|
||||
url: "{{ keycloak.health_url }}"
|
||||
validate_certs: "{{ keycloak_quarkus_validate_certs }}"
|
||||
register: keycloak_quarkus_status
|
||||
until: keycloak_quarkus_status.status == 200
|
||||
retries: 25
|
||||
delay: 10
|
||||
when: internal_force_health_check | default(keycloak_quarkus_restart_health_check)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
- name: "Configure sysconfig file for service: {{ keycloak.service_name }}"
|
||||
become: "{{ keycloak_quarkus_systemd_require_privilege_escalation | default(true) }}"
|
||||
ansible.builtin.template:
|
||||
src: keycloak-sysconfig.j2
|
||||
dest: "{{ keycloak_quarkus_sysconf_file }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0640'
|
||||
vars:
|
||||
keycloak_sys_pkg_java_home: "{{ keycloak_quarkus_pkg_java_home }}"
|
||||
notify:
|
||||
- rebuild keycloak config
|
||||
- restart keycloak
|
||||
|
||||
- name: "Configure systemd unit file for keycloak service"
|
||||
ansible.builtin.template:
|
||||
src: keycloak.service.j2
|
||||
dest: /etc/systemd/system/keycloak.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
become: "{{ keycloak_quarkus_systemd_require_privilege_escalation | default(true) }}"
|
||||
register: keycloak_quarkus_systemdunit
|
||||
notify:
|
||||
- rebuild keycloak config
|
||||
- restart keycloak
|
||||
Loading…
Reference in a new issue