Merge pull request #7 from motaparthipavankumar/stable

Local/Remote Source Support & User Federation Implementation
main
Guido Grazioli 2022-01-19 17:08:28 +01:00 committed by GitHub
commit 18e002bf27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 279 additions and 30 deletions

View File

@ -31,13 +31,32 @@ collections:
### Install Playbook ### Install Playbook
`playbooks/keycloak.yml` installs the keycloak or Red Hat Single Sign-On based on the defined variables. `playbooks/keycloak.yml` installs the upstream(Keycloak) based on the defined variables.
`playbooks/rhsso.yml` installs Red Hat Single Sign-On(RHSSO) based on defined variables.
### Choosing between Red Hat products and upstream project ### Choosing between upstream(Keycloak) project and Red Hat Single Sign-On(RHSSO)
The roles supports installing Red Hat Single Sign-On from the Customer Portal, when the following variables are defined: The roles supports installing upstream(Keycloak) or Red Hat Single Sign-On in the following ways
#### Install upstream(Keycloak) from remote source
This is default approach, there is one required variable
``` ```
keycloak_admin_password: "<changeme>"
```
#### Install upstream(Keycloak) from local source when the following variable is defined
```
keycloak_admin_password: "<changeme>"
zip_file_local_path: <keycloak zip file on Ansible control node local path>
```
#### Install RHSSO from the Red Hat Customer Support Portal, when the following variables are defined
```
keycloak_admin_password: "<changeme>"
rhn_username: '<customer_portal_username>' rhn_username: '<customer_portal_username>'
rhn_password: '<customer_portal_password>' rhn_password: '<customer_portal_password>'
rhsso_rhn_id: '<sso_product_id>' rhsso_rhn_id: '<sso_product_id>'
@ -45,6 +64,22 @@ rhsso_rhn_id: '<sso_product_id>'
where `sso_product_id` is the ID for the specific Red Hat Single Sign-On version, ie. _101971_ will install version _7.5_) where `sso_product_id` is the ID for the specific Red Hat Single Sign-On version, ie. _101971_ will install version _7.5_)
#### Install RHSSO from remote sources like Nexus etc, when the following variables are defined
```
keycloak_admin_password: "<changeme>"
keycloak_rhsso_enable: True
rhsso_source_download_url: '<url to download RHSSO zip file>'
```
#### Install RHSSO from local source when the following variable is defined
```
keycloak_admin_password: "<changeme>"
keycloak_rhsso_enable: True
zip_file_local_path: <rhsso zip file on Ansible control node local path>
```
### Install role ### Install role
* [`keycloak`](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak/README.md): role for installing the service. _Requires: python3-netaddr_ * [`keycloak`](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak/README.md): role for installing the service. _Requires: python3-netaddr_
@ -69,18 +104,18 @@ ansible-playbook -i <ansible_hosts> -e @rhn-creds.yml playbooks/keycloak.yml -e
### Config Playbook ### Config Playbook
`playbooks/keycloak-realm.yml` creates provided realm, client(s), client role(s) and client user(s) if they don't exist. `playbooks/keycloak-realm.yml` creates provided realm, user federation(s), client(s), client role(s) and client user(s) if they don't exist.
### Config role ### Config role
* [`keycloak_realm`](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak_realm/README.md): role for configuring a realm, with clients and users, in an installed service. * [`keycloak_realm`](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak_realm/README.md): role for configuring a realm, user federation(s), clients and users, in an installed service.
### Example configuration command ### Example configuration command
Execute the following command from the source root directory Execute the following command from the source root directory
``` ```
ansible-playbook -i <ansible_hosts> -e @rhn-creds.yml playbooks/keycloak.yml -e keycloak_admin_password=<changeme> -e keycloak_realm=test ansible-playbook -i <ansible_hosts> playbooks/keycloak-realm.yml -e keycloak_admin_password=<changeme> -e keycloak_realm=test
``` ```
- `keycloak_admin_password` password for the administration console user account. - `keycloak_admin_password` password for the administration console user account.

View File

