diff --git a/galaxy.yml b/galaxy.yml
index 65fe587..ba88e5a 100644
--- a/galaxy.yml
+++ b/galaxy.yml
@@ -15,6 +15,7 @@ tags:
- sso
dependencies:
- "middleware_automation.redhat_csp_download": ">=1.2.1"
+ - "middleware_automation.jcliff": ">=0.0.19"
repository: https://github.com/ansible-middleware/keycloak
documentation: https://github.com/ansible-middleware/keycloak
homepage: https://github.com/ansible-middleware/keycloak
diff --git a/meta/runtime.yml b/meta/runtime.yml
new file mode 100644
index 0000000..9baaad6
--- /dev/null
+++ b/meta/runtime.yml
@@ -0,0 +1,2 @@
+---
+requires_ansible: ">=2.9.10"
\ No newline at end of file
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
new file mode 100644
index 0000000..8d43718
--- /dev/null
+++ b/molecule/default/converge.yml
@@ -0,0 +1,8 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ tasks:
+ - name: Include keycloak role
+ include_role:
+ name: ../../roles/keycloak
\ No newline at end of file
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
new file mode 100644
index 0000000..1b3efda
--- /dev/null
+++ b/molecule/default/molecule.yml
@@ -0,0 +1,51 @@
+---
+dependency:
+ name: galaxy
+driver:
+ name: docker
+platforms:
+ - name: instance
+ image: registry.access.redhat.com/ubi8/ubi-init:latest
+ pre_build_image: true
+ privileged: true
+ command: "/usr/sbin/init"
+ port_bindings:
+ - "8080/tcp"
+ - "8443/tcp"
+ - "8009/tcp"
+ published_ports:
+ - 0.0.0.0:8443:8443/TCP
+provisioner:
+ name: ansible
+ config_options:
+ defaults:
+ interpreter_python: auto_silent
+ ssh_connection:
+ pipelining: false
+ playbooks:
+ prepare: prepare.yml
+ converge: converge.yml
+ verify: verify.yml
+ inventory:
+ host_vars:
+ localhost:
+ ansible_python_interpreter: "{{ ansible_playbook_python }}"
+ env:
+ ANSIBLE_FORCE_COLOR: "true"
+verifier:
+ name: ansible
+scenario:
+ test_sequence:
+ - dependency
+ - lint
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - prepare
+ - converge
+# - idempotence
+ - side_effect
+ - verify
+ - cleanup
+ - destroy
diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml
new file mode 100644
index 0000000..a0fd601
--- /dev/null
+++ b/molecule/default/prepare.yml
@@ -0,0 +1,8 @@
+---
+- name: Prepare
+ hosts: all
+ tasks:
+ - name: Install sudo
+ yum:
+ name: sudo
+ state: present
\ No newline at end of file
diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml
new file mode 100644
index 0000000..e28ed78
--- /dev/null
+++ b/molecule/default/verify.yml
@@ -0,0 +1,10 @@
+---
+- name: Verify
+ hosts: all
+ tasks:
+ - name: Populate service facts
+ ansible.builtin.service_facts:
+ - name: Check if infinispan service started
+ assert:
+ that:
+ - ansible_facts.services["keycloak.service"]["state"] == "running"
diff --git a/playbooks/keycloak.yml b/playbooks/keycloak.yml
new file mode 100644
index 0000000..4c4ee4b
--- /dev/null
+++ b/playbooks/keycloak.yml
@@ -0,0 +1,11 @@
+---
+- name: Playbook for Keycloak Hosts
+ hosts: keycloak
+ collections:
+ - middleware_automation.redhat_csp_download
+ roles:
+ - redhat_csp_download
+ tasks:
+ - name: Keycloak Role
+ include_role:
+ name: keycloak
\ No newline at end of file
diff --git a/requirements.yml b/requirements.yml
new file mode 100644
index 0000000..1cca528
--- /dev/null
+++ b/requirements.yml
@@ -0,0 +1,7 @@
+---
+collections:
+ - name: middleware_automation.redhat_csp_download
+ version: ">=1.2.1"
+ - name: middleware_automation.jcliff
+ version: ">=0.0.19"
+ - name: community.general
diff --git a/roles/keycloak/defaults/main.yml b/roles/keycloak/defaults/main.yml
new file mode 100644
index 0000000..af9ccdc
--- /dev/null
+++ b/roles/keycloak/defaults/main.yml
@@ -0,0 +1,71 @@
+---
+### Configuration specific to keycloak
+keycloak_version: 9.0.2
+keycloak_archive: keycloak-{{ keycloak_version }}.zip
+keycloak_download_url: https://downloads.jboss.org/keycloak/{{ keycloak_version }}/{{ keycloak_archive }}
+keycloak_local_download_dest: '{{ "~/keycloak_download" | expanduser }}'
+keycloak_installdir: "{{ keycloak_dest }}/keycloak-{{ keycloak_version }}"
+
+### Configuration specific to Red Hat Single Sing-On
+keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined else False }}"
+keycloak_rhsso_client_adapter_rhn_id: '101951'
+keycloak_rhsso_saml_adapter_rhn_id: '101901'
+keycloak_rhsso_version: 7.5
+keycloak_rhsso_archive: rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip
+keycloak_rhsso_installdir: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version }}"
+
+### Install location and service settings
+keycloak_dest: /opt/keycloak
+keycloak_jboss_home: "{{ keycloak_rhsso_installdir if rhsso_rhn_id is defined else keycloak_installdir }}"
+keycloak_config_dir: "{{ keycloak_jboss_home }}/standalone/configuration"
+keycloak_service_user: keycloak
+keycloak_service_group: keycloak
+keycloak_service_pidfile: "{{ keycloak_dest }}/keycloak.pid"
+keycloak_service_logfile: "{{ keycloak_dest }}/keycloak.log"
+
+### Keycloak configuration settings
+keycloak_bind_address: 0.0.0.0
+keycloak_host: localhost
+keycloak_http_port: 8080
+keycloak_https_port: 8443
+keycloak_management_http_port: 9990
+keycloak_management_https_port: 9993
+keycloak_java_opts: "-Xms1024m -Xmx20480m -XX:MaxPermSize=768m"
+keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
+keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
+# enable auto configuration for database backend, clustering and remote caches on infinispan
+keycloak_ha_enabled: False
+
+# keycloak administration console user
+keycloak_admin_user: admin
+keycloak_admin_password: "password"
+
+keycloak_auth_realm: master
+keycloak_auth_client: admin-cli
+
+keycloak_force_install: False
+
+keycloak_modcluster:
+ enabled: "{{ keycloak_ha_enabled }}"
+ reverse_proxy_url: jbcs-0
+
+keycloak_remotecache:
+ enabled: "{{ keycloak_ha_enabled }}"
+ username: supervisor
+ password: itsme
+ realm: default
+ server_name: jdg-1
+ trust_store_path: /path/to/jks/keystore
+ trust_store_password: changeme
+
+keycloak_jdbc:
+ postgres:
+ enabled: "{{ keycloak_ha_enabled }}"
+ driver_module_name: "org.postgresql"
+ driver_module_dir: "{{ keycloak_jboss_home }}/modules/org/postgresql/main"
+ driver_version: 9.4.1212
+ driver_jar_filename: "postgresql-9.4.1212.jar"
+ driver_jar_url: "https://repo.maven.apache.org/maven2/org/postgresql/postgresql/9.4.1212/postgresql-9.4.1212.jar"
+ connection_url: "jdbc:postgresql://pgsql-0:5432/keycloak"
+ db_user: "keycloak-user"
+ db_password: "keycloak-pass"
diff --git a/roles/keycloak/handlers/main.yml b/roles/keycloak/handlers/main.yml
new file mode 100644
index 0000000..6faa06c
--- /dev/null
+++ b/roles/keycloak/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart keycloak
+ include_tasks: restart_keycloak.yml
diff --git a/roles/keycloak/meta/main.yml b/roles/keycloak/meta/main.yml
new file mode 100644
index 0000000..2cc2def
--- /dev/null
+++ b/roles/keycloak/meta/main.yml
@@ -0,0 +1,56 @@
+galaxy_info:
+ author: your name
+ description: your role description
+ company: your company (optional)
+
+ # If the issue tracker for your role is not on github, uncomment the
+ # next line and provide a value
+ # issue_tracker_url: http://example.com/issue/tracker
+
+ # Choose a valid license ID from https://spdx.org - some suggested licenses:
+ # - BSD-3-Clause (default)
+ # - MIT
+ # - GPL-2.0-or-later
+ # - GPL-3.0-only
+ # - Apache-2.0
+ # - CC-BY-4.0
+ license: license (GPL-2.0-or-later, MIT, etc)
+
+ min_ansible_version: 2.9
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ #
+ # Provide a list of supported platforms, and for each platform a list of versions.
+ # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+ # To view available platforms and versions (or releases), visit:
+ # https://galaxy.ansible.com/api/v1/platforms/
+ #
+ # platforms:
+ # - name: Fedora
+ # versions:
+ # - all
+ # - 25
+ # - name: SomePlatform
+ # versions:
+ # - all
+ # - 1.0
+ # - 7
+ # - 99.99
+
+ galaxy_tags: []
+ # List tags for your role here, one per line. A tag is a keyword that describes
+ # and categorizes the role. Users find roles by searching for tags. Be sure to
+ # remove the '[]' above, if you add tags to this list.
+ #
+ # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
+ # Maximum 20 tags per role.
+
+dependencies: []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
+
+collections:
+ - middleware_automation.redhat_csp_download
+ - middleware_automation.jcliff
diff --git a/roles/keycloak/tasks/download_from_rhn.yml b/roles/keycloak/tasks/download_from_rhn.yml
new file mode 100644
index 0000000..edfcf01
--- /dev/null
+++ b/roles/keycloak/tasks/download_from_rhn.yml
@@ -0,0 +1,72 @@
+---
+- assert:
+ that:
+ - zipfile_dest is defined
+ - rhn_id_file is defined
+ - rhn_username is defined
+ - rhn_password is defined
+ quiet: true
+
+- set_fact:
+ rhn_base_url: "{{ override_rhn_base_url | default('https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId=') }}"
+ rhn_download_url: "{{ rhn_base_url }}{{ rhn_id_file }}"
+
+- name: "Check zipfile dest directory {{ zipfile_dest }}"
+ stat:
+ path: "{{ zipfile_dest }}"
+ register: archive_path
+
+- name: "Install zipfile from RHN: {{ rhn_download_url }}"
+ redhat_csp_download:
+ url: "{{ rhn_download_url }}"
+ dest: "{{ zipfile_dest }}"
+ username: "{{ rhn_username }}"
+ password: "{{ rhn_password }}"
+ no_log: "{{ omit_rhn_output | default(true) }}"
+ when:
+ - archive_path is defined
+ - archive_path.stat is defined
+ - not archive_path.stat.exists
+
+- name: "Check zipfile dest directory {{ zipfile_dest }}"
+ stat:
+ path: "{{ zipfile_dest }}"
+ register: path_to_downloaded_artefact
+
+- block:
+ - file:
+ path: "{{ work_dir }}"
+ state: directory
+
+ - stat:
+ path: "{{ target_dir }}"
+ register: target_dir_state
+
+ - assert:
+ that:
+ - target_dir_state is defined
+ - target_dir_state.stat is defined
+ fail_msg: "Directory layout for {{ target_dir }} is invalid."
+ quiet: true
+
+ - name: "Decompress {{ zipfile_dest }} into {{ work_dir }} (results in {{ target_dir }}."
+ unarchive:
+ src: "{{ zipfile_dest }}"
+ dest: "{{ work_dir }}"
+ owner: "{{ keycloak_service_user }}"
+ group: "{{ keycloak_service_user }}"
+ remote_src: yes
+ creates: "{{ target_dir }}"
+ when:
+ - not target_dir_state.stat.exists
+
+ - debug:
+ msg: "{{ target_dir }} already exists, skipping decompressing {{ zipfile_dest }}"
+ when:
+ - target_dir_state.stat.exists
+ when:
+ - path_to_downloaded_artefact is defined
+ - path_to_downloaded_artefact.stat is defined
+ - path_to_downloaded_artefact.stat.exists
+ - target_dir is defined
+ - work_dir is defined
diff --git a/roles/keycloak/tasks/fastpackages/check.yml b/roles/keycloak/tasks/fastpackages/check.yml
new file mode 100644
index 0000000..a31d28b
--- /dev/null
+++ b/roles/keycloak/tasks/fastpackages/check.yml
@@ -0,0 +1,14 @@
+---
+- block:
+ - name: "Check if package {{ package_name }} is already installed"
+ command: rpm -q {{ package_name }}
+ args:
+ warn: no
+ register: rpm_info
+ changed_when: rpm_info.failed
+
+ rescue:
+ - name: "If package {{ package_name }} is missing, add it to the yum install list."
+ set_fact:
+ packages_to_install: "{{ packages_to_install + [ package_name ] }}"
+ when: rpm_info.failed
\ No newline at end of file
diff --git a/roles/keycloak/tasks/fastpackages/install.yml b/roles/keycloak/tasks/fastpackages/install.yml
new file mode 100644
index 0000000..0f71965
--- /dev/null
+++ b/roles/keycloak/tasks/fastpackages/install.yml
@@ -0,0 +1,17 @@
+---
+- set_fact:
+ update_cache: true
+ packages_to_install: []
+
+- name: "Check packages to be installed"
+ include_tasks: check.yml
+ loop: "{{ packages_list | flatten }}"
+ loop_control:
+ loop_var: package_name
+
+- name: "Install packages: {{ packages_to_install }}"
+ become: yes
+ yum:
+ name: "{{ packages_to_install }}"
+ state: present
+ when: packages_to_install | length > 0
\ No newline at end of file
diff --git a/roles/keycloak/tasks/firewalld.yml b/roles/keycloak/tasks/firewalld.yml
new file mode 100644
index 0000000..346d58d
--- /dev/null
+++ b/roles/keycloak/tasks/firewalld.yml
@@ -0,0 +1,25 @@
+---
+- name: Ensures required package firewalld are installed
+ ansible.builtin.include_tasks: fastpackages/install.yml
+ vars:
+ packages_list:
+ - firewalld
+
+- name: Enable and start the firewalld service
+ become: yes
+ systemd:
+ name: firewalld
+ enabled: yes
+ state: started
+
+- name: Configure firewall for jdg ports
+ become: yes
+ ansible.posix.firewalld:
+ port: "{{ item }}"
+ permanent: true
+ state: enabled
+ immediate: yes
+ loop:
+ - "{{ keycloak_http_port }}/tcp"
+ - "{{ keycloak_https_port }}/tcp"
+ - "8009/tcp"
diff --git a/roles/keycloak/tasks/install.yml b/roles/keycloak/tasks/install.yml
new file mode 100644
index 0000000..120ad46
--- /dev/null
+++ b/roles/keycloak/tasks/install.yml
@@ -0,0 +1,141 @@
+---
+- assert:
+ that:
+ - keycloak_jboss_home is defined
+ - keycloak_service_user is defined
+ - keycloak_dest is defined
+ - keycloak_archive is defined
+ - keycloak_download_url is defined
+ - keycloak_version is defined
+ quiet: true
+
+- set_fact:
+ keycloak_service_group: "{{ keycloak_service_user }}"
+ when:
+ - not keycloak_service_group is defined
+
+- name: check for an existing deployment
+ become: yes
+ stat:
+ path: "{{ keycloak_jboss_home }}"
+ register: existing_deploy
+
+- block:
+ - name: stop the old keycloak service
+ become: yes
+ ignore_errors: yes
+ systemd:
+ name: keycloak
+ state: stopped
+ - name: remove the old Keycloak deployment
+ become: yes
+ file:
+ path: "{{ keycloak_jboss_home }}"
+ state: absent
+ when: existing_deploy.stat.exists and keycloak_force_install|bool
+
+- name: check for an existing deployment after possible forced removal
+ become: yes
+ stat:
+ path: "{{ keycloak_jboss_home }}"
+
+- name: create Keycloak service user/group
+ become: yes
+ user:
+ name: "{{ keycloak_service_user }}"
+ home: /opt/keycloak
+ system: yes
+ create_home: no
+
+- name: create Keycloak install location
+ become: yes
+ file:
+ dest: "{{ keycloak_dest }}"
+ state: directory
+ owner: "{{ keycloak_service_user }}"
+ group: "{{ keycloak_service_group }}"
+
+- block:
+ - set_fact:
+ archive: "{{ keycloak_dest }}/{{ keycloak_archive }}"
+ - name: "Check archive directory {{ archive }}"
+ stat:
+ path: "{{ archive }}"
+ register: archive_path
+
+ - name: download Keycloak archive to target
+ get_url:
+ url: "{{ keycloak_download_url }}"
+ dest: "{{ keycloak_dest }}"
+ owner: "{{ keycloak_service_user }}"
+ group: "{{ keycloak_service_group }}"
+ when:
+ - archive_path is defined
+ - archive_path.stat is defined
+ - not archive_path.stat.exists
+
+ - name: extract Keycloak archive on target
+ unarchive:
+ remote_src: yes
+ src: "{{ archive }}"
+ dest: "{{ keycloak_dest }}"
+ creates: "{{ keycloak_jboss_home }}"
+ owner: "{{ keycloak_service_user }}"
+ group: "{{ keycloak_service_group }}"
+ notify:
+ - restart keycloak
+ become: yes
+ when: not keycloak_rhsso_enable
+
+- block:
+ - assert:
+ that:
+ - rhsso_rhn_id is defined
+ quiet: true
+ fail_msg: "Can't install RHSSO without RHN ID."
+
+ - name: create download directory
+ file:
+ path: /opt/apps
+ state: directory
+
+ - include_tasks: download_from_rhn.yml
+ vars:
+ rhn_id_file: "{{ rhsso_rhn_id }}"
+ zipfile_dest: "{{ keycloak_dest }}/{{ keycloak_rhsso_archive }}"
+ work_dir: "{{ keycloak_dest }}"
+ target_dir: "{{ keycloak_jboss_home }}"
+ become: yes
+ when: keycloak_rhsso_enable
+
+- name: "Install Postresql driver"
+ include_role:
+ name: wildfly_driver
+ tasks_from: jdbc_driver.yml
+ vars:
+ wildfly_user: "{{ keycloak_service_user }}"
+ jdbc_driver_module_dir: "{{ keycloak_jdbc.postgres.driver_module_dir }}"
+ jdbc_driver_version: "{{ keycloak_jdbc.postgres.driver_version }}"
+ jdbc_driver_jar_filename: "{{ keycloak_jdbc.postgres.driver_jar_filename }}"
+ jdbc_driver_jar_url: "{{ keycloak_jdbc.postgres.driver_jar_url }}"
+ jdbc_driver_jar_installation_path: "{{ keycloak_jdbc.postgres.driver_module_dir }}/{{ keycloak_jdbc.postgres.driver_jar_filename }}"
+ jdbc_driver_module_name: "{{ keycloak_jdbc.postgres.driver_module_name }}"
+ when: keycloak_jdbc.postgres.enabled
+
+- name: "Deploy Keycloak's standalone.xml"
+ become: yes
+ template:
+ src: "{{ 'templates/standalone-rhsso.xml.j2' if keycloak_rhsso_enable else 'templates/standalone.xml.j2' }}"
+ dest: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml"
+ notify:
+ - restart keycloak
+ when: not keycloak_remotecache.enabled
+
+- name: "Deploy Keycloak's standalone.xml with remote cache store"
+ become: yes
+ template:
+ src: "{{ 'templates/standalone-rhsso-jdg.xml.j2' if keycloak_rhsso_enable else 'templates/standalone-infinispan.xml.j2' }}"
+ dest: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml"
+ notify:
+ - restart keycloak
+ when: keycloak_remotecache.enabled
diff --git a/roles/keycloak/tasks/main.yml b/roles/keycloak/tasks/main.yml
new file mode 100644
index 0000000..97407c9
--- /dev/null
+++ b/roles/keycloak/tasks/main.yml
@@ -0,0 +1,24 @@
+---
+# tasks file for keycloak
+
+- name: Prerequisites
+ include_tasks: prereqs.yml
+ tags:
+ - prereqs
+
+- include_tasks: tasks/install.yml
+
+- name: create Keycloak admin user
+ command:
+ args:
+ argv:
+ - "{{ keycloak_jboss_home }}/bin/add-user-keycloak.sh"
+ - -rmaster
+ - -u{{ keycloak_admin_user }}
+ - -p{{ keycloak_admin_password }}
+ creates: "{{ keycloak_config_dir }}/keycloak-add-user.json"
+ become: yes
+
+- include_tasks: tasks/systemd.yml
+
+
diff --git a/roles/keycloak/tasks/manage_client_roles.yml b/roles/keycloak/tasks/manage_client_roles.yml
new file mode 100644
index 0000000..d7fca8d
--- /dev/null
+++ b/roles/keycloak/tasks/manage_client_roles.yml
@@ -0,0 +1,12 @@
+- name: Create client roles
+ community.general.keycloak_role:
+ name: "{{ item }}"
+ realm: "{{ client.realm }}"
+ client_id: "{{ client.name }}"
+ auth_client_id: "{{ keycloak_auth_client }}"
+ auth_keycloak_url: "{{ keycloak_url }}/auth"
+ auth_realm: "{{ keycloak_auth_realm }}"
+ auth_username: "{{ keycloak_admin_user }}"
+ auth_password: "{{ keycloak_admin_password }}"
+ state: present
+ loop: "{{ client.roles | flatten }}"
diff --git a/roles/keycloak/tasks/manage_realm.yml b/roles/keycloak/tasks/manage_realm.yml
new file mode 100644
index 0000000..76b260f
--- /dev/null
+++ b/roles/keycloak/tasks/manage_realm.yml
@@ -0,0 +1,73 @@
+---
+- name: Generate keycloak auth token
+ uri:
+ url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
+ method: POST
+ body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password"
+ validate_certs: no
+ register: keycloak_auth_response
+ until: keycloak_auth_response.status == 200
+ retries: 5
+ delay: 2
+
+- name: "Determine if realm exists"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}"
+ method: GET
+ status_code:
+ - 200
+ - 404
+ headers:
+ Accept: "application/json"
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: keycloak_realm_exists
+
+- name: Create Realm
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms"
+ method: POST
+ body: "{{ lookup('template','realm.json.j2') }}"
+ validate_certs: no
+ body_format: json
+ headers:
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ status_code: 201
+ when: keycloak_realm_exists.status == 404
+
+- name: Create Client
+ community.general.keycloak_client:
+ auth_client_id: "{{ keycloak_auth_client }}"
+ auth_keycloak_url: "{{ keycloak_url }}/auth"
+ auth_realm: "{{ keycloak_auth_realm }}"
+ auth_username: "{{ keycloak_admin_user }}"
+ auth_password: "{{ keycloak_admin_password }}"
+ client_id: "{{ item.name }}"
+ realm: "{{ item.realm }}"
+ default_roles: "{{ item.roles | default(omit) }}"
+ root_url: "{{ item.root_url | default('') }}"
+ redirect_uris: "{{ demo_app_redirect_uris | default([]) }}"
+ public_client: "{{ item.public_client | default(False) }}"
+ web_origins: "{{ item.web_origins | default('+') }}"
+ state: present
+ register: create_client_result
+ loop: "{{ keycloak_clients | flatten }}"
+
+- name: Create client roles
+ include_tasks: manage_client_roles.yml
+ when: keycloak_rhsso_enable
+ loop: "{{ keycloak_clients | flatten }}"
+ loop_control:
+ loop_var: client
+
+- name: Manage Users
+ include_tasks: manage_user.yml
+ loop: "{{ keycloak_users }}"
+ loop_control:
+ loop_var: user
+
+- name: Manage User Roles
+ include_tasks: manage_user_roles.yml
+ loop: "{{ keycloak_users | flatten }}"
+ loop_control:
+ loop_var: user
+ when: "'client_roles' in user"
\ No newline at end of file
diff --git a/roles/keycloak/tasks/manage_user.yml b/roles/keycloak/tasks/manage_user.yml
new file mode 100644
index 0000000..019d65b
--- /dev/null
+++ b/roles/keycloak/tasks/manage_user.yml
@@ -0,0 +1,51 @@
+---
+- name: "Check if User Already Exists"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
+ validate_certs: no
+ headers:
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: keycloak_user_serach_result
+
+- name: "Create User"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users"
+ method: POST
+ body:
+ enabled: true
+ attributes: "{{ user.attributes | default(omit) }}"
+ username: "{{ user.username }}"
+ email: "{{ user.email | default(omit) }}"
+ firstName: "{{ user.firstName | default(omit) }}"
+ lastName: "{{ user.lastName | default(omit) }}"
+ validate_certs: no
+ body_format: json
+ headers:
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ status_code: 201
+ when: keycloak_user_serach_result.json | length == 0
+
+- name: "Get User"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
+ validate_certs: no
+ headers:
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: keycloak_user
+
+- name: "Update User Password"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users/{{ (keycloak_user.json | first).id }}/reset-password"
+ method: PUT
+ body:
+ type: password
+ temporary: false
+ value: "{{ user.password }}"
+ validate_certs: no
+ body_format: json
+ status_code:
+ - 200
+ - 204
+ headers:
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: keycloak_user
diff --git a/roles/keycloak/tasks/manage_user_client_roles.yml b/roles/keycloak/tasks/manage_user_client_roles.yml
new file mode 100644
index 0000000..562ff09
--- /dev/null
+++ b/roles/keycloak/tasks/manage_user_client_roles.yml
@@ -0,0 +1,40 @@
+---
+- name: "Get Realm for role"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ client_role.realm }}"
+ method: GET
+ status_code:
+ - 200
+ headers:
+ Accept: "application/json"
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: client_role_realm
+
+- name: Check if Mapping is available
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ client_role.realm }}/users/{{ (keycloak_user.json | first).id }}/role-mappings/clients/{{ (create_client_result.results | selectattr('end_state.clientId', 'equalto', client_role.client) | list | first).end_state.id }}/available"
+ method: GET
+ status_code:
+ - 200
+ headers:
+ Accept: "application/json"
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: client_role_user_available
+
+- name: "Create Role Mapping"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ client_role.realm }}/users/{{ (keycloak_user.json | first).id }}/role-mappings/clients/{{ (create_client_result.results | selectattr('end_state.clientId', 'equalto', client_role.client) | list | first).end_state.id }}"
+ method: POST
+ body:
+ - id: "{{ item.id }}"
+ clientRole: "{{ item.clientRole }}"
+ containerId: "{{ item.containerId }}"
+ name: "{{ item.name }}"
+ composite: "{{ item.composite }}"
+ validate_certs: False
+ body_format: json
+ headers:
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ status_code: 204
+ loop: "{{ client_role_user_available.json | flatten }}"
+ when: item.name == client_role.role
diff --git a/roles/keycloak/tasks/manage_user_roles.yml b/roles/keycloak/tasks/manage_user_roles.yml
new file mode 100644
index 0000000..82ee948
--- /dev/null
+++ b/roles/keycloak/tasks/manage_user_roles.yml
@@ -0,0 +1,26 @@
+---
+
+- name: "Get User {{ user.username }}"
+ uri:
+ url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
+ headers:
+ validate_certs: no
+ Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
+ register: keycloak_user
+
+- name: Refresh keycloak auth token
+ uri:
+ url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
+ method: POST
+ body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password"
+ validate_certs: no
+ register: keycloak_auth_response
+ until: keycloak_auth_response.status == 200
+ retries: 5
+ delay: 2
+
+- name: "Manage Client Role Mapping for {{ user.username }}"
+ include_tasks: manage_user_client_roles.yml
+ loop: "{{ user.client_roles | flatten }}"
+ loop_control:
+ loop_var: client_role
diff --git a/roles/keycloak/tasks/prereqs.yml b/roles/keycloak/tasks/prereqs.yml
new file mode 100644
index 0000000..b6abb88
--- /dev/null
+++ b/roles/keycloak/tasks/prereqs.yml
@@ -0,0 +1,12 @@
+---
+- set_fact:
+ required_packages:
+ - "{{ jvm_package | default('java-1.8.0-openjdk-devel') }}"
+ - unzip
+ - procps-ng
+ - initscripts
+
+- name: "Ensures required packages are installed"
+ ansible.builtin.include_tasks: fastpackages/install.yml
+ vars:
+ packages_list: "{{ required_packages }}"
\ No newline at end of file
diff --git a/roles/keycloak/tasks/restart_keycloak.yml b/roles/keycloak/tasks/restart_keycloak.yml
new file mode 100644
index 0000000..774d14d
--- /dev/null
+++ b/roles/keycloak/tasks/restart_keycloak.yml
@@ -0,0 +1,7 @@
+---
+- name: "Restart and enable keycloack service"
+ systemd:
+ name: keycloak
+ enabled: yes
+ state: restarted
+ become: yes
diff --git a/roles/keycloak/tasks/stop_keycloak.yml b/roles/keycloak/tasks/stop_keycloak.yml
new file mode 100644
index 0000000..d6203b2
--- /dev/null
+++ b/roles/keycloak/tasks/stop_keycloak.yml
@@ -0,0 +1,7 @@
+---
+- name: "Stop SSO service"
+ systemd:
+ name: keycloak
+ enabled: yes
+ state: stopped
+ become: yes
diff --git a/roles/keycloak/tasks/systemd.yml b/roles/keycloak/tasks/systemd.yml
new file mode 100644
index 0000000..67fd2e1
--- /dev/null
+++ b/roles/keycloak/tasks/systemd.yml
@@ -0,0 +1,65 @@
+- name: configure keycloak service script wrapper
+ become: yes
+ template:
+ src: keycloak-service.sh.j2
+ dest: "{{ keycloak_dest }}/keycloak-service.sh"
+ owner: root
+ group: root
+ mode: 0755
+ notify:
+ - restart keycloak
+
+- name: configure sysconfig file for keycloak service
+ become: yes
+ template:
+ src: keycloak-sysconfig.j2
+ dest: /etc/sysconfig/keycloak
+ owner: root
+ group: root
+ mode: 0644
+ notify:
+ - restart keycloak
+
+- name: configure systemd unit file for keycloak service
+ template:
+ src: keycloak.service.j2
+ dest: /etc/systemd/system/keycloak.service
+ owner: root
+ group: root
+ mode: 0644
+ become: yes
+ register: systemdunit
+ notify:
+ - restart keycloak
+
+- name: reload systemd
+ become: yes
+ systemd:
+ daemon_reload: yes
+ when: systemdunit.changed
+
+- name: start keycloak
+ systemd:
+ name: keycloak
+ enabled: yes
+ state: started
+ become: yes
+
+- command: "systemctl status keycloak"
+ register: keycloak_service_status
+ changed_when: False
+
+- assert:
+ that:
+ - keycloak_service_status is defined
+ - keycloak_service_status.stdout is defined
+
+- meta: flush_handlers
+
+- name: Wait until Keycloak becomes active
+ uri:
+ url: "{{ keycloak_management_url }}/health"
+ register: keycloak_status
+ until: keycloak_status.status == 200
+ retries: 20
+ delay: 10
diff --git a/roles/keycloak/templates/keycloak-service.sh.j2 b/roles/keycloak/templates/keycloak-service.sh.j2
new file mode 100755
index 0000000..ebbecf0
--- /dev/null
+++ b/roles/keycloak/templates/keycloak-service.sh.j2
@@ -0,0 +1,125 @@
+#!/bin/bash
+set -eo pipefail
+
+checkEnvVar() {
+ local envVar=${1}
+ local msg=${2}
+ local exitCode=${3}
+
+ if [ -z "${envVar}" ]; then
+ echo "${msg}"
+ exit "${exitCode}"
+ fi
+}
+# SystemD will do for the unit, decomment
+# for testing outside systemd
+. /etc/sysconfig/keycloak
+
+readonly KEYCLOAK_HOME={{ keycloak_jboss_home }}
+readonly KEYCLOAK_BIND_ADDRESS=${KEYCLOAK_BIND_ADDRESS}
+readonly KEYCLOAK_HTTP_PORT=${KEYCLOAK_HTTP_PORT}
+readonly KEYCLOAK_HTTPS_PORT=${KEYCLOAK_HTTPS_PORT}
+readonly KEYCLOAK_MANAGEMENT_HTTP_PORT=${KEYCLOAK_MANAGEMENT_HTTP_PORT}
+readonly KEYCLOAK_MANAGEMENT_HTTPS_PORT=${KEYCLOAK_MANAGEMENT_HTTPS_PORT}
+readonly KEYCLOAK_LOGFILE={{ keycloak_service_logfile }}
+readonly KEYCLOAK_PIDFILE={{ keycloak_service_pidfile }}
+
+set -u
+if [ ! -d "${KEYCLOAK_HOME}" ]; then
+ echo "KEYCLOAK_HOME (${KEYCLOAK_HOME}) is not a director or does not exists."
+ exit 1
+fi
+
+checkEnvVar "${KEYCLOAK_PIDFILE}" 'KEYCLOAK_PIDFILE not provided' 2
+
+getKeycloakPID() {
+
+ local pid
+ if [ -e "${KEYCLOAK_PIDFILE}" ]; then
+ cat "${KEYCLOAK_PIDFILE}"
+ fi
+}
+
+statusKeycloak() {
+
+ if [ "$(isKeyCloakRunning)" -eq 1 ]; then
+ echo "Keycloak is running (PID:$(getKeycloakPID ))"
+ else
+ echo "Keycloak is NOT running."
+ fi
+}
+
+isKeyCloakRunning() {
+ set +e
+ local statusKeycloak=0
+ local pid=$(getKeycloakPID )
+ if [ -n "${pid}" ]; then
+ kill -0 "${pid}" 2> /dev/null
+ if [ "${?}" -eq 0 ]; then
+ statusKeycloak=1
+ fi
+ fi
+ set -e
+ echo "${statusKeycloak}"
+}
+
+startKeycloak() {
+ checkEnvVar "${KEYCLOAK_BIND_ADDRESS}" 'KEYCLOAK_BIND_ADDRESS not provided' 2
+ checkEnvVar "${KEYCLOAK_HTTP_PORT}" 'KEYCLOAK_HTTP_PORT not provided' 4
+ checkEnvVar "${KEYCLOAK_HTTPS_PORT}" 'KEYCLOAK_HTTPS_PORT not provided' 5
+ checkEnvVar "${KEYCLOAK_MANAGEMENT_HTTP_PORT}" 'KEYCLOAK_MANAGEMENT_HTTP_PORT not provided' 6
+ checkEnvVar "${KEYCLOAK_MANAGEMENT_HTTPS_PORT}" 'KEYCLOAK_MANAGEMENT_HTTPS_PORT not provided' 7
+ checkEnvVar "${KEYCLOAK_LOGFILE}" 'KEYCLOAK_LOGFILE not provided' 8
+
+ if [ "$(isKeyCloakRunning)" -eq 1 ]; then
+ statusKeycloak
+ else
+ ${KEYCLOAK_HOME}/bin/standalone.sh \
+ -Djboss.bind.address=${KEYCLOAK_BIND_ADDRESS} \
+ -Djboss.http.port=${KEYCLOAK_HTTP_PORT} \
+ -Djboss.https.port=${KEYCLOAK_HTTPS_PORT} \
+ -Djboss.management.http.port=${KEYCLOAK_MANAGEMENT_HTTP_PORT} \
+ -Djboss.management.https.port=${KEYCLOAK_MANAGEMENT_HTTPS_PORT} \
+ -Djboss.node.name={{ inventory_hostname }} 2>&1 >> "${KEYCLOAK_LOGFILE}" &
+ echo "${!}" > "${KEYCLOAK_PIDFILE}"
+ fi
+}
+
+stopKeycloak() {
+ local pid=$(getKeycloakPID)
+ if [ -n "${pid}" ]; then
+ set +e
+ kill ${pid} 2> /dev/null
+ kill -0 "${pid}" 2> /dev/null
+# if [ "${?}" -eq 0 ]; then
+# sleep 5
+# kill -9 "${pid}" > /dev/null
+# fi
+ set -e
+ deletePidFile
+ fi
+}
+
+deletePidFile() {
+ rm -f "${KEYCLOAK_PIDFILE}"
+}
+
+case "$1" in
+ start)
+ startKeycloak
+ ;;
+ stop)
+ stopKeycloak
+ ;;
+ restart)
+ stopKeycloak
+ startKeycloak
+ ;;
+ status)
+ statusKeycloak
+ ;;
+ *)
+ echo "usage: $0 start|stop|restart" >&2
+ exit 1
+ ;;
+esac
diff --git a/roles/keycloak/templates/keycloak-sysconfig.j2 b/roles/keycloak/templates/keycloak-sysconfig.j2
new file mode 100644
index 0000000..d0682ac
--- /dev/null
+++ b/roles/keycloak/templates/keycloak-sysconfig.j2
@@ -0,0 +1,7 @@
+JAVA_OPTS='{{ keycloak_java_opts }}'
+JBOSS_HOME={{ keycloak_jboss_home }}
+KEYCLOAK_BIND_ADDRESS={{ keycloak_bind_address }}
+KEYCLOAK_HTTP_PORT={{ keycloak_http_port }}
+KEYCLOAK_HTTPS_PORT={{ keycloak_https_port }}
+KEYCLOAK_MANAGEMENT_HTTP_PORT={{ keycloak_management_http_port }}
+KEYCLOAK_MANAGEMENT_HTTPS_PORT={{ keycloak_management_https_port }}
diff --git a/roles/keycloak/templates/keycloak.service.j2 b/roles/keycloak/templates/keycloak.service.j2
new file mode 100644
index 0000000..a3aa846
--- /dev/null
+++ b/roles/keycloak/templates/keycloak.service.j2
@@ -0,0 +1,19 @@
+[Unit]
+Description=Keycloak Server
+After=network.target
+
+[Service]
+Type=forking
+EnvironmentFile=-/etc/sysconfig/keycloak
+
+User={{ keycloak_service_user }}
+Group={{ keycloak_service_group }}
+PIDFile={{ keycloak_service_pidfile }}
+ExecStart={{ keycloak_dest }}/keycloak-service.sh start
+ExecStop={{ keycloak_dest }}/keycloak-service.sh stop
+TimeoutStartSec=60
+TimeoutStopSec=60
+LimitNOFILE=102642
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/keycloak/templates/realm.json.j2 b/roles/keycloak/templates/realm.json.j2
new file mode 100644
index 0000000..88ee819
--- /dev/null
+++ b/roles/keycloak/templates/realm.json.j2
@@ -0,0 +1,7 @@
+{
+ "id": "{{ keycloak_realm }}",
+ "realm": "{{ keycloak_realm }}",
+ "enabled": true,
+ "eventsEnabled": true,
+ "eventsExpiration": 7200
+}
\ No newline at end of file
diff --git a/roles/keycloak/templates/standalone-infinispan.xml.j2 b/roles/keycloak/templates/standalone-infinispan.xml.j2
new file mode 100644
index 0000000..d63072a
--- /dev/null
+++ b/roles/keycloak/templates/standalone-infinispan.xml.j2
@@ -0,0 +1,719 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ h2
+
+ sa
+ sa
+
+
+
+{% if keycloak_jdbc.postgres.enabled %}
+ {{ keycloak_jdbc.postgres.connection_url }}
+ {{ keycloak_jdbc.postgres.driver_module_name }}
+
+ 20
+
+
+ {{ keycloak_jdbc.postgres.db_user }}
+ {{ keycloak_jdbc.postgres.db_password }}
+
+{% else %}
+ jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE
+ h2
+
+ sa
+ sa
+
+{% endif %}
+
+
+{% if keycloak_jdbc.postgres.enabled %}
+
+ org.postgresql.Driver
+ org.postgresql.xa.PGXADataSource
+
+{% endif %}
+
+ org.h2.jdbcx.JdbcDataSource
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens" ] %}
+
+
+ true
+ org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
+ false
+ {{ keycloak_remotecache.username }}
+ {{ keycloak_remotecache.password }}
+ {{ keycloak_remotecache.realm | default('default') }}
+ {{ keycloak_remotecache.server_name }}
+ {{ keycloak_remotecache.sasl_mechanism | default('SCRAM-SHA-512') }}
+ false
+ {{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}
+ JKS
+ {{ keycloak_remotecache.trust_store_password | default("changeme") }}
+
+
+ {% endfor %}
+
+
+ true
+ org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
+ false
+ {{ keycloak_remotecache.username }}
+ {{ keycloak_remotecache.password }}
+ {{ keycloak_remotecache.realm | default('default') }}
+ {{ keycloak_remotecache.server_name }}
+ {{ keycloak_remotecache.sasl_mechanism | default('SCRAM-SHA-512') }}
+ false
+ {{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}
+ JKS
+ {{ keycloak_remotecache.trust_store_password | default("changeme") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ auth
+
+
+ classpath:${jboss.home.dir}/providers/*
+
+
+ master
+ 900
+
+ 2592000
+ true
+ true
+ ${jboss.home.dir}/themes
+
+
+
+
+
+
+
+
+
+
+
+
+ jpa
+
+
+ basic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default
+
+
+
+
+
+
+
+ ${keycloak.jta.lookup.provider:jboss}
+
+
+
+
+
+
+
+
+
+
+ ${keycloak.x509cert.lookup.provider:default}
+
+
+
+ default
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+
+
+
+
+{% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+{% endif %}
+
+
+
+
+
diff --git a/roles/keycloak/templates/standalone-rhsso-jdg.xml.j2 b/roles/keycloak/templates/standalone-rhsso-jdg.xml.j2
new file mode 100644
index 0000000..c308dde
--- /dev/null
+++ b/roles/keycloak/templates/standalone-rhsso-jdg.xml.j2
@@ -0,0 +1,719 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ h2
+
+ sa
+ sa
+
+
+
+{% if keycloak_jdbc.postgres.enabled %}
+ {{ keycloak_jdbc.postgres.connection_url }}
+ {{ keycloak_jdbc.postgres.driver_module_name }}
+
+ 20
+
+
+ {{ keycloak_jdbc.postgres.db_user }}
+ {{ keycloak_jdbc.postgres.db_password }}
+
+{% else %}
+ jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE
+ h2
+
+ sa
+ sa
+
+{% endif %}
+
+
+{% if keycloak_jdbc.postgres.enabled %}
+
+ org.postgresql.Driver
+ org.postgresql.xa.PGXADataSource
+
+{% endif %}
+
+ org.h2.jdbcx.JdbcDataSource
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens" ] %}
+
+
+ true
+ org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
+ false
+ {{ keycloak_remotecache.username }}
+ {{ keycloak_remotecache.password }}
+ {{ keycloak_remotecache.realm | default('default') }}
+ {{ keycloak_remotecache.server_name }}
+ {{ keycloak_remotecache.sasl_mechanism | default('SCRAM-SHA-512') }}
+ false
+ {{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}
+ JKS
+ {{ keycloak_remotecache.trust_store_password | default("changeme") }}
+
+
+ {% endfor %}
+
+
+ true
+ org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
+ false
+ {{ keycloak_remotecache.username }}
+ {{ keycloak_remotecache.password }}
+ {{ keycloak_remotecache.realm | default('default') }}
+ {{ keycloak_remotecache.server_name }}
+ {{ keycloak_remotecache.sasl_mechanism | default('SCRAM-SHA-512') }}
+ false
+ {{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}
+ JKS
+ {{ keycloak_remotecache.trust_store_password | default("changeme") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ auth
+
+
+ classpath:${jboss.home.dir}/providers/*
+
+
+ master
+ 900
+
+ 2592000
+ true
+ true
+ ${jboss.home.dir}/themes
+
+
+
+
+
+
+
+
+
+
+
+
+ jpa
+
+
+ basic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default
+
+
+
+
+
+
+
+ ${keycloak.jta.lookup.provider:jboss}
+
+
+
+
+
+
+
+
+
+
+ ${keycloak.x509cert.lookup.provider:default}
+
+
+
+ default
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+
+
+
+
+{% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+{% endif %}
+
+
+
+
+
diff --git a/roles/keycloak/templates/standalone-rhsso.xml.j2 b/roles/keycloak/templates/standalone-rhsso.xml.j2
new file mode 100644
index 0000000..777aa85
--- /dev/null
+++ b/roles/keycloak/templates/standalone-rhsso.xml.j2
@@ -0,0 +1,632 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ h2
+
+ sa
+ sa
+
+
+
+ jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE
+ h2
+
+ sa
+ sa
+
+
+
+
+ org.h2.jdbcx.JdbcDataSource
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ auth
+
+
+ classpath:${jboss.home.dir}/providers/*
+
+
+ master
+ 900
+
+ 2592000
+ true
+ true
+ ${jboss.home.dir}/themes
+
+
+
+
+
+
+
+
+
+
+
+
+ jpa
+
+
+ basic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default
+
+
+
+
+
+
+
+ ${keycloak.jta.lookup.provider:jboss}
+
+
+
+
+
+
+
+
+
+
+ ${keycloak.x509cert.lookup.provider:default}
+
+
+
+ default
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+
+
+
+
+{% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+{% endif %}
+
+
diff --git a/roles/keycloak/templates/standalone.xml.j2 b/roles/keycloak/templates/standalone.xml.j2
new file mode 100644
index 0000000..9e620b2
--- /dev/null
+++ b/roles/keycloak/templates/standalone.xml.j2
@@ -0,0 +1,614 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ h2
+
+ sa
+ sa
+
+
+
+ jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE
+ h2
+
+ sa
+ sa
+
+
+
+
+ org.h2.jdbcx.JdbcDataSource
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+
+
+
+
+{% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ auth
+
+ classpath:${jboss.home.dir}/providers/*
+
+ master
+ 900
+
+ 2592000
+ true
+ true
+ ${jboss.home.dir}/themes
+
+
+
+
+
+
+
+
+
+
+
+
+ jpa
+
+
+ basic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default
+
+
+
+
+
+
+
+ ${keycloak.jta.lookup.provider:jboss}
+
+
+
+
+
+
+
+
+
+
+ ${keycloak.x509cert.lookup.provider:default}
+
+
+
+ default
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% if keycloak_modcluster.enabled %}
+
+
+
+{% endif %}
+
+
diff --git a/roles/keycloak/vars/main.yml b/roles/keycloak/vars/main.yml
new file mode 100644
index 0000000..203b6d7
--- /dev/null
+++ b/roles/keycloak/vars/main.yml
@@ -0,0 +1,2 @@
+---
+# vars file for keycloak
\ No newline at end of file