diff --git a/molecule/quarkus/converge.yml b/molecule/quarkus/converge.yml index ea04de27..0d590500 100644 --- a/molecule/quarkus/converge.yml +++ b/molecule/quarkus/converge.yml @@ -15,6 +15,10 @@ keycloak_quarkus_ks_vault_enabled: true keycloak_quarkus_ks_vault_file: "/opt/keycloak/certs/keystore.p12" keycloak_quarkus_ks_vault_pass: keystorepassword + keycloak_quarkus_systemd_wait_for_port: true + keycloak_quarkus_systemd_wait_for_timeout: 20 + keycloak_quarkus_systemd_wait_for_delay: 2 + keycloak_quarkus_systemd_wait_for_log: true roles: - role: keycloak_quarkus - role: keycloak_realm diff --git a/molecule/quarkus/prepare.yml b/molecule/quarkus/prepare.yml index b4f24310..00952261 100644 --- a/molecule/quarkus/prepare.yml +++ b/molecule/quarkus/prepare.yml @@ -24,7 +24,9 @@ - name: Create vault keystore ansible.builtin.command: keytool -importpass -alias TestRealm_testalias -keystore keystore.p12 -storepass keystorepassword delegate_to: localhost + register: keytool_cmd changed_when: False + failed_when: not 'already exists' in keytool_cmd.stdout and keytool_cmd.rc != 0 - name: Copy certificates and vault become: yes diff --git a/roles/keycloak_quarkus/README.md b/roles/keycloak_quarkus/README.md index fb41533d..5d0641ce 100644 --- a/roles/keycloak_quarkus/README.md +++ b/roles/keycloak_quarkus/README.md @@ -12,15 +12,16 @@ Role Defaults | Variable | Description | Default | |:---------|:------------|:--------| |`keycloak_quarkus_version`| keycloak.org package version | `24.0.3` | +|`keycloak_quarkus_offline_install` | Perform an offline install | `False`| +|`keycloak_quarkus_version`| keycloak.org package version | `23.0.7` | +|`keycloak_quarkus_dest`| Installation root path | `/opt/keycloak` | +|`keycloak_quarkus_download_url` | Download URL for keycloak | `https://github.com/keycloak/keycloak/releases/download/{{ keycloak_quarkus_version }}/{{ keycloak_quarkus_archive }}` | #### Service configuration | Variable | Description | Default | |:---------|:------------|:--------| -|`keycloak_quarkus_ha_enabled`| Enable auto configuration for database backend, clustering and remote caches on infinispan | `False` | -|`keycloak_quarkus_ha_discovery`| Discovery protocol for HA cluster members | `TCPPING` | -|`keycloak_quarkus_db_enabled`| Enable auto configuration for database backend | `True` if `keycloak_quarkus_ha_enabled` is True, else `False` | |`keycloak_quarkus_admin_user`| Administration console user account | `admin` | |`keycloak_quarkus_bind_address`| Address for binding service ports | `0.0.0.0` | |`keycloak_quarkus_host`| Hostname for the Keycloak server | `localhost` | @@ -29,13 +30,11 @@ Role Defaults |`keycloak_quarkus_http_port`| HTTP listening port | `8080` | |`keycloak_quarkus_https_port`| TLS HTTP listening port | `8443` | |`keycloak_quarkus_ajp_port`| AJP port | `8009` | -|`keycloak_quarkus_jgroups_port`| jgroups cluster tcp port | `7800` | |`keycloak_quarkus_service_user`| Posix account username | `keycloak` | |`keycloak_quarkus_service_group`| Posix account group | `keycloak` | |`keycloak_quarkus_service_restart_always`| systemd restart always behavior activation | `False` | |`keycloak_quarkus_service_restart_on_failure`| systemd restart on-failure behavior activation | `False` | |`keycloak_quarkus_service_restartsec`| systemd RestartSec | `10s` | -|`keycloak_quarkus_service_pidfile`| Pid file path for service | `/run/keycloak.pid` | |`keycloak_quarkus_jvm_package`| RHEL java package runtime | `java-17-openjdk-headless` | |`keycloak_quarkus_java_home`| JAVA_HOME of installed JRE, leave empty for using specified keycloak_quarkus_jvm_package RPM path | `None` | |`keycloak_quarkus_java_heap_opts`| Heap memory JVM setting | `-Xms1024m -Xmx2048m` | @@ -57,8 +56,24 @@ Role Defaults |`keycloak_quarkus_https_trust_store_file`| The file path to the trust store | `{{ keycloak.home }}/conf/trust_store.p12` | |`keycloak_quarkus_https_trust_store_password`| Password for the trust store | `""` | |`keycloak_quarkus_proxy_headers`| Parse reverse proxy headers (`forwarded` or `xforwarded`) | `""` | -|`keycloak_quarkus_config_key_store_file`| Path to the configuration key store; only used if `keycloak_quarkus_keystore_password` is not empty | `{{ keycloak.home }}/conf/conf_store.p12` if `keycloak_quarkus_keystore_password`!='', else '' | -|`keycloak_quarkus_config_key_store_password`| Password of the configuration key store; if non-empty, `keycloak_quarkus_db_pass` will be saved to the key store at `keycloak_quarkus_config_key_store_file` (instead of being written to the configuration file in clear text | `""` | +|`keycloak_quarkus_config_key_store_file`| Path to the configuration key store; only used if `keycloak_quarkus_keystore_password` is not empty | `{{ keycloak.home }}/conf/conf_store.p12` if `keycloak_quarkus_keystore_password != ''`, else `''` | +|`keycloak_quarkus_config_key_store_password`| Password of the configuration keystore; if non-empty, `keycloak_quarkus_db_pass` will be saved to the keystore at `keycloak_quarkus_config_key_store_file` instead of being written to the configuration file in clear text | `""` | +|`keycloak_quarkus_configure_firewalld` | Ensure firewalld is running and configure keycloak ports | `False` | +|`keycloak_quarkus_configure_iptables` | Ensure iptables is configured for keycloak ports | `False` | + + +#### High-availability + +| Variable | Description | Default | +|:---------|:------------|:--------| +|`keycloak_quarkus_ha_enabled`| Enable auto configuration for database backend, clustering and remote caches on infinispan | `False` | +|`keycloak_quarkus_ha_discovery`| Discovery protocol for HA cluster members | `TCPPING` | +|`keycloak_quarkus_db_enabled`| Enable auto configuration for database backend | `True` if `keycloak_quarkus_ha_enabled` is True, else `False` | +|`keycloak_quarkus_jgroups_port`| jgroups cluster tcp port | `7800` | +|`keycloak_quarkus_systemd_wait_for_port` | Whether systemd unit should wait for keycloak port before returning | `{{ keycloak_quarkus_ha_enabled }}` | +|`keycloak_quarkus_systemd_wait_for_log` | Whether systemd unit should wait for service to be up in logs | `false` | +|`keycloak_quarkus_systemd_wait_for_timeout`| How long to wait for service to be alive (seconds) | `60` | +|`keycloak_quarkus_systemd_wait_for_delay`| Activation delay for service systemd unit (seconds) | `10` | #### Hostname configuration @@ -94,17 +109,6 @@ Role Defaults |`keycloak_quarkus_ispn_trust_store_password` | Password for infinispan certificate keystore | `changeit` | -#### Install options - -| Variable | Description | Default | -|:---------|:------------|:---------| -|`keycloak_quarkus_offline_install` | Perform an offline install | `False`| -|`keycloak_quarkus_version`| keycloak.org package version | `23.0.7` | -|`keycloak_quarkus_dest`| Installation root path | `/opt/keycloak` | -|`keycloak_quarkus_download_url` | Download URL for keycloak | `https://github.com/keycloak/keycloak/releases/download/{{ keycloak_quarkus_version }}/{{ keycloak_quarkus_archive }}` | -|`keycloak_quarkus_configure_firewalld` | Ensure firewalld is running and configure keycloak ports | `False` | - - #### Miscellaneous configuration | Variable | Description | Default | diff --git a/roles/keycloak_quarkus/defaults/main.yml b/roles/keycloak_quarkus/defaults/main.yml index e3e2504f..1999dd85 100644 --- a/roles/keycloak_quarkus/defaults/main.yml +++ b/roles/keycloak_quarkus/defaults/main.yml @@ -16,7 +16,6 @@ keycloak_quarkus_config_dir: "{{ keycloak_quarkus_home }}/conf" keycloak_quarkus_start_dev: false keycloak_quarkus_service_user: keycloak keycloak_quarkus_service_group: keycloak -keycloak_quarkus_service_pidfile: "/run/keycloak/keycloak.pid" keycloak_quarkus_service_restart_always: false keycloak_quarkus_service_restart_on_failure: false keycloak_quarkus_service_restartsec: "10s" @@ -66,7 +65,11 @@ keycloak_quarkus_config_key_store_password: '' keycloak_quarkus_ha_enabled: false keycloak_quarkus_ha_discovery: "TCPPING" ### Enable database configuration, must be enabled when HA is configured -keycloak_quarkus_db_enabled: "{{ True if keycloak_quarkus_ha_enabled else False }}" +keycloak_quarkus_db_enabled: "{{ keycloak_quarkus_ha_enabled }}" +keycloak_quarkus_systemd_wait_for_port: "{{ keycloak_quarkus_ha_enabled }}" +keycloak_quarkus_systemd_wait_for_log: false +keycloak_quarkus_systemd_wait_for_timeout: 60 +keycloak_quarkus_systemd_wait_for_delay: 10 ### keycloak frontend url keycloak_quarkus_frontend_url: diff --git a/roles/keycloak_quarkus/handlers/main.yml b/roles/keycloak_quarkus/handlers/main.yml index d6b22208..f60e7476 100644 --- a/roles/keycloak_quarkus/handlers/main.yml +++ b/roles/keycloak_quarkus/handlers/main.yml @@ -9,9 +9,9 @@ - name: "Restart {{ keycloak.service_name }}" ansible.builtin.include_tasks: restart.yml listen: "restart keycloak" - - name: "Print deprecation warning" ansible.builtin.fail: msg: "Deprecation warning: you are using the deprecated variable '{{ deprecated_variable | d('NotSet') }}', check docs on how to upgrade." ignore_errors: true + failed_when: false listen: "print deprecation warning" diff --git a/roles/keycloak_quarkus/meta/argument_specs.yml b/roles/keycloak_quarkus/meta/argument_specs.yml index 5d0519bc..460c9a77 100644 --- a/roles/keycloak_quarkus/meta/argument_specs.yml +++ b/roles/keycloak_quarkus/meta/argument_specs.yml @@ -48,10 +48,6 @@ argument_specs: default: "keycloak" description: "Posix account group" type: "str" - keycloak_quarkus_service_pidfile: - default: "/run/keycloak/keycloak.pid" - description: "Pid file path for service" - type: "str" keycloak_quarkus_configure_firewalld: default: false description: "Ensure firewalld is running and configure keycloak ports" @@ -360,6 +356,22 @@ argument_specs: required: false type: "str" description: "The password for accessing the keystore vault SPI" + keycloak_quarkus_systemd_wait_for_port: + description: 'Whether systemd unit should wait for keycloak port before returning' + default: "{{ keycloak_quarkus_ha_enabled }}" + type: "bool" + keycloak_quarkus_systemd_wait_for_log: + description: 'Whether systemd unit should wait for service to be up in logs' + default: false + type: "bool" + keycloak_quarkus_systemd_wait_for_timeout: + description: "How long to wait for service to be alive (seconds)" + default: 60 + type: 'int' + keycloak_quarkus_systemd_wait_for_delay: + description: "Activation delay for service systemd unit (seconds)" + default: 10 + type: 'int' downstream: options: rhbk_version: diff --git a/roles/keycloak_quarkus/tasks/restart.yml b/roles/keycloak_quarkus/tasks/restart.yml index f709f755..77e10998 100644 --- a/roles/keycloak_quarkus/tasks/restart.yml +++ b/roles/keycloak_quarkus/tasks/restart.yml @@ -1,5 +1,6 @@ --- - name: "Restart and enable {{ keycloak.service_name }} service" + throttle: 1 ansible.builtin.systemd: name: keycloak enabled: true diff --git a/roles/keycloak_quarkus/templates/keycloak.service.j2 b/roles/keycloak_quarkus/templates/keycloak.service.j2 index 3cdfacf6..9cabb695 100644 --- a/roles/keycloak_quarkus/templates/keycloak.service.j2 +++ b/roles/keycloak_quarkus/templates/keycloak.service.j2 @@ -4,9 +4,7 @@ Description=Keycloak Server After=network.target [Service] -Type=simple EnvironmentFile=-{{ keycloak_quarkus_sysconf_file }} -PIDFile={{ keycloak_quarkus_service_pidfile }} {% if keycloak_quarkus_start_dev %} ExecStart={{ keycloak.home }}/bin/kc.sh start-dev {% else %} @@ -14,15 +12,22 @@ ExecStart={{ keycloak.home }}/bin/kc.sh start --optimized {% endif %} User={{ keycloak.service_user }} Group={{ keycloak.service_group }} +SuccessExitStatus=0 143 {% if keycloak_quarkus_service_restart_always %} Restart=always {% elif keycloak_quarkus_service_restart_on_failure %} Restart=on-failure {% endif %} RestartSec={{ keycloak_quarkus_service_restartsec }} -{% if keycloak_quarkus_http_port|int < 1024 or keycloak_quarkus_https_port|int < 1024 %} +{% if keycloak_quarkus_http_port | int < 1024 or keycloak_quarkus_https_port | int < 1024 %} AmbientCapabilities=CAP_NET_BIND_SERVICE {% endif %} +{% if keycloak_quarkus_systemd_wait_for_port %} +ExecStartPost=/usr/bin/timeout {{ keycloak_quarkus_systemd_wait_for_timeout }} sh -c 'while ! ss -H -t -l -n sport = :{{ keycloak_quarkus_https_port }} | grep -q "^LISTEN.*:{{ keycloak_quarkus_https_port }}"; do sleep 1; done && /bin/sleep {{ keycloak_quarkus_systemd_wait_for_delay }}' +{% endif %} +{% if keycloak_quarkus_systemd_wait_for_log %} +ExecStartPost=/usr/bin/timeout {{ keycloak_quarkus_systemd_wait_for_timeout }} sh -c 'cat {{ keycloak.log.file }} | sed "/Profile.*activated/ q" && /bin/sleep {{ keycloak_quarkus_systemd_wait_for_delay }}' +{% endif %} [Install] WantedBy=multi-user.target