@ -8,6 +8,46 @@
vars: vars:
keycloak_admin_password: "changeme" keycloak_admin_password: "changeme"
keycloak_realm: TestRealm keycloak_realm: TestRealm
keycloak_user_federation:
- realm: TestRealm
name: my-ldap
provider_id: ldap
provider_type: org.keycloak.storage.UserStorageProvider
config:
priority: '0'
enabled: true
cachePolicy: DEFAULT
batchSizeForSync: '1000'
editMode: READ_ONLY
importEnabled: true
syncRegistrations: false
vendor: other
usernameLDAPAttribute: uid
rdnLDAPAttribute: uid
uuidLDAPAttribute: entryUUID
userObjectClasses: inetOrgPerson, organizationalPerson
connectionUrl: ldaps://ldap.example.com:636
usersDn: ou=Users,dc=example,dc=com
authType: simple
bindDn: cn=directory reader
bindCredential: password
searchScope: '1'
validatePasswordPolicy: false
trustEmail: false
useTruststoreSpi: ldapsOnly
connectionPooling: true
pagination: true
allowKerberosAuthentication: false
debug: false
useKerberosForPasswordAuthentication: false
mappers:
- name: "full name"
providerId: "full-name-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
ldap.full.name.attribute: cn
read.only: true
write.only: false
keycloak_clients: keycloak_clients:
- name: TestClient1 - name: TestClient1
roles: roles:

View File

@ -2,11 +2,9 @@
- name: Playbook for Keycloak Hosts - name: Playbook for Keycloak Hosts
hosts: keycloak hosts: keycloak
collections: collections:
- middleware_automation.redhat_csp_download - middleware_automation.keycloak
roles:
- redhat_csp_download
tasks: tasks:
- name: Keycloak Role - name: Include keycloak role
include_role: include_role:
name: keycloak name: keycloak
vars: vars:

View File

@ -0,0 +1,14 @@
---
- 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
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True

View File

@ -26,6 +26,7 @@ Role Defaults
| Variable | Description | Default | | Variable | Description | Default |
|:---------|:------------|:---------| |:---------|:------------|:---------|
|`keycloak_rhsso_enable`| Enable Red Hat Single Sign-on installation | `False` |
|`keycloak_ha_enabled`| Enable auto configuration for database backend, clustering and remote caches on infinispan | `False` | |`keycloak_ha_enabled`| Enable auto configuration for database backend, clustering and remote caches on infinispan | `False` |
|`keycloak_db_enabled`| Enable auto configuration for database backend | `True` if `keycloak_ha_enabled` is True, else `False` | |`keycloak_db_enabled`| Enable auto configuration for database backend | `True` if `keycloak_ha_enabled` is True, else `False` |
|`keycloak_admin_user`| Administration console user account | `admin` | |`keycloak_admin_user`| Administration console user account | `admin` |
@ -75,20 +76,29 @@ The following variables are _required_ only when `keycloak_db_enabled` is True:
|`keycloak_db_user` | username for connecting to postgres | `keycloak-user` | |`keycloak_db_user` | username for connecting to postgres | `keycloak-user` |
|`keycloak_db_pass` | password for connecting to postgres | `keycloak-pass` | |`keycloak_db_pass` | password for connecting to postgres | `keycloak-pass` |
The following variable can be used to install Keycloak or Red Hat Single Sign-On from local path:
| Variable | Description | Example |
|:---------|:------------|:---------|
|`zip_file_local_path` | Full local path of upstream(Keycloak) or Red Hat Single Sign-On zip file on Ansible control plane | `tmp/rhsso/rh-sso-7.5-server-dist.zip` |
The following variable can be used to install Red Hat Single Sign-On from source via url, auth support is not added right now.
| Variable | Description | Example |
|:---------|:------------|:---------|
|`rhsso_source_download_url` | URL to download Red Hat Single Sign-On zip file from source | `http://localhost:8081/nexus/rhsso/rh-sso-7.5-server-dist.zip` |
Dependencies Dependencies
------------ ------------
The roles depends on: The roles depends on:
* the `redhat_csp_download` role from [middleware_automation.redhat_csp_download](https://github.com/ansible-middleware/redhat-csp-download) collection * the redhat_csp_download role from [middleware_automation.redhat_csp_download](https://github.com/ansible-middleware/redhat-csp-download) collection if Red Hat Single Sign-on zip have to be downloaded from RHN.
* the `wildfly_driver` role from [middleware_automation.wildfly](https://github.com/ansible-middleware/wildfly) collection * the wildfly_driver role from [middleware_automation.wildfly](https://github.com/ansible-middleware/wildfly) collection
Example Playbook Example Playbook
---------------- ----------------
The following is an example playbook that makes use of the role to install keycloak The following is an example playbook that makes use of the role to install keycloak from remote
```yaml ```yaml
--- ---
@ -103,6 +113,75 @@ The following is an example playbook that makes use of the role to install keycl
keycloak_admin_password: "changeme" keycloak_admin_password: "changeme"
``` ```
The following is an example playbook that makes use of the role to install keycloak from local path on Ansible node
```yaml
---
- hosts: ...
collections:
- middleware_automation.keycloak
tasks:
- name: Include keycloak role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
zip_file_local_path: "/tmp/keycloak/keycloak-16.1.0.zip" # This should be local path on Ansible node of upstream(keycloak) zip file
```
The following is an example playbook that makes use of the role to install Red Hat Single Sign-On from RHN
```yaml
---
- name: Playbook for RHSSO
hosts: keycloak
collections:
- middleware_automation.redhat_csp_download
roles:
- redhat_csp_download
tasks:
- name: Keycloak Role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
```
The following is an example playbook that makes use of the role to install Red Hat Single Sign-On from source url
```yaml
---
- hosts: keycloak
collections:
- middleware_automation.keycloak
tasks:
- name: Keycloak Role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
rhsso_source_download_url: "<REPLACE with - Source download url>" # This should be the full of remote source rhsso zip file
```
The following is an example playbook that makes use of the role to install Red Hat Single Sign-On from local path on Ansible node
```yaml
---
- hosts: keycloak
collections:
- middleware_automation.keycloak
tasks:
- name: Keycloak Role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
zip_file_local_path: "/tmp/rhsso/rh-sso-7.5-server-dist.zip" # This should be local path on Ansible node of rhsso zip file
```
License License
------- -------

View File

@ -7,7 +7,7 @@ keycloak_download_url_9x: "https://downloads.jboss.org/keycloak/{{ keycloak_vers
keycloak_installdir: "{{ keycloak_dest }}/keycloak-{{ keycloak_version }}" keycloak_installdir: "{{ keycloak_dest }}/keycloak-{{ keycloak_version }}"
### Configuration specific to Red Hat Single Sing-On ### Configuration specific to Red Hat Single Sing-On
keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined else False }}" keycloak_rhsso_enable: False
keycloak_rhsso_version: 7.5 keycloak_rhsso_version: 7.5
keycloak_rhsso_archive: "rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip" keycloak_rhsso_archive: "rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip"
keycloak_rhsso_installdir: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version }}" keycloak_rhsso_installdir: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version }}"
@ -16,7 +16,7 @@ keycloak_rhsso_base_url: 'https://access.redhat.com/jbossnetwork/restricted/soft
### Install location and service settings ### Install location and service settings
jvm_package: java-1.8.0-openjdk-devel jvm_package: java-1.8.0-openjdk-devel
keycloak_dest: /opt/keycloak keycloak_dest: /opt/keycloak
keycloak_jboss_home: "{{ keycloak_rhsso_installdir if rhsso_rhn_id is defined else keycloak_installdir }}" keycloak_jboss_home: "{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}"
keycloak_config_dir: "{{ keycloak_jboss_home }}/standalone/configuration" keycloak_config_dir: "{{ keycloak_jboss_home }}/standalone/configuration"
keycloak_config_standalone_xml: "keycloak.xml" keycloak_config_standalone_xml: "keycloak.xml"

View File

@ -2,20 +2,20 @@
- assert: - assert:
that: that:
- zipfile_dest is defined - zipfile_dest is defined
- rhn_id_file is defined - keycloak_rhsso_enable
- rhn_username is defined
- rhn_password is defined
quiet: true quiet: true
- set_fact: - set_fact:
rhn_download_url: "{{ keycloak_rhsso_base_url }}{{ rhn_id_file }}" rhn_download_url: "{{ keycloak_rhsso_base_url }}{{ rhsso_rhn_id }}"
when:
- rhsso_rhn_id is defined
- name: "Check zipfile dest directory {{ zipfile_dest }}" - name: "Check zipfile dest directory {{ zipfile_dest }}"
stat: stat:
path: "{{ zipfile_dest }}" path: "{{ zipfile_dest }}"
register: archive_path register: archive_path
- name: "Install zipfile from RHN: {{ rhn_download_url }}" - name: "Download zipfile from RHN: {{ rhn_download_url }}"
redhat_csp_download: redhat_csp_download:
url: "{{ rhn_download_url }}" url: "{{ rhn_download_url }}"
dest: "{{ zipfile_dest }}" dest: "{{ zipfile_dest }}"
@ -26,11 +26,40 @@
- archive_path is defined - archive_path is defined
- archive_path.stat is defined - archive_path.stat is defined
- not archive_path.stat.exists - not archive_path.stat.exists
- rhn_username is defined
- rhn_password is defined
- rhsso_rhn_id is defined
- name: "Copy zipfile from source like Nexus etc : {{ rhsso_source_download_url }}"
get_url:
url: "{{ rhsso_source_download_url }}"
dest: "{{ zipfile_dest }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- rhsso_source_download_url is defined
- name: "Copy zipfile from local source: {{ zip_file_local_path }}"
ansible.builtin.copy:
src: "{{ zip_file_local_path }}"
dest: "{{ zipfile_dest }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- zip_file_local_path is defined
- name: "Check zipfile dest directory {{ zipfile_dest }}" - name: "Check zipfile dest directory {{ zipfile_dest }}"
stat: stat:
path: "{{ zipfile_dest }}" path: "{{ zipfile_dest }}"
register: path_to_downloaded_artefact register: path_to_downloaded_artifact
- block: - block:
- file: - file:
@ -68,8 +97,8 @@
when: when:
- target_dir_state.stat.exists - target_dir_state.stat.exists
when: when:
- path_to_downloaded_artefact is defined - path_to_downloaded_artifact is defined
- path_to_downloaded_artefact.stat is defined - path_to_downloaded_artifact.stat is defined
- path_to_downloaded_artefact.stat.exists - path_to_downloaded_artifact.stat.exists
- target_dir is defined - target_dir is defined
- work_dir is defined - work_dir is defined

View File

@ -74,6 +74,20 @@
- archive_path is defined - archive_path is defined
- archive_path.stat is defined - archive_path.stat is defined
- not archive_path.stat.exists - not archive_path.stat.exists
- not keycloak_rhsso_enable and not zip_file_local_path is defined
- name: "Copy zipfile from local source: {{ zip_file_local_path }}"
ansible.builtin.copy:
src: "{{ zip_file_local_path }}"
dest: "{{ keycloak_dest }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- not keycloak_rhsso_enable and zip_file_local_path is defined
- name: extract Keycloak archive on target - name: extract Keycloak archive on target
unarchive: unarchive:
@ -91,9 +105,9 @@
- block: - block:
- assert: - assert:
that: that:
- rhsso_rhn_id is defined - rhsso_rhn_id is defined or zip_file_local_path is defined
quiet: true quiet: true
fail_msg: "Can't install RHSSO without RHN ID." fail_msg: "Can't install RHSSO without either RHN ID or RHSSO zip file located on Ansible node"
- name: create download directory - name: create download directory
file: file:
@ -103,9 +117,8 @@
group: "{{ keycloak_service_group }}" group: "{{ keycloak_service_group }}"
mode: 0750 mode: 0750
- include_tasks: download_from_rhn.yml - include_tasks: get_rhsso.yml
vars: vars:
rhn_id_file: "{{ rhsso_rhn_id }}"
zipfile_dest: "{{ keycloak_dest }}/{{ keycloak_rhsso_archive }}" zipfile_dest: "{{ keycloak_dest }}/{{ keycloak_rhsso_archive }}"
work_dir: "{{ keycloak_dest }}" work_dir: "{{ keycloak_dest }}"
target_dir: "{{ keycloak_jboss_home }}" target_dir: "{{ keycloak_jboss_home }}"

View File

@ -14,6 +14,8 @@ Role Defaults
|`keycloak_http_port` | HTTP port | `8080` | |`keycloak_http_port` | HTTP port | `8080` |
|`keycloak_https_port` | TLS HTTP port | `8443` | |`keycloak_https_port` | TLS HTTP port | `8443` |
|`keycloak_auth_realm` | Name of the main authentication realm | `master` | |`keycloak_auth_realm` | Name of the main authentication realm | `master` |
|`keycloak_rhsso_enable` | Define service is an upstream(Keycloak) or RHSSO | `master` |
Role Variables Role Variables
@ -35,10 +37,29 @@ The following variables are available for creating clients:
|`keycloak_client_default_roles` | List of default role name for clients | `[]` | |`keycloak_client_default_roles` | List of default role name for clients | `[]` |
|`keycloak_client_users` | List of user/role mappings for a client | `[]` | |`keycloak_client_users` | List of user/role mappings for a client | `[]` |
The following variable are available for creating user federation:
| Variable | Description | Default |
|:---------|:------------|:---------|
|`keycloak_user_federation` | List of _keycloak_user_federation_ for the realm | `[]` |
Variable formats Variable formats
---------------- ----------------
* `keycloak_user_federation`, a list of:
```yaml
- realm: <name of the realm in which user federation should be configured, required>
name: <name of the user federation provider, required>
provider_id: <Type of the user federation provider, required>
provider_type: < Provider Type, default is set to org.keycloak.storage.UserStorageProvider>
config: <Dictionary of supported configuration values, required>
mappers: <List of supported configuration values, required>
```
Refer to [docs](https://docs.ansible.com/ansible/latest/collections/community/general/keycloak_user_federation_module.html) for information on supported variables.
* `keycloak_clients`, a list of: * `keycloak_clients`, a list of:
```yaml ```yaml
@ -71,7 +92,6 @@ Variable formats
For a comprehensive example, refer to the [playbook](playbooks/keycloak.yml). For a comprehensive example, refer to the [playbook](playbooks/keycloak.yml).
Example Playbook Example Playbook
---------------- ----------------

View File

@ -9,6 +9,9 @@ keycloak_admin_user: admin
keycloak_auth_realm: master keycloak_auth_realm: master
keycloak_auth_client: admin-cli keycloak_auth_client: admin-cli
### List of Keycloak User Federation
keycloak_user_federation: []
### Keycloak realm client defaults ### Keycloak realm client defaults
# list of clients to create in the realm # list of clients to create in the realm
# #

View File

@ -34,6 +34,24 @@
status_code: 201 status_code: 201
when: keycloak_realm_exists.status == 404 when: keycloak_realm_exists.status == 404
- name: Create user federation
community.general.keycloak_user_federation:
auth_keycloak_url: "{{ keycloak_url }}/auth"
auth_realm: "{{ keycloak_auth_realm }}"
auth_username: "{{ keycloak_admin_user }}"
auth_password: "{{ keycloak_admin_password }}"
realm: "{{ item.realm }}"
name: "{{ item.name }}"
state: present
provider_id: "{{ item.provider_id }}"
provider_type: "{{ item.provider_type | default(org.keycloak.storage.UserStorageProvider) }}"
config: "{{ item.config }}"
mappers: "{{ item.mappers | default(omit) }}"
register: create_user_federation_result
loop: "{{ keycloak_user_federation | flatten }}"
when: keycloak_user_federation is defined
- name: Create Client - name: Create Client
community.general.keycloak_client: community.general.keycloak_client:
auth_client_id: "{{ keycloak_auth_client }}" auth_client_id: "{{ keycloak_auth_client }}"

View File

@ -13,4 +13,4 @@ keycloak_clients:
# other settings # other settings
keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}" keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}" keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined else False }}" keycloak_rhsso_enable: False