Compare commits

...

51 Commits
1.0.1 ... 1.0.3

Author SHA1 Message Date
github-actions
95c346d4b3 Update changelog for release 1.0.3 2022-05-09 15:51:47 +00:00
Guido Grazioli
f4674a8762 ci: release triggers with correct tag version 2022-05-09 17:34:19 +02:00
Guido Grazioli
3714145526 keycloak: fix jdbc assert 2022-05-09 17:26:20 +02:00
Guido Grazioli
4167edda63 ci: use tar creating token, allow dispatch of docs 2022-05-09 17:22:52 +02:00
Guido Grazioli
7d57857a1f ci: use github custom action 2022-05-09 16:00:00 +02:00
Guido Grazioli
8341416ee0 keycloak: default jvm to headless variant, add jdbc validation 2022-05-09 15:57:12 +02:00
Guido Grazioli
fbc0d7ab99 Merge pull request #31 from guidograzioli/ensure_java_home
Make sure systemd unit starts with selected java JVM
2022-04-28 15:05:45 +02:00
Guido Grazioli
78d5499abf fix: linter 2022-04-28 12:15:48 +02:00
Guido Grazioli
9987f6a044 update molecule test and verify for jvm 2022-04-28 11:33:40 +02:00
Guido Grazioli
e3bb10d901 fix: ensure correct jvm java_home is set 2022-04-28 11:33:23 +02:00
Guido Grazioli
7028b068b6 Merge pull request #30 from guidograzioli/custom_keycloak_template
Add `keycloak_config_override_template` parameter for passing custom xml configuration
2022-04-12 12:26:49 +02:00
Guido Grazioli
0751b97b87 Add custom xml parameter and test scenario 2022-04-12 12:07:06 +02:00
Guido Grazioli
548db6fc4b Merge pull request #29 from guidograzioli/quarkus
New role for installing keycloak >= 17.0.0 (quarkus)
2022-04-11 14:03:47 +02:00
Guido Grazioli
dc33cbc358 quarkus: add README, update parameters doc 2022-04-11 13:48:59 +02:00
Romain Pelisse
9bb9816a01 Switch playbooks hosts to all 2022-04-11 10:50:22 +02:00
Guido Grazioli
33c8f74122 add molecule test for keycloak_quarkus 2022-04-07 14:07:45 +02:00
Guido Grazioli
cf92da9e94 update keycloak_realm to test nicely with keycloak_quarkus 2022-04-07 14:07:28 +02:00
Guido Grazioli
419c862341 add role keycloak_quarkus 2022-04-07 14:07:08 +02:00
Guido Grazioli
c7b6bc1d61 ci: docs wf uses custom action 2022-04-07 08:53:43 +02:00
Guido Grazioli
a62f26648f bump version, use git describe for -devel changelogs 2022-04-04 17:35:22 +02:00
Guido Grazioli
29aaafb9e4 ci: changelogs skip unlabeled PRs 2022-04-01 21:41:52 +02:00
Guido Grazioli
9d57057272 docs: fix unbalanced quotes in release workflow 2022-04-01 13:23:10 +02:00
github-actions
fddfa9a493 Update changelog for release 1.0.2 2022-04-01 10:57:28 +00:00
Guido Grazioli
5cbe905dda docs: restructuredtext link needs separator 2022-04-01 12:53:56 +02:00
Guido Grazioli
4e6ea2f1ca ci: release wf uses deep clone 2022-04-01 12:14:09 +02:00
Guido Grazioli
28ff78d809 docs: changelog pasted into github release page 2022-04-01 10:57:42 +02:00
Guido Grazioli
9365d38162 docs: add role index to toctree 2022-03-31 16:51:25 +02:00
Guido Grazioli
d3f9b0ca86 docs: add PR link to previous releases 2022-03-31 16:12:04 +02:00
Guido Grazioli
bada6f4073 docs: add changelog breaking_change type 2022-03-31 15:54:30 +02:00
Guido Grazioli
b91c9e17fc docs: fix typo in href target generation 2022-03-31 15:40:16 +02:00
Guido Grazioli
b974bf1967 docs: absolute links in READMEs 2022-03-31 15:30:23 +02:00
Guido Grazioli
9ee6788f98 docs: workaround unstaged file when checking out gh-pages 2022-03-31 15:13:30 +02:00
Guido Grazioli
c166c643fc docs: set -devel version for main branch 2022-03-31 15:04:55 +02:00
Guido Grazioli
abd922417c Merge pull request #27 from guidograzioli/changelogs
docs: add changelogs
2022-03-31 14:58:23 +02:00
Guido Grazioli
5a45d1f4f8 add prerelease to docs wf, generate on release wf 2022-03-31 14:56:41 +02:00
Guido Grazioli
6091477294 ci: generate changelog fragments from PR messages 2022-03-30 17:49:03 +02:00
Guido Grazioli
63f31fe258 Add gitignore to ansible-test sanity excludes 2022-03-25 18:22:55 +01:00
Guido Grazioli
fc780599b0 add antsibull generated changelog 2022-03-25 11:45:11 +01:00
Guido Grazioli
494a1c518b docs: add changelogs 2022-03-25 11:17:58 +01:00
Guido Grazioli
f736ad5632 misc: switch default keycloak_rhsso_apply_patches to false 2022-03-25 10:11:22 +01:00
Guido Grazioli
b0a11013fa Merge pull request #25 from guidograzioli/keycloak_frontend_url_default
Set the frontend URL to play well with other defaults
2022-03-25 10:06:07 +01:00
Guido Grazioli
10ff1763c1 Merge pull request #26 from guidograzioli/keycloak_admin_password_var
move admin pwd param from vars to defaults and assert
2022-03-25 09:57:21 +01:00
Guido Grazioli
85b0a2549a update tests with pwd, apply change to keycloak_realm 2022-03-25 00:34:41 +01:00
Guido Grazioli
d854791183 set admin pass to valid length 2022-03-24 18:07:33 +01:00
Guido Grazioli
a67081a68d move admin pwd param from vars to defaults, add assert 2022-03-24 17:44:13 +01:00
Guido Grazioli
8173be4b58 Set the frontend URL to play well with other defaults 2022-03-24 17:00:30 +01:00
Guido Grazioli
6270762a3a trigger EE rebuild when released 2022-03-23 15:42:41 +01:00
Guido Grazioli
5828c0a7bb fix: spelling 2022-03-23 12:30:32 +01:00
Guido Grazioli
e773e12e24 use proper service name in task names 2022-03-17 10:45:55 +01:00
Guido Grazioli
33e80a0cd4 remove unused set_fact 2022-03-11 16:27:23 +01:00
Guido Grazioli
bf26c727a8 misc: simply fastpackages logic and reduce play time 2022-03-11 16:27:23 +01:00
81 changed files with 2094 additions and 206 deletions

View File

@@ -40,7 +40,7 @@ jobs:
mkdir -p /home/runner/.ansible/collections/ansible_collections
- name: Run sanity tests
run: ansible-test sanity --docker -v --color --python ${{ matrix.python_version }}
run: ansible-test sanity --docker -v --color --python ${{ matrix.python_version }} --exclude changelogs/fragments/.gitignore
working-directory: ./ansible_collections/middleware_automation/keycloak
- name: Run molecule test

View File

@@ -6,6 +6,7 @@ on:
- main
tags:
- "[0-9]+.[0-9]+.[0-9]+"
workflow_dispatch:
env:
COLORTERM: 'yes'
@@ -40,36 +41,21 @@ jobs:
python -m pip install --upgrade pip
pip install -r ansible_collections/middleware_automation/keycloak/docs/requirements.txt
pip install -r ansible_collections/middleware_automation/keycloak/requirements.txt
sudo apt install -y sed hub
- name: Create default collection path
run: |
mkdir -p /home/runner/.ansible/collections/ansible_collections
- name: Create doc directories and resources
run: |
mkdir -p ./docs/plugins ./docs/roles
cat ./docs/roles.rst.template > ./docs/roles/index.rst
antsibull-docs collection --use-current --squash-hierarchy --dest-dir docs/plugins middleware_automation.keycloak
for role_readme in roles/*/README.md; do ln -f -s ../../$role_readme ./docs/roles/$(basename $(dirname $role_readme)).md; echo " * :doc:\`$(basename $(dirname $role_readme))\`" >> ./docs/roles/index.rst; done
working-directory: ansible_collections/middleware_automation/keycloak
- name: Run sphinx
run: |
sphinx-build -M html . _build -v
working-directory: ansible_collections/middleware_automation/keycloak/docs/
- name: Commit docs
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git checkout gh-pages
rm -rf $(basename ${GITHUB_REF})
mv docs/_build/html $(basename ${GITHUB_REF})
ln --force --no-dereference --symbolic main latest
git show origin/main:docs/_gh_include/header.inc > index.html
(echo main; echo latest; dirname *.*.*/index.html | sort --version-sort --reverse) | xargs -I@@ -n1 echo '<li class="toctree-l1"><a class="reference internal" href="@@/">@@</a></li>' >> index.html
git show origin/main:docs/_gh_include/footer.inc >> index.html
git add $(basename ${GITHUB_REF}) latest index.html
git commit -m "Update docs for $(basename ${GITHUB_REF})" || true
git push origin gh-pages
working-directory: ansible_collections/middleware_automation/keycloak/
- name: Create changelog and documentation
uses: ansible-middleware/collection-docs-action@main
with:
collection_fqcn: middleware_automation.keycloak
collection_repo: ansible-middleware/keycloak
dependencies: false
commit_changelog: false
commit_ghpages: true
changelog_release: false
generate_docs: true
path: ansible_collections/middleware_automation/keycloak
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,47 +1,97 @@
---
name: Release collection
on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+"
workflow_dispatch:
jobs:
release:
runs-on: ubuntu-latest
if: github.repository == 'ansible-middleware/keycloak'
permissions:
actions: write
checks: write
contents: write
deployments: write
packages: write
pages: write
outputs:
tag_version: ${{ steps.get_version.outputs.TAG_VERSION }}
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.TRIGGERING_PAT }}
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: "3.x"
- name: Get Tag Version
- name: Get current version
id: get_version
run: echo ::set-output name=TAG_VERSION::${GITHUB_REF#refs/tags/}
run: echo "::set-output name=TAG_VERSION::$(grep version galaxy.yml | awk -F'"' '{ print $2 }')"
- name: Check if tag exists
id: check_tag
run: echo "::set-output name=TAG_EXISTS::$(git tag | grep ${{ steps.get_version.outputs.TAG_VERSION }})"
- name: Fail if tag exists
if: ${{ steps.get_version.outputs.TAG_VERSION == steps.check_tag.outputs.TAG_EXISTS }}
uses: actions/github-script@v3
with:
script: |
core.setFailed('Release tag already exists')
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ansible-core
pip install ansible-core antsibull
sudo apt install -y sed hub
- name: Build collection
run: |
ansible-galaxy collection build .
- name: Publish Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create changelog and documentation
uses: ansible-middleware/collection-docs-action@main
with:
files: "*.tar.gz"
body: "Release v${{ steps.get_version.outputs.TAG_VERSION }}"
collection_fqcn: middleware_automation.keycloak
collection_repo: ansible-middleware/keycloak
dependencies: false
commit_changelog: true
commit_ghpages: false
changelog_release: true
generate_docs: false
token: ${{ secrets.GITHUB_TOKEN }}
- name: Publish collection
env:
ANSIBLE_GALAXY_API_KEY: ${{ secrets.ANSIBLE_GALAXY_API_KEY }}
run: |
ansible-galaxy collection publish *.tar.gz --api-key $ANSIBLE_GALAXY_API_KEY
- name: Create release tag
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git tag -a ${{ steps.get_version.outputs.TAG_VERSION }} -m "Release v${{ steps.get_version.outputs.TAG_VERSION }}" || true
git push origin --tags
- name: Publish Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.get_version.outputs.TAG_VERSION }}
files: "*.tar.gz"
body_path: gh-release.md
dispatch:
needs: release
strategy:
matrix:
repo: ['ansible-middleware/cross-dc-rhsso-demo', 'ansible-middleware/flange-demo']
repo: ['ansible-middleware/cross-dc-rhsso-demo', 'ansible-middleware/flange-demo', 'ansible-middleware/ansible-middleware-ee']
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
@@ -49,5 +99,5 @@ jobs:
with:
token: ${{ secrets.TRIGGERING_PAT }}
repository: ${{ matrix.repo }}
event-type: "Dependency released - Keycloak"
event-type: "Dependency released - Keycloak v${{ needs.release.outputs.tag_version }}"
client-payload: '{ "github": ${{toJson(github)}} }'

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@ docs/_build/
.pytest_cache/
.mypy_cache/
*.retry
changelogs/.plugin-cache.yaml

67
CHANGELOG.rst Normal file
View File

@@ -0,0 +1,67 @@
============================================
middleware_automation.keycloak Release Notes
============================================
.. contents:: Topics
This changelog describes changes after version 0.2.6.
v1.0.3
======
Major Changes
-------------
- New role for installing keycloak >= 17.0.0 (quarkus) `#29 <https://github.com/ansible-middleware/keycloak/pull/29>`_
Minor Changes
-------------
- Add ``keycloak_config_override_template`` parameter for passing a custom xml config template `#30 <https://github.com/ansible-middleware/keycloak/pull/30>`_
Bugfixes
--------
- Make sure systemd unit starts with selected java JVM `#31 <https://github.com/ansible-middleware/keycloak/pull/31>`_
v1.0.2
======
Minor Changes
-------------
- Make ``keycloak_admin_password`` a default with assert (was: role variable) `#26 <https://github.com/ansible-middleware/keycloak/pull/26>`_
- Simplify dependency install logic and reduce play execution time `#19 <https://github.com/ansible-middleware/keycloak/pull/19>`_
Bugfixes
--------
- Set ``keycloak_frontend_url`` default according to other defaults `#25 <https://github.com/ansible-middleware/keycloak/pull/25>`_
v1.0.1
======
Release Summary
---------------
Minor enhancements, bug and documentation fixes.
Major Changes
-------------
- Apply latest cumulative patch of RH-SSO automatically when new parameter ``keycloak_rhsso_apply_patches`` is ``true`` `#18 <https://github.com/ansible-middleware/keycloak/pull/18>`_
Minor Changes
-------------
- Clustered installs now perform database initialization on first node to avoid locking issues `#17 <https://github.com/ansible-middleware/keycloak/pull/17>`_
v1.0.0
======
Release Summary
---------------
This is the first stable release of the ``middleware_automation.keycloak`` collection.

View File

@@ -43,6 +43,7 @@ A requirement file is provided to install:
* [`keycloak`](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak/README.md): role for installing the 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.
* [`keycloak_quarkus`](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak_quarkus/README.md): role for installing the quarkus variant of keycloak (>= 17.0.0).
## Usage
@@ -50,12 +51,12 @@ A requirement file is provided to install:
### Install Playbook
* [`playbooks/keycloak.yml`](playbooks/keycloak.yml) installs the upstream(Keycloak) based on the defined variables.
* [`playbooks/rhsso.yml`](playbooks/rhsso.yml) installs Red Hat Single Sign-On(RHSSO) based on defined variables.
* [`playbooks/keycloak.yml`](https://github.com/ansible-middleware/keycloak/blob/main/playbooks/keycloak.yml) installs the upstream(Keycloak) based on the defined variables.
* [`playbooks/rhsso.yml`](https://github.com/ansible-middleware/keycloak/blob/main/playbooks/rhsso.yml) installs Red Hat Single Sign-On(RHSSO) based on defined variables.
Both playbooks include the `keycloak` role, with different settings, as described in the following sections.
For full service configuration details, refer to the [keycloak role README](roles/keycloak/README.md).
For full service configuration details, refer to the [keycloak role README](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak/README.md).
### Choosing between upstream project (Keycloak) and Red Hat Single Sign-On (RHSSO)
@@ -134,7 +135,7 @@ ansible-playbook -i <ansible_hosts> -e @rhn-creds.yml playbooks/keycloak.yml -e
### Config Playbook
[`playbooks/keycloak_realm.yml`](playbooks/keycloak_realm.yml) creates or updates provided realm, user federation(s), client(s), client role(s) and client user(s).
[`playbooks/keycloak_realm.yml`](https://github.com/ansible-middleware/keycloak/blob/main/playbooks/keycloak_realm.yml) creates or updates provided realm, user federation(s), client(s), client role(s) and client user(s).
### Example configuration command
@@ -154,7 +155,7 @@ ansible-playbook -i <ansible_hosts> playbooks/keycloak_realm.yml -e keycloak_adm
localhost ansible_connection=local
```
For full configuration details, refer to the [keycloak_realm role README](roles/keycloak_realm/README.md).
For full configuration details, refer to the [keycloak_realm role README](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak_realm/README.md).
## Support

60
changelogs/changelog.yaml Normal file
View File

@@ -0,0 +1,60 @@
ancestor: 0.2.6
releases:
1.0.0:
changes:
release_summary: 'This is the first stable release of the ``middleware_automation.keycloak``
collection.
'
release_date: '2022-03-04'
1.0.1:
changes:
major_changes:
- Apply latest cumulative patch of RH-SSO automatically when new parameter ``keycloak_rhsso_apply_patches``
is ``true`` `#18 <https://github.com/ansible-middleware/keycloak/pull/18>`_
minor_changes:
- Clustered installs now perform database initialization on first node to avoid
locking issues `#17 <https://github.com/ansible-middleware/keycloak/pull/17>`_
release_summary: 'Minor enhancements, bug and documentation fixes.
'
release_date: '2022-03-11'
1.0.2:
changes:
bugfixes:
- 'Set ``keycloak_frontend_url`` default according to other defaults `#25 <https://github.com/ansible-middleware/keycloak/pull/25>`_
'
minor_changes:
- 'Make ``keycloak_admin_password`` a default with assert (was: role variable)
`#26 <https://github.com/ansible-middleware/keycloak/pull/26>`_
'
- 'Simplify dependency install logic and reduce play execution time `#19 <https://github.com/ansible-middleware/keycloak/pull/19>`_
'
fragments:
- 19.yaml
- 25.yaml
- 26.yaml
release_date: '2022-04-01'
1.0.3:
changes:
bugfixes:
- 'Make sure systemd unit starts with selected java JVM `#31 <https://github.com/ansible-middleware/keycloak/pull/31>`_
'
major_changes:
- 'New role for installing keycloak >= 17.0.0 (quarkus) `#29 <https://github.com/ansible-middleware/keycloak/pull/29>`_
'
minor_changes:
- 'Add ``keycloak_config_override_template`` parameter for passing a custom
xml config template `#30 <https://github.com/ansible-middleware/keycloak/pull/30>`_
'
fragments:
- 29.yaml
- 30.yaml
- 31.yaml
release_date: '2022-05-09'

32
changelogs/config.yaml Normal file
View File

@@ -0,0 +1,32 @@
---
changelog_filename_template: ../CHANGELOG.rst
changelog_filename_version_depth: 0
changes_file: changelog.yaml
changes_format: combined
ignore_other_fragment_extensions: true
keep_fragments: false
mention_ancestor: true
new_plugins_after_name: removed_features
notesdir: fragments
prelude_section_name: release_summary
prelude_section_title: Release Summary
sections:
- - major_changes
- Major Changes
- - minor_changes
- Minor Changes
- - breaking_changes
- Breaking Changes / Porting Guide
- - deprecated_features
- Deprecated Features
- - removed_features
- Removed Features
- - security_fixes
- Security Fixes
- - bugfixes
- Bugfixes
- - known_issues
- Known Issues
title: middleware_automation.keycloak
trivial_section_name: trivial
use_fqcn: true

2
changelogs/fragments/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

1
docs/CHANGELOG.rst Symbolic link
View File

@@ -0,0 +1 @@
../CHANGELOG.rst

View File

@@ -15,8 +15,8 @@ Welcome to Keycloak Collection documentation
:maxdepth: 2
:caption: Developer documentation
developing
testing
developing
releasing
.. toctree::

View File

@@ -1,3 +1,4 @@
Role Index
==========
.. toctree::

View File

@@ -1,7 +1,7 @@
---
namespace: middleware_automation
name: keycloak
version: "1.0.1"
version: "1.0.3"
readme: README.md
authors:
- Romain Pelisse <rpelisse@redhat.com>
@@ -22,12 +22,13 @@ tags:
- authentication
dependencies:
"middleware_automation.redhat_csp_download": ">=1.2.1"
"middleware_automation.wildfly": ">=0.0.6"
"middleware_automation.wildfly": ">=1.0.0"
repository: https://github.com/ansible-middleware/keycloak
documentation: https://ansible-middleware.github.io/keycloak
homepage: https://github.com/ansible-middleware/keycloak
issues: https://github.com/ansible-middleware/keycloak/issues
build_ignore:
- molecule
- docs
- .github
- '*.tar.gz'
- '*.zip'

View File

@@ -2,17 +2,15 @@
- name: Converge
hosts: all
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_jvm_package: java-11-openjdk-headless
roles:
- role: keycloak
tasks:
- name: Include keycloak role
include_role:
name: ../../roles/keycloak
vars:
keycloak_admin_password: "changeme"
- name: Keycloak Realm Role
include_role:
name: ../../roles/keycloak_realm
ansible.builtin.include_role:
name: keycloak_realm
vars:
keycloak_admin_password: "changeme"
keycloak_client_default_roles:
- TestRoleAdmin
- TestRoleUser

View File

@@ -8,5 +8,7 @@
- name: Install sudo
ansible.builtin.yum:
name: sudo
name:
- sudo
- java-1.8.0-openjdk
state: present

1
molecule/default/roles Symbolic link
View File

@@ -0,0 +1 @@
../../roles

View File

@@ -1,6 +1,11 @@
---
- name: Verify
hosts: all
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_jvm_package: java-11-openjdk-headless
keycloak_port: http://localhost:8080
keycloak_management_port: http://localhost:9990
tasks:
- name: Populate service facts
ansible.builtin.service_facts:
@@ -8,3 +13,17 @@
ansible.builtin.assert:
that:
- ansible_facts.services["keycloak.service"]["state"] == "running"
- ansible_facts.services["keycloak.service"]["status"] == "enabled"
- name: Verify we are running on requested jvm
shell: |
ps -ef | grep /usr/lib/jvm/java-11 | grep -v grep
- name: Verify token api call
ansible.builtin.uri:
url: "{{ keycloak_port }}/auth/realms/master/protocol/openid-connect/token"
method: POST
body: "client_id=admin-cli&username=admin&password={{ keycloak_admin_password }}&grant_type=password"
validate_certs: no
register: keycloak_auth_response
until: keycloak_auth_response.status == 200
retries: 2
delay: 2

View File

@@ -0,0 +1,43 @@
---
- name: Converge
hosts: all
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_config_override_template: custom.xml.j2
keycloak_http_port: 8081
keycloak_management_http_port: 19990
roles:
- role: keycloak
tasks:
- name: Keycloak Realm Role
ansible.builtin.include_role:
name: keycloak_realm
vars:
keycloak_client_default_roles:
- TestRoleAdmin
- TestRoleUser
keycloak_client_users:
- username: TestUser
password: password
client_roles:
- client: TestClient
role: TestRoleUser
realm: "{{ keycloak_realm }}"
- username: TestAdmin
password: password
client_roles:
- client: TestClient
role: TestRoleUser
realm: "{{ keycloak_realm }}"
- client: TestClient
role: TestRoleAdmin
realm: "{{ keycloak_realm }}"
keycloak_realm: TestRealm
keycloak_clients:
- name: TestClient
roles: "{{ keycloak_client_default_roles }}"
realm: "{{ keycloak_realm }}"
public_client: "{{ keycloak_client_public }}"
web_origins: "{{ keycloak_client_web_origins }}"
users: "{{ keycloak_client_users }}"
client_id: TestClient

View File

@@ -0,0 +1,53 @@
---
dependency:
name: shell
command: ansible-galaxy collection install -r molecule/default/requirements.yml -p $HOME/.ansible/collections --force-with-deps
driver:
name: docker
lint: |
ansible-lint --version
ansible-lint -v
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"
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

View File

@@ -0,0 +1,12 @@
---
- name: Prepare
hosts: all
tasks:
- name: Disable beta repos
ansible.builtin.command: yum config-manager --disable '*beta*'
ignore_errors: yes
- name: Install sudo
ansible.builtin.yum:
name: sudo
state: present

View File

@@ -0,0 +1,10 @@
---
collections:
- name: middleware_automation.redhat_csp_download
version: ">=1.2.1"
- name: middleware_automation.wildfly
version: ">=0.0.5"
- name: community.general
- name: community.docker
version: ">=1.9.1"

1
molecule/overridexml/roles Symbolic link
View File

@@ -0,0 +1 @@
../../roles

View File

@@ -0,0 +1,604 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- {{ ansible_managed }} -->
<server xmlns="urn:jboss:domain:16.0">
<extensions>
<extension module="org.jboss.as.clustering.infinispan"/>
<extension module="org.jboss.as.connector"/>
<extension module="org.jboss.as.deployment-scanner"/>
<extension module="org.jboss.as.ee"/>
<extension module="org.jboss.as.ejb3"/>
<extension module="org.jboss.as.jaxrs"/>
<extension module="org.jboss.as.jmx"/>
<extension module="org.jboss.as.jpa"/>
<extension module="org.jboss.as.logging"/>
<extension module="org.jboss.as.mail"/>
<extension module="org.jboss.as.modcluster"/>
<extension module="org.jboss.as.naming"/>
<extension module="org.jboss.as.remoting"/>
<extension module="org.jboss.as.security"/>
<extension module="org.jboss.as.transactions"/>
<extension module="org.jboss.as.weld"/>
<extension module="org.keycloak.keycloak-server-subsystem"/>
<extension module="org.wildfly.extension.bean-validation"/>
<extension module="org.wildfly.extension.core-management"/>
<extension module="org.wildfly.extension.elytron"/>
<extension module="org.wildfly.extension.health"/>
<extension module="org.wildfly.extension.io"/>
<extension module="org.wildfly.extension.metrics"/>
<extension module="org.wildfly.extension.request-controller"/>
<extension module="org.wildfly.extension.security.manager"/>
<extension module="org.wildfly.extension.undertow"/>
</extensions>
<management>
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<local default-user="$local" skip-group-loading="true"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization map-groups-to-roles="false">
<properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
<security-realm name="ApplicationRealm">
<server-identities>
<ssl>
<keystore path="application.keystore" relative-to="jboss.server.config.dir" keystore-password="password" alias="server" key-password="password" generate-self-signed-certificate-host="localhost"/>
</ssl>
</server-identities>
<authentication>
<local default-user="$local" allowed-users="*" skip-group-loading="true"/>
<properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization>
<properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
</security-realms>
<audit-log>
<formatters>
<json-formatter name="json-formatter"/>
</formatters>
<handlers>
<file-handler name="file" formatter="json-formatter" path="audit-log.log" relative-to="jboss.server.data.dir"/>
</handlers>
<logger log-boot="true" log-read-only="false" enabled="false">
<handlers>
<handler name="file"/>
</handlers>
</logger>
</audit-log>
<management-interfaces>
<http-interface security-realm="ManagementRealm">
<http-upgrade enabled="true"/>
<socket-binding http="management-http"/>
</http-interface>
</management-interfaces>
<access-control provider="simple">
<role-mapping>
<role name="SuperUser">
<include>
<user name="$local"/>
</include>
</role>
</role-mapping>
</access-control>
</management>
<profile>
<subsystem xmlns="urn:jboss:domain:logging:8.0">
<console-handler name="CONSOLE">
<level name="INFO"/>
<formatter>
<named-formatter name="COLOR-PATTERN"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<named-formatter name="PATTERN"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
<logger category="io.jaegertracing.Configuration">
<level name="WARN"/>
</logger>
<logger category="org.jboss.as.config">
<level name="DEBUG"/>
</logger>
<logger category="sun.rmi">
<level name="WARN"/>
</logger>
<root-logger>
<level name="INFO"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
<formatter name="PATTERN">
<pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
<formatter name="COLOR-PATTERN">
<pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
</subsystem>
<subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
<subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
<subsystem xmlns="urn:jboss:domain:datasources:6.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
<subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:ee:6.0">
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<concurrent>
<context-services>
<context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/>
</context-services>
<managed-thread-factories>
<managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
</managed-thread-factories>
<managed-executor-services>
<managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-termination-period="0" hung-task-threshold="60000" keepalive-time="5000"/>
</managed-executor-services>
<managed-scheduled-executor-services>
<managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-termination-period="0" hung-task-threshold="60000" keepalive-time="3000"/>
</managed-scheduled-executor-services>
</concurrent>
<default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/KeycloakDS" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:ejb3:9.0">
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
<stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>
<singleton default-access-timeout="5000"/>
</session-bean>
<pools>
<bean-instance-pools>
<strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
<strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
<caches>
<cache name="simple"/>
<cache name="distributable" passivation-store-ref="infinispan" aliases="passivating clustered"/>
</caches>
<passivation-stores>
<passivation-store name="infinispan" cache-container="ejb" max-size="10000"/>
</passivation-stores>
<async thread-pool-name="default"/>
<timer-service thread-pool-name="default" default-data-store="default-file-store">
<data-stores>
<file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
</data-stores>
</timer-service>
<remote cluster="ejb" connectors="http-remoting-connector" thread-pool-name="default">
<channel-creation-options>
<option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
</channel-creation-options>
</remote>
<thread-pools>
<thread-pool name="default">
<max-threads count="10"/>
<keepalive-time time="60" unit="seconds"/>
</thread-pool>
</thread-pools>
<default-security-domain value="other"/>
<default-missing-method-permissions-deny-access value="true"/>
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/>
</subsystem>
<subsystem xmlns="urn:wildfly:elytron:13.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
<providers>
<aggregate-providers name="combined-providers">
<providers name="elytron"/>
<providers name="openssl"/>
</aggregate-providers>
<provider-loader name="elytron" module="org.wildfly.security.elytron"/>
<provider-loader name="openssl" module="org.wildfly.openssl"/>
</providers>
<audit-logging>
<file-audit-log name="local-audit" path="audit.log" relative-to="jboss.server.log.dir" format="JSON"/>
</audit-logging>
<security-domains>
<security-domain name="ApplicationDomain" default-realm="ApplicationRealm" permission-mapper="default-permission-mapper">
<realm name="ApplicationRealm" role-decoder="groups-to-roles"/>
<realm name="local"/>
</security-domain>
<security-domain name="ManagementDomain" default-realm="ManagementRealm" permission-mapper="default-permission-mapper">
<realm name="ManagementRealm" role-decoder="groups-to-roles"/>
<realm name="local" role-mapper="super-user-mapper"/>
</security-domain>
</security-domains>
<security-realms>
<identity-realm name="local" identity="$local"/>
<properties-realm name="ApplicationRealm">
<users-properties path="application-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ApplicationRealm"/>
<groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
<properties-realm name="ManagementRealm">
<users-properties path="mgmt-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ManagementRealm"/>
<groups-properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
</security-realms>
<mappers>
<simple-permission-mapper name="default-permission-mapper" mapping-mode="first">
<permission-mapping>
<principal name="anonymous"/>
<permission-set name="default-permissions"/>
</permission-mapping>
<permission-mapping match-all="true">
<permission-set name="login-permission"/>
<permission-set name="default-permissions"/>
</permission-mapping>
</simple-permission-mapper>
<constant-realm-mapper name="local" realm-name="local"/>
<simple-role-decoder name="groups-to-roles" attribute="groups"/>
<constant-role-mapper name="super-user-mapper">
<role name="SuperUser"/>
</constant-role-mapper>
</mappers>
<permission-sets>
<permission-set name="login-permission">
<permission class-name="org.wildfly.security.auth.permission.LoginPermission"/>
</permission-set>
<permission-set name="default-permissions">
<permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/>
<permission class-name="org.wildfly.transaction.client.RemoteTransactionPermission" module="org.wildfly.transaction.client"/>
<permission class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
<permission class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
</permission-set>
</permission-sets>
<http>
<http-authentication-factory name="management-http-authentication" security-domain="ManagementDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="DIGEST">
<mechanism-realm realm-name="ManagementRealm"/>
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<provider-http-server-mechanism-factory name="global"/>
</http>
<sasl>
<sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
<mechanism-configuration>
<mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
<mechanism mechanism-name="DIGEST-MD5">
<mechanism-realm realm-name="ApplicationRealm"/>
</mechanism>
</mechanism-configuration>
</sasl-authentication-factory>
<sasl-authentication-factory name="management-sasl-authentication" sasl-server-factory="configured" security-domain="ManagementDomain">
<mechanism-configuration>
<mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
<mechanism mechanism-name="DIGEST-MD5">
<mechanism-realm realm-name="ManagementRealm"/>
</mechanism>
</mechanism-configuration>
</sasl-authentication-factory>
<configurable-sasl-server-factory name="configured" sasl-server-factory="elytron">
<properties>
<property name="wildfly.sasl.local-user.default-user" value="$local"/>
</properties>
</configurable-sasl-server-factory>
<mechanism-provider-filtering-sasl-server-factory name="elytron" sasl-server-factory="global">
<filters>
<filter provider-name="WildFlyElytron"/>
</filters>
</mechanism-provider-filtering-sasl-server-factory>
<provider-sasl-server-factory name="global"/>
</sasl>
<tls>
<key-stores>
<key-store name="applicationKS">
<credential-reference clear-text="password"/>
<implementation type="JKS"/>
<file path="application.keystore" relative-to="jboss.server.config.dir"/>
</key-store>
</key-stores>
<key-managers>
<key-manager name="applicationKM" key-store="applicationKS" generate-self-signed-certificate-host="localhost">
<credential-reference clear-text="password"/>
</key-manager>
</key-managers>
<server-ssl-contexts>
<server-ssl-context name="applicationSSC" key-manager="applicationKM"/>
</server-ssl-contexts>
</tls>
</subsystem>
<subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/>
<subsystem xmlns="urn:jboss:domain:infinispan:12.0">
<cache-container name="ejb" default-cache="passivation" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan">
<local-cache name="passivation">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
<file-store passivation="true" purge="false"/>
</local-cache>
</cache-container>
<cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan">
<local-cache name="realms">
<heap-memory size="10000"/>
</local-cache>
<local-cache name="users">
<heap-memory size="10000"/>
</local-cache>
<local-cache name="sessions"/>
<local-cache name="authenticationSessions"/>
<local-cache name="offlineSessions"/>
<local-cache name="clientSessions"/>
<local-cache name="offlineClientSessions"/>
<local-cache name="loginFailures"/>
<local-cache name="work"/>
<local-cache name="authorization">
<heap-memory size="10000"/>
</local-cache>
<local-cache name="keys">
<heap-memory size="1000"/>
<expiration max-idle="3600000"/>
</local-cache>
<local-cache name="actionTokens">
<heap-memory size="-1"/>
<expiration interval="300000" max-idle="-1"/>
</local-cache>
</cache-container>
<cache-container name="server" default-cache="default" modules="org.wildfly.clustering.server">
<local-cache name="default">
<transaction mode="BATCH"/>
</local-cache>
</cache-container>
<cache-container name="web" default-cache="passivation" modules="org.wildfly.clustering.web.infinispan">
<local-cache name="passivation">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
<file-store passivation="true" purge="false"/>
</local-cache>
<local-cache name="sso">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
</local-cache>
<local-cache name="routing"/>
</cache-container>
<cache-container name="hibernate" modules="org.infinispan.hibernate-cache">
<local-cache name="entity">
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps"/>
</cache-container>
</subsystem>
<subsystem xmlns="urn:jboss:domain:io:3.0">
<worker name="default"/>
<buffer-pool name="default"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jaxrs:2.0"/>
<subsystem xmlns="urn:jboss:domain:jca:5.0">
<archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
<bean-validation enabled="true"/>
<default-workmanager>
<short-running-threads>
<core-threads count="50"/>
<queue-length count="50"/>
<max-threads count="50"/>
<keepalive-time time="10" unit="seconds"/>
</short-running-threads>
<long-running-threads>
<core-threads count="50"/>
<queue-length count="50"/>
<max-threads count="50"/>
<keepalive-time time="10" unit="seconds"/>
</long-running-threads>
</default-workmanager>
<cached-connection-manager/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jmx:1.3">
<expose-resolved-model/>
<expose-expression-model/>
<remoting-connector/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jpa:1.1">
<jpa default-extended-persistence-inheritance="DEEP"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
<web-context>auth</web-context>
<providers>
<provider>
classpath:${jboss.home.dir}/providers/*
</provider>
</providers>
<master-realm-name>master</master-realm-name>
<scheduled-task-interval>900</scheduled-task-interval>
<theme>
<staticMaxAge>2592000</staticMaxAge>
<cacheThemes>true</cacheThemes>
<cacheTemplates>true</cacheTemplates>
<dir>${jboss.home.dir}/themes</dir>
</theme>
<spi name="eventsStore">
<provider name="jpa" enabled="true">
<properties>
<property name="exclude-events" value="[&quot;REFRESH_TOKEN&quot;]"/>
</properties>
</provider>
</spi>
<spi name="userCache">
<provider name="default" enabled="true"/>
</spi>
<spi name="userSessionPersister">
<default-provider>jpa</default-provider>
</spi>
<spi name="timer">
<default-provider>basic</default-provider>
</spi>
<spi name="connectionsHttpClient">
<provider name="default" enabled="true"/>
</spi>
<spi name="connectionsJpa">
<provider name="default" enabled="true">
<properties>
<property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
<property name="initializeEmpty" value="true"/>
<property name="migrationStrategy" value="update"/>
<property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
</properties>
</provider>
</spi>
<spi name="realmCache">
<provider name="default" enabled="true"/>
</spi>
<spi name="connectionsInfinispan">
<default-provider>default</default-provider>
<provider name="default" enabled="true">
<properties>
<property name="cacheContainer" value="java:jboss/infinispan/container/keycloak"/>
</properties>
</provider>
</spi>
<spi name="jta-lookup">
<default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>
<provider name="jboss" enabled="true"/>
</spi>
<spi name="publicKeyStorage">
<provider name="infinispan" enabled="true">
<properties>
<property name="minTimeBetweenRequests" value="10"/>
</properties>
</provider>
</spi>
<spi name="x509cert-lookup">
<default-provider>${keycloak.x509cert.lookup.provider:default}</default-provider>
<provider name="default" enabled="true"/>
</spi>
<spi name="hostname">
<default-provider>default</default-provider>
<provider name="default" enabled="true">
<properties>
<property name="frontendUrl" value="{{ keycloak_modcluster.frontend_url }}"/>
<property name="forceBackendUrlToFrontendUrl" value="true"/>
</properties>
</provider>
</spi>
</subsystem>
<subsystem xmlns="urn:jboss:domain:mail:4.0">
<mail-session name="default" jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
</subsystem>
<subsystem xmlns="urn:wildfly:metrics:1.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:jboss}"/>
<subsystem xmlns="urn:jboss:domain:naming:2.0">
<remote-naming/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:remoting:4.0">
<http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
<subsystem xmlns="urn:jboss:domain:security:2.0">
<security-domains>
<security-domain name="other" cache-type="default">
<authentication>
<login-module code="Remoting" flag="optional">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="RealmDirect" flag="required">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
</authentication>
</security-domain>
<security-domain name="jboss-web-policy" cache-type="default">
<authorization>
<policy-module code="Delegating" flag="required"/>
</authorization>
</security-domain>
<security-domain name="jaspitest" cache-type="default">
<authentication-jaspi>
<login-module-stack name="dummy">
<login-module code="Dummy" flag="optional"/>
</login-module-stack>
<auth-module code="Dummy"/>
</authentication-jaspi>
</security-domain>
<security-domain name="jboss-ejb-policy" cache-type="default">
<authorization>
<policy-module code="Delegating" flag="required"/>
</authorization>
</security-domain>
</security-domains>
</subsystem>
<subsystem xmlns="urn:jboss:domain:security-manager:1.0">
<deployment-permissions>
<maximum-set>
<permission class="java.security.AllPermission"/>
</maximum-set>
</deployment-permissions>
</subsystem>
<subsystem xmlns="urn:jboss:domain:transactions:6.0">
<core-environment node-identifier="${jboss.tx.node.id:1}">
<process-id>
<uuid/>
</process-id>
</core-environment>
<recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
<coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:undertow:12.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<http-invoker security-realm="ApplicationRealm"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
</subsystem>
<subsystem xmlns="urn:jboss:domain:weld:4.0"/>
</profile>
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="http" port="8081"/>
<socket-binding name="management-http" interface="management" port="19990"/>
<socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="mail-smtp">
<remote-destination host="${jboss.mail.server.host:localhost}" port="${jboss.mail.server.port:25}"/>
</outbound-socket-binding>
</socket-binding-group>
</server>

View File

@@ -0,0 +1,11 @@
---
- name: Verify
hosts: all
tasks:
- name: Populate service facts
ansible.builtin.service_facts:
- name: Check if keycloak service started
ansible.builtin.assert:
that:
- ansible_facts.services["keycloak.service"]["state"] == "running"
- ansible_facts.services["keycloak.service"]["status"] == "enabled"

View File

@@ -0,0 +1,39 @@
---
- name: Converge
hosts: all
vars:
keycloak_quarkus_admin_pass: "remembertochangeme"
keycloak_admin_password: "remembertochangeme"
keycloak_realm: TestRealm
roles:
- role: keycloak_quarkus
- role: keycloak_realm
keycloak_context: ''
keycloak_client_default_roles:
- TestRoleAdmin
- TestRoleUser
keycloak_client_users:
- username: TestUser
password: password
client_roles:
- client: TestClient
role: TestRoleUser
realm: "{{ keycloak_realm }}"
- username: TestAdmin
password: password
client_roles:
- client: TestClient
role: TestRoleUser
realm: "{{ keycloak_realm }}"
- client: TestClient
role: TestRoleAdmin
realm: "{{ keycloak_realm }}"
keycloak_realm: TestRealm
keycloak_clients:
- name: TestClient
roles: "{{ keycloak_client_default_roles }}"
realm: "{{ keycloak_realm }}"
public_client: "{{ keycloak_client_public }}"
web_origins: "{{ keycloak_client_web_origins }}"
users: "{{ keycloak_client_users }}"
client_id: TestClient

View File

@@ -0,0 +1,53 @@
---
dependency:
name: shell
command: ansible-galaxy collection install -r molecule/default/requirements.yml -p $HOME/.ansible/collections --force-with-deps
driver:
name: docker
lint: |
ansible-lint --version
ansible-lint -v
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"
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

View File

@@ -0,0 +1,12 @@
---
- name: Prepare
hosts: all
tasks:
- name: Disable beta repos
ansible.builtin.command: yum config-manager --disable '*beta*'
ignore_errors: yes
- name: Install sudo
ansible.builtin.yum:
name: sudo
state: present

View File

@@ -0,0 +1,10 @@
---
collections:
- name: middleware_automation.redhat_csp_download
version: ">=1.2.1"
- name: middleware_automation.wildfly
version: ">=0.0.5"
- name: community.general
- name: community.docker
version: ">=1.9.1"

1
molecule/quarkus/roles Symbolic link
View File

@@ -0,0 +1 @@
../../roles

View File

@@ -0,0 +1,11 @@
---
- name: Verify
hosts: all
tasks:
- name: Populate service facts
ansible.builtin.service_facts:
- name: Check if keycloak service started
ansible.builtin.assert:
that:
- ansible_facts.services["keycloak.service"]["state"] == "running"
- ansible_facts.services["keycloak.service"]["status"] == "enabled"

View File

@@ -1,11 +1,9 @@
---
- name: Playbook for Keycloak Hosts
hosts: keycloak
hosts: all
vars:
keycloak_admin_password: "remembertochangeme"
collections:
- middleware_automation.keycloak
tasks:
- name: Include keycloak role
ansible.builtin.include_role:
name: middleware_automation.keycloak.keycloak
vars:
keycloak_admin_password: "changeme"
roles:
- keycloak

View File

@@ -1,12 +1,12 @@
---
- name: Playbook for Keycloak Hosts
hosts: keycloak
hosts: all
tasks:
- name: Keycloak Realm Role
ansible.builtin.include_role:
name: middleware_automation.keycloak.keycloak_realm
vars:
keycloak_admin_password: "changeme"
keycloak_admin_password: "remembertochangeme"
keycloak_realm: TestRealm
keycloak_user_federation:
- realm: TestRealm

View File

@@ -1,14 +1,12 @@
---
- name: Playbook for Keycloak Hosts
hosts: keycloak
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_rhsso_enable: True
collections:
- middleware_automation.redhat_csp_download
- middleware_automation.keycloak
roles:
- middleware_automation.redhat_csp_download.redhat_csp_download
tasks:
- name: Keycloak Role
ansible.builtin.include_role:
name: middleware_automation.keycloak.keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
- middleware_automation.keycloak.keycloak

View File

@@ -1,7 +1,7 @@
keycloak
========
Install [keycloak](https://keycloak.org/) or [Red Hat Single Sing-On](https://access.redhat.com/products/red-hat-single-sign-on) server configurations.
Install [keycloak](https://keycloak.org/) or [Red Hat Single Sign-On](https://access.redhat.com/products/red-hat-single-sign-on) server configurations.
Requirements
@@ -34,7 +34,7 @@ Versions
Patching
--------
When variable `keycloak_rhsso_apply_patches` is `True` (default: `True`), the role will automatically apply the latest cumulative patch for the selected base version.
When variable `keycloak_rhsso_apply_patches` is `True` (default: `False`), the role will automatically apply the latest cumulative patch for the selected base version.
| RH-SSO VERSION | Release Date | RH-SSO LATEST CP | Notes |
|:---------------|:------------------|:-----------------|:----------------|
@@ -60,13 +60,14 @@ Role Defaults
|`keycloak_jgroups_port`| jgroups cluster tcp port | `7600` |
|`keycloak_management_http_port`| Management port | `9990` |
|`keycloak_management_https_port`| TLS management port | `9993` |
|`keycloak_java_opts`| Additional JVM options | `-Xms1024m -Xmx2048m` |
|`keycloak_prefer_ipv4`| Prefer IPv4 stack and addresses for port binding | `True` |
|`keycloak_config_standalone_xml`| filename for configuration | `keycloak.xml` |
|`keycloak_service_user`| posix account username | `keycloak` |
|`keycloak_service_group`| posix account group | `keycloak` |
|`keycloak_service_pidfile`| pid file path for service | `/run/keycloak.pid` |
|`jvm_package`| RHEL java package runtime | `java-1.8.0-openjdk-devel` |
|`keycloak_jvm_package`| RHEL java package runtime | `java-1.8.0-openjdk-headless` |
|`keycloak_java_home`| JAVA_HOME of installed JRE, leave empty for using specified keycloak_jvm_package RPM path | `None` |
|`keycloak_java_opts`| Additional JVM options | `-Xms1024m -Xmx2048m` |
* Install options
@@ -79,7 +80,7 @@ Role Defaults
|`keycloak_rhsso_download_url`| Download URL for RHSSO | `https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId=<productID>`|
|`keycloak_version`| keycloak.org package version | `15.0.2` |
|`keycloak_rhsso_version`| RHSSO version | `7.5.0` |
|`keycloak_rhsso_apply_patches`| Install RHSSO more recent cumulative patch | `True` |
|`keycloak_rhsso_apply_patches`| Install RHSSO more recent cumulative patch | `False` |
|`keycloak_dest`| Installation root path | `/opt/keycloak` |
|`keycloak_download_url` | Download URL for keycloak | `https://github.com/keycloak/keycloak/releases/download/{{ keycloak_version }}/{{ keycloak_archive }}` |
|`keycloak_rhn_url` | Base download URI for customer portal | `https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId=` |
@@ -99,6 +100,7 @@ Role Defaults
|`keycloak_jboss_home` | Installation work directory | `{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}` |
|`keycloak_config_dir` | Path for configuration | `{{ keycloak_jboss_home }}/standalone/configuration` |
|`keycloak_config_path_to_standalone_xml` | Custom path for configuration | `{{ keycloak_jboss_home }}/standalone/configuration/{{ keycloak_config_standalone_xml }}` |
|`keycloak_config_override_template` | Path to custom template for standalone.xml configuration | `''` |
|`keycloak_auth_realm` | Name for rest authentication realm | `master` |
|`keycloak_auth_client` | Authentication client for configuration REST calls | `admin-cli` |
|`keycloak_force_install` | Remove pre-existing versions of service | `False` |
@@ -114,7 +116,8 @@ The following are a set of _required_ variables for the role:
| Variable | Description |
|:---------|:------------|
|`keycloak_admin_password`| Password for the administration console user account |
|`keycloak_admin_password`| Password for the administration console user account (minimum 12 characters) |
|`keycloak_frontend_url` | frontend URL for keycloak endpoint | `http://localhost:8080/auth` |
The following variables are _required_ only when `keycloak_ha_enabled` is True:
@@ -122,8 +125,7 @@ The following variables are _required_ only when `keycloak_ha_enabled` is True:
| Variable | Description | Default |
|:---------|:------------|:---------|
|`keycloak_modcluster_url` | URL for the modcluster reverse proxy | `localhost` |
|`keycloak_frontend_url` | frontend URL for keycloak endpoints when a reverse proxy is used | `http://localhost` |
|`keycloak_jdbc_engine` | backend database flavour when db is enabled: [ postgres, mariadb ] | `postgres` |
|`keycloak_jdbc_engine` | backend database engine when db is enabled: [ postgres, mariadb ] | `postgres` |
|`infinispan_url` | URL for the infinispan remote-cache server | `localhost:11122` |
|`infinispan_user` | username for connecting to infinispan | `supervisor` |
|`infinispan_pass` | password for connecting to infinispan | `supervisor` |
@@ -154,14 +156,12 @@ _NOTE_: use ansible vaults or other security systems for storing credentials.
```yaml
---
- hosts: ...
vars:
keycloak_admin_password: "remembertochangeme"
collections:
- middleware_automation.keycloak
tasks:
- name: Include keycloak role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
roles:
- middleware_automation.keycloak.keycloak
```
* The following is an example playbook that makes use of the role to install Red Hat Single Sign-On from RHN:
@@ -179,7 +179,7 @@ _NOTE_: use ansible vaults or other security systems for storing credentials.
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_admin_password: "remembertochangeme"
keycloak_rhsso_enable: True
rhn_username: '<customer portal username>'
rhn_password: '<customer portal password>'
@@ -198,7 +198,7 @@ _NOTE_: use ansible vaults or other security systems for storing credentials.
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_admin_password: "remembertochangeme"
keycloak_offline_install: True
# This should be the filename of keycloak archive on Ansible node: keycloak-16.1.0.zip
```
@@ -216,14 +216,14 @@ _NOTE_: use ansible vaults or other security systems for storing credentials.
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_admin_password: "remembertochangeme"
keycloak_rhsso_enable: True
keycloak_rhsso_download_url: "<REPLACE with download url>"
# This should be the full of remote source rhsso zip file and can contain basic authentication credentials
```
* The following is an example playbook that makes use of the role to install Red Hat Single Sign-On from the controller node:
* The following is an example playbook that makes use of the role to install Red Hat Single Sign-On offline from the controller node, and apply latest cumulative patch:
```yaml
---
@@ -235,9 +235,10 @@ _NOTE_: use ansible vaults or other security systems for storing credentials.
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_admin_password: "remembertochangeme"
keycloak_rhsso_enable: True
keycloak_offline_install: True
keycloak_rhsso_apply_patches: True
# This should be the filename of rhsso zip file on Ansible node: rh-sso-7.5-server-dist.zip
```

View File

@@ -6,14 +6,14 @@ keycloak_download_url: "https://github.com/keycloak/keycloak/releases/download/{
keycloak_download_url_9x: "https://downloads.jboss.org/keycloak/{{ keycloak_version }}/{{ keycloak_archive }}"
keycloak_installdir: "{{ keycloak_dest }}/keycloak-{{ keycloak_version }}"
### Configuration specific to Red Hat Single Sing-On
### Configuration specific to Red Hat Single Sign-On
keycloak_rhsso_version: 7.5.0
rhsso_rhn_id: "{{ rhsso_rhn_ids[keycloak_rhsso_version].id }}"
keycloak_rhsso_archive: "rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip"
keycloak_rhsso_installdir: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version | regex_replace('^([0-9])\\.([0-9]*).*', '\\1.\\2') }}"
keycloak_rhn_url: 'https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId='
keycloak_rhsso_download_url: "{{ keycloak_rhn_url }}{{ rhsso_rhn_id }}"
keycloak_rhsso_apply_patches: True
keycloak_rhsso_apply_patches: False
### keycloak/rhsso choice: by default install rhsso if rhn credentials are defined
keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined and rhn_username is defined and rhn_password is defined else False }}"
@@ -21,17 +21,22 @@ keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined and rhn_username is d
keycloak_offline_install: False
### Install location and service settings
jvm_package: java-1.8.0-openjdk-devel
keycloak_jvm_package: java-1.8.0-openjdk-headless
keycloak_java_home:
keycloak_dest: /opt/keycloak
keycloak_jboss_home: "{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}"
keycloak_config_dir: "{{ keycloak_jboss_home }}/standalone/configuration"
keycloak_config_standalone_xml: "keycloak.xml"
keycloak_config_path_to_standalone_xml: "{{ keycloak_jboss_home }}/standalone/configuration/{{ keycloak_config_standalone_xml }}"
keycloak_config_override_template: ''
keycloak_service_user: keycloak
keycloak_service_group: keycloak
keycloak_service_pidfile: "/run/keycloak.pid"
keycloak_configure_firewalld: False
### administrator console password
keycloak_admin_password: ''
### Common configuration settings
keycloak_bind_address: 0.0.0.0
keycloak_host: localhost
@@ -58,7 +63,9 @@ keycloak_force_install: False
### mod_cluster reverse proxy
keycloak_modcluster_url: localhost
keycloak_frontend_url: http://localhost
### keycloak frontend url
keycloak_frontend_url: http://localhost:8080/auth
### infinispan remote caches access (hotrod)
infinispan_user: supervisor

View File

@@ -1,3 +1,4 @@
---
- name: restart keycloak
- name: "Restart handler"
ansible.builtin.include_tasks: restart_keycloak.yml
listen: "restart keycloak"

View File

@@ -48,7 +48,7 @@ argument_specs:
type: "str"
keycloak_rhsso_apply_patches:
# line 16 of keycloak/defaults/main.yml
default: true
default: false
description: "Install RHSSO more recent cumulative patch"
type: "bool"
keycloak_rhsso_installdir:
@@ -76,11 +76,14 @@ argument_specs:
default: false
description: "Perform an offline install"
type: "bool"
jvm_package:
keycloak_jvm_package:
# line 23 of keycloak/defaults/main.yml
default: "java-1.8.0-openjdk-devel"
default: "java-1.8.0-openjdk-headless"
description: "RHEL java package runtime rpm"
type: "str"
keycloak_java_home:
description: "JAVA_HOME of installed JRE, leave empty for using specified keycloak_jvm_package RPM path"
type: "str"
keycloak_dest:
# line 24 of keycloak/defaults/main.yml
default: "/opt/keycloak"
@@ -106,6 +109,11 @@ argument_specs:
default: "{{ keycloak_jboss_home }}/standalone/configuration/{{ keycloak_config_standalone_xml }}"
description: "Custom path for configuration"
type: "str"
keycloak_config_override_template:
# line 30 of keycloak/defaults/main.yml
default: ""
description: "Path to custom template for standalone.xml configuration"
type: "str"
keycloak_service_user:
# line 29 of keycloak/defaults/main.yml
default: "keycloak"

View File

@@ -7,7 +7,7 @@ galaxy_info:
role_name: keycloak
namespace: middleware_automation
author: Romain Pelisse, Guido Grazioli, Pavan Kumar Motaparthi
description: Install keycloak or Red Hat Single Sing-On server configurations
description: Install keycloak or Red Hat Single Sign-On server configurations
company: Red Hat, Inc.
license: Apache License 2.0
@@ -23,5 +23,7 @@ galaxy_info:
- keycloak
- redhat
- rhel
- rhn
- sso
- sso
- authentication
- identity
- security

View File

@@ -0,0 +1,21 @@
---
- block:
- name: "Check if packages are already installed"
ansible.builtin.command: "rpm -q {{ packages_list | join(' ') }}"
args:
warn: no
register: rpm_info
changed_when: rpm_info.failed
rescue:
- name: "Add missing packages to the yum install list"
ansible.builtin.set_fact:
packages_to_install: "{{ packages_to_install | default([]) + rpm_info.stdout_lines | map('regex_findall', 'package (.+) is not installed$') | flatten }}"
when: rpm_info.failed
- name: "Install packages: {{ packages_to_install }}"
become: yes
ansible.builtin.yum:
name: "{{ packages_to_install }}"
state: present
when: packages_to_install | default([]) | length > 0

View File

@@ -1,14 +0,0 @@
---
- block:
- name: "Check if package {{ package_name }} is already installed"
ansible.builtin.command: rpm -q {{ package_name }}
args:
warn: no
register: rpm_info
changed_when: rpm_info.failed
rescue:
- name: "Add {{ package_name }} to the yum install list if missing"
ansible.builtin.set_fact:
packages_to_install: "{{ packages_to_install + [ package_name ] }}"
when: rpm_info.failed

View File

@@ -1,18 +0,0 @@
---
- name: Set facts
ansible.builtin.set_fact:
update_cache: true
packages_to_install: []
- name: "Check packages to be installed"
ansible.builtin.include_tasks: check.yml
loop: "{{ packages_list | flatten }}"
loop_control:
loop_var: package_name
- name: "Install packages: {{ packages_to_install }}"
become: yes
ansible.builtin.yum:
name: "{{ packages_to_install }}"
state: present
when: packages_to_install | length > 0

View File

@@ -1,6 +1,6 @@
---
- name: Ensures required package firewalld are installed
ansible.builtin.include_tasks: fastpackages/install.yml
- name: Ensure required package firewalld are installed
ansible.builtin.include_tasks: fastpackages.yml
vars:
packages_list:
- firewalld
@@ -12,7 +12,7 @@
enabled: yes
state: started
- name: Configure firewall for keycloak ports
- name: "Configure firewall for {{ keycloak.service_name }} ports"
become: yes
firewalld:
port: "{{ item }}"

View File

@@ -17,25 +17,25 @@
register: existing_deploy
- block:
- name: Stop the old keycloak service
- name: "Stop the old {{ keycloak.service_name }} service"
become: yes
ignore_errors: yes
ansible.builtin.systemd:
name: keycloak
state: stopped
- name: Remove the old Keycloak deployment
- name: "Remove the old {{ keycloak.service_name }} deployment"
become: yes
ansible.builtin.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
- name: Check for an existing deployment after possible forced removal
become: yes
ansible.builtin.stat:
path: "{{ keycloak_jboss_home }}"
- name: create Keycloak service user/group
- name: "Create {{ keycloak.service_name }} service user/group"
become: yes
ansible.builtin.user:
name: "{{ keycloak_service_user }}"
@@ -43,7 +43,7 @@
system: yes
create_home: no
- name: create Keycloak install location
- name: "Create {{ keycloak.service_name }} install location"
become: yes
ansible.builtin.file:
dest: "{{ keycloak_dest }}"
@@ -58,6 +58,7 @@
archive: "{{ keycloak_dest }}/{{ keycloak.bundle }}"
- name: Check download archive path
become: yes
ansible.builtin.stat:
path: "{{ archive }}"
register: archive_path
@@ -70,9 +71,10 @@
delegate_to: localhost
- name: Download keycloak archive
ansible.builtin.get_url:
ansible.builtin.get_url: # noqa risky-file-permissions delegated, uses controller host user
url: "{{ keycloak_download_url }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
mode: 0640
delegate_to: localhost
when:
- archive_path is defined
@@ -98,9 +100,10 @@
- keycloak_rhn_url in keycloak_rhsso_download_url
- name: Download rhsso archive from alternate location
ansible.builtin.get_url:
ansible.builtin.get_url: # noqa risky-file-permissions delegated, uses controller host user
url: "{{ keycloak_rhsso_download_url }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
mode: 0640
delegate_to: localhost
when:
- archive_path is defined
@@ -180,17 +183,17 @@
jdbc_driver_module_name: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}"
when: keycloak_jdbc[keycloak_jdbc_engine].enabled
- name: "Deploy {{ keycloak.service_name }} config to {{ keycloak_config_path_to_standalone_xml }}"
- name: "Deploy {{ keycloak.service_name }} config to {{ keycloak_config_path_to_standalone_xml }} from {{ keycloak.config_template_source }}"
become: yes
ansible.builtin.template:
src: templates/standalone.xml.j2
src: "templates/{{ keycloak.config_template_source }}"
dest: "{{ keycloak_config_path_to_standalone_xml }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0640
notify:
- restart keycloak
when: not keycloak_remotecache.enabled
when: not keycloak_remotecache.enabled or keycloak_config_override_template|length > 0
- name: "Deploy {{ keycloak.service_name }} config with remote cache store to {{ keycloak_config_path_to_standalone_xml }}"
become: yes

View File

@@ -36,7 +36,7 @@
dest: /var/log/keycloak
- block:
- name: Check admin credentials by generating a token
- name: Check admin credentials by generating a token (supposed to fail on first installation)
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
method: POST

View File

@@ -1,4 +1,12 @@
---
- name: Validate admin console password
ansible.builtin.assert:
that:
- keycloak_admin_password | length > 12
quiet: True
fail_msg: "The console administrator password is empty or invalid. Please set the keycloak_admin_password variable to a 12+ char long string"
success_msg: "{{ 'Console administrator password OK' }}"
- name: Validate configuration
ansible.builtin.assert:
that:
@@ -16,15 +24,23 @@
fail_msg: "Cannot install Red Hat SSO without RHN credentials. Check rhn_username and rhn_password are defined"
success_msg: "{{ 'Installing Red Hat Single Sign-On' if keycloak_rhsso_enable else 'Installing keycloak.org' }}"
- name: Set required packages facts
ansible.builtin.set_fact:
required_packages:
- "{{ jvm_package }}"
- unzip
- procps-ng
- initscripts
- name: Validate persistence configuration
ansible.builtin.assert:
that:
- keycloak_jdbc_engine is defined and keycloak_jdbc_engine in [ 'postgres', 'mariadb' ]
- keycloak_jdbc_url | length > 0
- keycloak_db_user | length > 0
- keycloak_db_pass | length > 0
quiet: True
fail_msg: "Configuration for the JDBC persistence is invalid or incomplete"
success_msg: "Configuring JDBC persistence using {{ keycloak_jdbc_engine }} database"
when: keycloak_db_enabled
- name: Ensures required packages are installed
ansible.builtin.include_tasks: fastpackages/install.yml
- name: Ensure required packages are installed
ansible.builtin.include_tasks: fastpackages.yml
vars:
packages_list: "{{ required_packages }}"
packages_list:
- "{{ keycloak_jvm_package }}"
- unzip
- procps-ng
- initscripts

View File

@@ -1,5 +1,5 @@
---
- name: "Restart and enable keycloack service"
- name: "Restart and enable {{ keycloak.service_name }} service"
ansible.builtin.systemd:
name: keycloak
enabled: yes

View File

@@ -31,7 +31,7 @@
dest: "{{ patch_archive }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
mode: 0640
register: new_version_downloaded
when:
- not patch_archive_path.stat.exists
@@ -62,7 +62,7 @@
when:
- cli_result.rc == 0
- name: "Wait until Keycloak becomes active {{ keycloak.health_url }}"
- name: "Wait until {{ keycloak.service_name }} becomes active {{ keycloak.health_url }}"
ansible.builtin.uri:
url: "{{ keycloak.health_url }}"
register: keycloak_status
@@ -83,5 +83,5 @@
success_msg: "Patch installation successful"
- name: "Skipping patch"
debug:
ansible.builtin.debug:
msg: "Latest cumulative patch {{ rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.v }} already installed, skipping patch installation."

View File

@@ -1,12 +1,12 @@
---
- name: start keycloak
- name: "Start {{ keycloak.service_name }} service"
ansible.builtin.systemd:
name: keycloak
enabled: yes
state: started
become: yes
- name: "Wait until Keycloak becomes active {{ keycloak.health_url }}"
- name: "Wait until {{ keycloak.service_name }} becomes active {{ keycloak.health_url }}"
ansible.builtin.uri:
url: "{{ keycloak.health_url }}"
register: keycloak_status

View File

@@ -1,5 +1,5 @@
---
- name: Stop keycloak
- name: "Stop {{ keycloak.service_name }}"
ansible.builtin.systemd:
name: keycloak
enabled: yes

View File

@@ -1,4 +1,5 @@
- name: Configure keycloak service script wrapper
---
- name: "Configure {{ keycloak.service_name }} service script wrapper"
become: yes
ansible.builtin.template:
src: keycloak-service.sh.j2
@@ -9,7 +10,16 @@
notify:
- restart keycloak
- name: Configure sysconfig file for keycloak service
- name: Determine JAVA_HOME for selected JVM RPM # noqa blocked_modules
ansible.builtin.shell: |
set -o pipefail
rpm -ql {{ keycloak_jvm_package }} | grep -Po '/usr/lib/jvm/.*(?=/bin/java$)'
args:
executable: /bin/bash
changed_when: False
register: rpm_java_home
- name: "Configure sysconfig file for {{ keycloak.service_name }} service"
become: yes
ansible.builtin.template:
src: keycloak-sysconfig.j2
@@ -17,10 +27,12 @@
owner: root
group: root
mode: 0644
vars:
keycloak_rpm_java_home: "{{ rpm_java_home.stdout }}"
notify:
- restart keycloak
- name: Configure systemd unit file for keycloak service
- name: "Configure systemd unit file for {{ keycloak.service_name }} service"
ansible.builtin.template:
src: keycloak.service.j2
dest: /etc/systemd/system/keycloak.service
@@ -38,12 +50,12 @@
daemon_reload: yes
when: systemdunit.changed
- name: Start and wait for keycloak service (first node db)
- name: "Start and wait for {{ keycloak.service_name }} service (first node db)"
ansible.builtin.include_tasks: start_keycloak.yml
run_once: yes
when: keycloak_db_enabled
- name: Start and wait for keycloak service (remaining nodes)
- name: "Start and wait for {{ keycloak.service_name }} service (remaining nodes)"
ansible.builtin.include_tasks: start_keycloak.yml
- name: Check service status

View File

@@ -17,7 +17,7 @@ checkEnvVar() {
# for testing outside systemd
. /etc/sysconfig/keycloak
readonly KEYCLOAK_HOME={{ keycloak_jboss_home }}
readonly KEYCLOAK_HOME={{ keycloak.home }}
readonly KEYCLOAK_BIND_ADDRESS=${KEYCLOAK_BIND_ADDRESS}
readonly KEYCLOAK_HTTP_PORT=${KEYCLOAK_HTTP_PORT}
readonly KEYCLOAK_HTTPS_PORT=${KEYCLOAK_HTTPS_PORT}
@@ -27,7 +27,7 @@ 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."
echo "KEYCLOAK_HOME (${KEYCLOAK_HOME}) is not a directory or does not exists."
exit 1
fi

View File

@@ -1,6 +1,7 @@
# {{ ansible_managed }}
JAVA_OPTS='{{ keycloak_java_opts }}'
JBOSS_HOME={{ keycloak_jboss_home }}
JAVA_HOME={{ keycloak_java_home | default(keycloak_rpm_java_home, true) }}
JBOSS_HOME={{ keycloak.home }}
KEYCLOAK_BIND_ADDRESS={{ keycloak_bind_address }}
KEYCLOAK_HTTP_PORT={{ keycloak_http_port }}
KEYCLOAK_HTTPS_PORT={{ keycloak_https_port }}

View File

@@ -1,6 +1,6 @@
# {{ ansible_managed }}
[Unit]
Description=Keycloak Server
Description={{ keycloak.service_name }} Server
After=network.target
[Service]

View File

@@ -1,8 +1,4 @@
---
# required variables for keycloak
# administrator console password
keycloak_admin_password:
# internal variables below
rhsso_rhn_ids:
'7.5.0':
@@ -24,6 +20,7 @@ keycloak:
service_name: "{{ 'rhsso' if keycloak_rhsso_enable else 'keycloak' }}"
health_url: "{{ keycloak_management_url }}/health"
cli_path: "{{ keycloak_jboss_home }}/bin/jboss-cli.sh"
config_template_source: "{{ keycloak_config_override_template if keycloak_config_override_template | length > 0 else 'standalone.xml.j2' }}"
# database
keycloak_jdbc:

View File

@@ -0,0 +1,101 @@
keycloak_quarkus
================
Install [keycloak](https://keycloak.org/) >= 17.0.0 (quarkus) server configurations.
Role Defaults
-------------
* Service configuration
| Variable | Description | Default |
|:---------|:------------|:--------|
|`keycloak_quarkus_ha_enabled`| Enable auto configuration for database backend, clustering and remote caches on infinispan | `False` |
|`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 | `localhost` |
|`keycloak_quarkus_http_port`| HTTP port | `8080` |
|`keycloak_quarkus_https_port`| TLS HTTP port | `8443` |
|`keycloak_quarkus_ajp_port`| AJP port | `8009` |
|`keycloak_quarkus_jgroups_port`| jgroups cluster tcp port | `7600` |
|`keycloak_quarkus_java_opts`| Additional JVM options | `-Xms1024m -Xmx2048m` |
|`keycloak_quarkus_service_user`| Posix account username | `keycloak` |
|`keycloak_quarkus_service_group`| Posix account group | `keycloak` |
|`keycloak_quarkus_service_pidfile`| Pid file path for service | `/run/keycloak.pid` |
|`keycloak_quarkus_jvm_package`| RHEL java package runtime | `java-11-openjdk-headless` |
|`keycloak_quarkus_frontend_url`| Service public URL | `http://localhost:8080/auth` |
|`keycloak_quarkus_http_relative_path` | Service context path | `auth` |
* Database configuration
| Variable | Description | Default |
|:---------|:------------|:--------|
|`keycloak_quarkus_jdbc_engine` | Database engine [mariadb,postres] | `postgres` |
|`keycloak_quarkus_db_user` | User for database connection | `keycloak-user` |
|`keycloak_quarkus_db_pass` | Password for database connection | `keycloak-pass` |
|`keycloak_quarkus_jdbc_url` | JDBC URL for connecting to database | `jdbc:postgresql://localhost:5432/keycloak` |
|`keycloak_quarkus_jdbc_driver_version` | Version for JDBC driver | `9.4.1212` |
* Remote caches configuration
| Variable | Description | Default |
|:---------|:------------|:--------|
|`keycloak_quarkus_ispn_user` | Username for connecting to infinispan | `supervisor` |
|`keycloak_quarkus_ispn_pass` | Password for connecting to infinispan | `supervisor` |
|`keycloak_quarkus_ispn_url` | URL for connecting to infinispan | `localhost` |
|`keycloak_quarkus_ispn_sasl_mechanism` | Infinispan auth mechanism | `SCRAM-SHA-512` |
|`keycloak_quarkus_ispn_use_ssl` | Whether infinispan uses TLS connection | `false` |
|`keycloak_quarkus_ispn_trust_store_path` | Path to infinispan server trust certificate | `/etc/pki/java/cacerts` |
|`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_download_url`| Download URL for keycloak | `https://github.com/keycloak/keycloak/releases/download/<version>/<archive>`|
|`keycloak_quarkus_version`| keycloak.org package version | `17.0.1` |
|`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 |
|:---------|:------------|:--------|
|`keycloak_quarkus_metrics_enabled`| Whether to enable metrics | `False` |
|`keycloak_quarkus_archive` | keycloak install archive filename | `keycloak-{{ keycloak_quarkus_version }}.zip` |
|`keycloak_quarkus_installdir` | Installation path | `{{ keycloak_quarkus_dest }}/keycloak-{{ keycloak_quarkus_version }}` |
|`keycloak_quarkus_home` | Installation work directory | `{{ keycloak_quarkus_installdir }}` |
|`keycloak_quarkus_config_dir` | Path for configuration | `{{ keycloak_quarkus_home }}/conf` |
|`keycloak_quarkus_master_realm` | Name for rest authentication realm | `master` |
|`keycloak_auth_client` | Authentication client for configuration REST calls | `admin-cli` |
|`keycloak_force_install` | Remove pre-existing versions of service | `False` |
|`keycloak_url` | URL for configuration rest calls | `http://{{ keycloak_quarkus_host }}:{{ keycloak_http_port }}` |
|`keycloak_management_url` | URL for management console rest calls | `http://{{ keycloak_quarkus_host }}:{{ keycloak_management_http_port }}` |
Role Variables
--------------
| Variable | Description |
|:---------|:------------|
|`keycloak_quarkus_admin_pass`| Password of console admin account |
License
-------
Apache License 2.0
Author Information
------------------
* [Guido Grazioli](https://github.com/guidograzioli)

View File

@@ -0,0 +1,70 @@
---
### Configuration specific to keycloak
keycloak_quarkus_version: 17.0.1
keycloak_quarkus_archive: "keycloak-{{ keycloak_quarkus_version }}.zip"
keycloak_quarkus_download_url: "https://github.com/keycloak/keycloak/releases/download/{{ keycloak_quarkus_version }}/{{ keycloak_quarkus_archive }}"
keycloak_quarkus_installdir: "{{ keycloak_quarkus_dest }}/keycloak-{{ keycloak_quarkus_version }}"
# whether to install from local archive
keycloak_quarkus_offline_install: False
### Install location and service settings
keycloak_quarkus_jvm_package: java-11-openjdk-headless
keycloak_quarkus_dest: /opt/keycloak
keycloak_quarkus_home: "{{ keycloak_quarkus_installdir }}"
keycloak_quarkus_config_dir: "{{ keycloak_quarkus_home }}/conf"
keycloak_quarkus_service_user: keycloak
keycloak_quarkus_service_group: keycloak
keycloak_quarkus_service_pidfile: "/run/keycloak.pid"
keycloak_quarkus_configure_firewalld: False
### administrator console password
keycloak_quarkus_admin_user: admin
keycloak_quarkus_admin_pass: ''
keycloak_quarkus_master_realm: master
### Configuration settings
keycloak_quarkus_bind_address: 0.0.0.0
keycloak_quarkus_host: localhost
keycloak_quarkus_http_port: 8080
keycloak_quarkus_https_port: 8443
keycloak_quarkus_ajp_port: 8009
keycloak_quarkus_jgroups_port: 7600
keycloak_quarkus_java_opts: "-Xms1024m -Xmx2048m"
### Enable configuration for database backend, clustering and remote caches on infinispan
keycloak_quarkus_ha_enabled: False
### Enable database configuration, must be enabled when HA is configured
keycloak_quarkus_db_enabled: "{{ True if keycloak_quarkus_ha_enabled else False }}"
### keycloak frontend url
keycloak_quarkus_http_relative_path: auth
keycloak_quarkus_frontend_url: http://localhost:8080/auth
keycloak_quarkus_metrics_enabled: False
### infinispan remote caches access (hotrod)
keycloak_quarkus_ispn_user: supervisor
keycloak_quarkus_ispn_pass: supervisor
keycloak_quarkus_ispn_url: localhost
keycloak_quarkus_ispn_sasl_mechanism: SCRAM-SHA-512
keycloak_quarkus_ispn_use_ssl: False
# if ssl is enabled, import ispn server certificate here
keycloak_quarkus_ispn_trust_store_path: /etc/pki/java/cacerts
keycloak_quarkus_ispn_trust_store_password: changeit
### database backend engine: values [ 'postgres', 'mariadb' ]
keycloak_quarkus_jdbc_engine: postgres
### database backend credentials
keycloak_quarkus_db_user: keycloak-user
keycloak_quarkus_db_pass: keycloak-pass
keycloak_quarkus_jdbc_url: "{{ keycloak_quarkus_default_jdbc[keycloak_quarkus_jdbc_engine].url }}"
keycloak_quarkus_jdbc_driver_version: "{{ keycloak_quarkus_default_jdbc[keycloak_quarkus_jdbc_engine].version }}"
# override the variables above, following defaults show minimum supported versions
keycloak_quarkus_default_jdbc:
postgres:
url: 'jdbc:postgresql://localhost:5432/keycloak'
version: 9.4.1212
mariadb:
url: 'jdbc:mariadb://localhost:3306/keycloak'
version: 2.7.4

View File

@@ -0,0 +1,4 @@
---
- name: "Restart {{ keycloak.service_name }}"
ansible.builtin.include_tasks: restart.yml
listen: "restart keycloak"

View File

@@ -0,0 +1,203 @@
argument_specs:
main:
options:
keycloak_quarkus_version:
# line 3 of defaults/main.yml
default: "17.0.1"
description: "keycloak.org package version"
type: "str"
keycloak_quarkus_archive:
# line 4 of defaults/main.yml
default: "keycloak-{{ keycloak_quarkus_version }}.zip"
description: "keycloak install archive filename"
type: "str"
keycloak_quarkus_download_url:
# line 5 of defaults/main.yml
default: "https://github.com/keycloak/keycloak/releases/download/{{ keycloak_quarkus_version }}/{{ keycloak_quarkus_archive }}"
description: "Download URL for keycloak"
type: "str"
keycloak_quarkus_installdir:
# line 6 of defaults/main.yml
default: "{{ keycloak_quarkus_dest }}/keycloak-{{ keycloak_quarkus_version }}"
description: "Installation path"
type: "str"
keycloak_quarkus_offline_install:
# line 9 of defaults/main.yml
default: false
description: "Perform an offline install"
type: "bool"
keycloak_quarkus_jvm_package:
# line 12 of defaults/main.yml
default: "java-11-openjdk-headless"
description: "RHEL java package runtime"
type: "str"
keycloak_quarkus_dest:
# line 13 of defaults/main.yml
default: "/opt/keycloak"
description: "Installation root path"
type: "str"
keycloak_quarkus_home:
# line 14 of defaults/main.yml
default: "{{ keycloak_quarkus_installdir }}"
description: "Installation work directory"
type: "str"
keycloak_quarkus_config_dir:
# line 15 of defaults/main.yml
default: "{{ keycloak_quarkus_home }}/conf"
description: "Path for configuration"
type: "str"
keycloak_quarkus_service_user:
# line 16 of defaults/main.yml
default: "keycloak"
description: "Posix account username"
type: "str"
keycloak_quarkus_service_group:
# line 17 of defaults/main.yml
default: "keycloak"
description: "Posix account group"
type: "str"
keycloak_quarkus_service_pidfile:
# line 18 of defaults/main.yml
default: "/run/keycloak.pid"
description: "Pid file path for service"
type: "str"
keycloak_quarkus_configure_firewalld:
# line 19 of defaults/main.yml
default: false
description: "Ensure firewalld is running and configure keycloak ports"
type: "bool"
keycloak_quarkus_admin_user:
# line 22 of defaults/main.yml
default: "admin"
description: "Administration console user account"
type: "str"
keycloak_quarkus_admin_pass:
# line 23 of defaults/main.yml
default: ""
description: "Password of console admin account"
type: "str"
keycloak_quarkus_master_realm:
# line 24 of defaults/main.yml
default: "master"
description: "Name for rest authentication realm"
type: "str"
keycloak_quarkus_bind_address:
# line 27 of defaults/main.yml
default: "0.0.0.0"
description: "Address for binding service ports"
type: "str"
keycloak_quarkus_host:
# line 28 of defaults/main.yml
default: "localhost"
description: "hostname"
type: "str"
keycloak_quarkus_http_port:
# line 29 of defaults/main.yml
default: 8080
description: "HTTP port"
type: "int"
keycloak_quarkus_https_port:
# line 30 of defaults/main.yml
default: 8443
description: "HTTPS port"
type: "int"
keycloak_quarkus_ajp_port:
# line 31 of defaults/main.yml
default: 8009
description: "AJP port"
type: "int"
keycloak_quarkus_jgroups_port:
# line 32 of defaults/main.yml
default: 7600
description: "jgroups cluster tcp port"
type: "int"
keycloak_quarkus_java_opts:
# line 33 of defaults/main.yml
default: "-Xms1024m -Xmx2048m"
description: "Additional JVM options"
type: "str"
keycloak_quarkus_ha_enabled:
# line 36 of defaults/main.yml
default: false
description: "Enable auto configuration for database backend, clustering and remote caches on infinispan"
type: "bool"
keycloak_quarkus_db_enabled:
# line 38 of defaults/main.yml
default: "{{ True if keycloak_quarkus_ha_enabled else False }}"
description: "Enable auto configuration for database backend"
type: "str"
keycloak_quarkus_http_relative_path:
# line 41 of defaults/main.yml
default: "auth"
description: "Service context path"
type: "str"
keycloak_quarkus_frontend_url:
# line 41 of defaults/main.yml
default: "http://localhost:8080/auth"
description: "Service public URL"
type: "str"
keycloak_quarkus_metrics_enabled:
# line 43 of defaults/main.yml
default: false
description: "Whether to enable metrics"
type: "bool"
keycloak_quarkus_ispn_user:
# line 46 of defaults/main.yml
default: "supervisor"
description: "Username for connecting to infinispan"
type: "str"
keycloak_quarkus_ispn_pass:
# line 47 of defaults/main.yml
default: "supervisor"
description: "Password for connecting to infinispan"
type: "str"
keycloak_quarkus_ispn_url:
# line 48 of defaults/main.yml
default: "localhost"
description: "URL for connecting to infinispan"
type: "str"
keycloak_quarkus_ispn_sasl_mechanism:
# line 49 of defaults/main.yml
default: "SCRAM-SHA-512"
description: "Infinispan auth mechanism"
type: "str"
keycloak_quarkus_ispn_use_ssl:
# line 50 of defaults/main.yml
default: false
description: "Whether infinispan uses TLS connection"
type: "bool"
keycloak_quarkus_ispn_trust_store_path:
# line 52 of defaults/main.yml
default: "/etc/pki/java/cacerts"
description: "Path to infinispan server trust certificate"
type: "str"
keycloak_quarkus_ispn_trust_store_password:
# line 53 of defaults/main.yml
default: "changeit"
description: "Password for infinispan certificate keystore"
type: "str"
keycloak_quarkus_jdbc_engine:
# line 56 of defaults/main.yml
default: "postgres"
description: "Database engine [mariadb,postres]"
type: "str"
keycloak_quarkus_db_user:
# line 58 of defaults/main.yml
default: "keycloak-user"
description: "User for database connection"
type: "str"
keycloak_quarkus_db_pass:
# line 59 of defaults/main.yml
default: "keycloak-pass"
description: "Password for database connection"
type: "str"
keycloak_quarkus_jdbc_url:
# line 60 of defaults/main.yml
default: "{{ keycloak_quarkus_default_jdbc[keycloak_quarkus_jdbc_engine].url }}"
description: "JDBC URL for connecting to database"
type: "str"
keycloak_quarkus_jdbc_driver_version:
# line 61 of defaults/main.yml
default: "{{ keycloak_quarkus_default_jdbc[keycloak_quarkus_jdbc_engine].version }}"
description: "Version for JDBC driver"
type: "str"

View File

@@ -0,0 +1,28 @@
---
collections:
galaxy_info:
role_name: keycloak_quarkus
namespace: middleware_automation
author: Guido Grazioli
description: Install keycloak on quarkus server configurations
company: Red Hat, Inc.
license: Apache License 2.0
min_ansible_version: "2.9"
platforms:
- name: EL
versions:
- 8
galaxy_tags:
- keycloak
- quarkus
- redhat
- rhel
- sso
- authentication
- identity
- security

View File

@@ -0,0 +1,21 @@
---
- block:
- name: "Check if packages are already installed"
ansible.builtin.command: "rpm -q {{ packages_list | join(' ') }}"
args:
warn: no
register: rpm_info
changed_when: rpm_info.failed
rescue:
- name: "Add missing packages to the yum install list"
ansible.builtin.set_fact:
packages_to_install: "{{ packages_to_install | default([]) + rpm_info.stdout_lines | map('regex_findall', 'package (.+) is not installed$') | flatten }}"
when: rpm_info.failed
- name: "Install packages: {{ packages_to_install }}"
become: yes
ansible.builtin.yum:
name: "{{ packages_to_install }}"
state: present
when: packages_to_install | default([]) | length > 0

View File

@@ -0,0 +1,25 @@
---
- 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: yes
ansible.builtin.systemd:
name: firewalld
enabled: yes
state: started
- name: "Configure firewall for {{ keycloak.service_name }} ports"
become: yes
firewalld:
port: "{{ item }}"
permanent: true
state: enabled
immediate: yes
loop:
- "{{ keycloak_quarkus_http_port }}/tcp"
- "{{ keycloak_quarkus_https_port }}/tcp"
- "{{ keycloak_quarkus_jgroups_port }}/tcp"

View File

@@ -0,0 +1,111 @@
---
- 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
quiet: true
- name: Check for an existing deployment
become: yes
ansible.builtin.stat:
path: "{{ keycloak.home }}"
register: existing_deploy
- name: "Create {{ keycloak.service_name }} service user/group"
become: yes
ansible.builtin.user:
name: "{{ keycloak.service_user }}"
home: /opt/keycloak
system: yes
create_home: no
- name: "Create {{ keycloak.service_name }} install location"
become: yes
ansible.builtin.file:
dest: "{{ keycloak_quarkus_dest }}"
state: directory
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
mode: 0750
## check remote archive
- name: Set download archive path
ansible.builtin.set_fact:
archive: "{{ keycloak_quarkus_dest }}/{{ keycloak.bundle }}"
- name: Check download archive path
become: yes
ansible.builtin.stat:
path: "{{ archive }}"
register: archive_path
## download to controller
- name: Check local download archive path
ansible.builtin.stat:
path: "{{ lookup('env', 'PWD') }}"
register: local_path
delegate_to: localhost
- name: Download keycloak archive
ansible.builtin.get_url: # noqa risky-file-permissions delegated, uses controller host user
url: "{{ keycloak_quarkus_download_url }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
mode: 0640
delegate_to: localhost
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- not keycloak.offline_install
- name: Check downloaded archive
ansible.builtin.stat:
path: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
register: local_archive_path
delegate_to: localhost
## copy and unpack
- name: Copy archive to target nodes
ansible.builtin.copy:
src: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
dest: "{{ archive }}"
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
mode: 0750
register: new_version_downloaded
when:
- not archive_path.stat.exists
- local_archive_path.stat is defined
- local_archive_path.stat.exists
become: yes
- name: "Check target directory: {{ keycloak.home }}"
ansible.builtin.stat:
path: "{{ keycloak.home }}"
register: path_to_workdir
become: yes
- name: "Extract Keycloak archive on target"
ansible.builtin.unarchive:
remote_src: yes
src: "{{ archive }}"
dest: "{{ keycloak_quarkus_dest }}"
creates: "{{ keycloak.home }}"
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
become: yes
when:
- new_version_downloaded.changed or not path_to_workdir.stat.exists
notify:
- restart keycloak
- name: Inform decompression was not executed
ansible.builtin.debug:
msg: "{{ keycloak.home }} already exists and version unchanged, skipping decompression"
when:
- not new_version_downloaded.changed and path_to_workdir.stat.exists

View File

@@ -0,0 +1,41 @@
---
# tasks file for keycloak
- name: Check prerequisites
ansible.builtin.include_tasks: prereqs.yml
tags:
- prereqs
- name: Include firewall config tasks
ansible.builtin.include_tasks: firewalld.yml
when: keycloak_quarkus_configure_firewalld
tags:
- firewall
- name: Include install tasks
ansible.builtin.include_tasks: install.yml
tags:
- install
- name: Include systemd tasks
ansible.builtin.include_tasks: systemd.yml
tags:
- systemd
- name: "Configure config for keycloak service"
ansible.builtin.template:
src: keycloak.conf.j2
dest: "{{ keycloak.home }}/conf/keycloak.conf"
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
mode: 0644
notify:
- restart keycloak
- name: "Start and wait for keycloak service"
ansible.builtin.include_tasks: start.yml
- name: Check service status
ansible.builtin.command: "systemctl status keycloak"
register: keycloak_service_status
changed_when: False

View File

@@ -0,0 +1,34 @@
---
- name: Validate admin console password
ansible.builtin.assert:
that:
- keycloak_quarkus_admin_pass | length > 12
quiet: True
fail_msg: "The console administrator password is empty or invalid. Please set the keycloak_quarkus_admin_pass variable to a 12+ char long string"
success_msg: "{{ 'Console administrator password OK' }}"
- 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: "Cannot install HA setup without 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 credentials
# ansible.builtin.assert:
# that:
# - (rhn_username is defined and keycloak_rhsso_enable) or not keycloak_rhsso_enable or keycloak_offline_install
# - (rhn_password is defined and keycloak_rhsso_enable) or not keycloak_rhsso_enable or keycloak_offline_install
# quiet: True
# fail_msg: "Cannot install Red Hat SSO without RHN credentials. Check rhn_username and rhn_password are defined"
# success_msg: "{{ 'Installing Red Hat Single Sign-On' if keycloak_rhsso_enable else 'Installing keycloak.org' }}"
- name: Ensure required packages are installed
ansible.builtin.include_tasks: fastpackages.yml
vars:
packages_list:
- "{{ keycloak_quarkus_jvm_package }}"
- unzip
- procps-ng
- initscripts

View File

@@ -0,0 +1,7 @@
---
- name: "Restart and enable {{ keycloak.service_name }} service"
ansible.builtin.systemd:
name: keycloak
enabled: yes
state: restarted
become: yes

View File

@@ -0,0 +1,15 @@
---
- name: "Start {{ keycloak.service_name }} service"
ansible.builtin.systemd:
name: keycloak
enabled: yes
state: started
become: yes
- name: "Wait until {{ keycloak.service_name }} becomes active {{ keycloak.health_url }}"
ansible.builtin.uri:
url: "{{ keycloak.health_url }}"
register: keycloak_status
until: keycloak_status.status == 200
retries: 25
delay: 10

View File

@@ -0,0 +1,29 @@
---
- name: "Configure sysconfig file for keycloak service"
become: yes
ansible.builtin.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"
ansible.builtin.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
ansible.builtin.systemd:
daemon_reload: yes
when: systemdunit.changed

View File

@@ -0,0 +1,3 @@
# {{ ansible_managed }}
KEYCLOAK_ADMIN={{ keycloak_quarkus_admin_user }}
KEYCLOAK_ADMIN_PASSWORD='{{ keycloak_quarkus_admin_pass }}'

View File

@@ -0,0 +1,51 @@
# {{ ansible_managed }}
# Database
# Database vendor [dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres]
#db=postgres
# The username of the database user.
#db-username=keycloak
# The password of the database user.
#db-password=password
# The full database JDBC URL. If not provided, a default URL is set based on the selected database vendor.
#db-url=jdbc:postgresql://localhost/keycloak
# Observability
# If the server should expose metrics and healthcheck endpoints.
#metrics-enabled=true
# HTTP
http-enabled=true
http-port=8080
https-port=8443
# The file path to a server certificate or certificate chain in PEM format.
#https-certificate-file=${kc.home.dir}conf/server.crt.pem
# The file path to a private key in PEM format.
#https-certificate-key-file=${kc.home.dir}conf/server.key.pem
# The proxy address forwarding mode if the server is behind a reverse proxy.
#proxy=reencrypt
# Do not attach route to cookies and rely on the session affinity capabilities from reverse proxy
#spi-sticky-session-encoder-infinispan-should-attach-route=false
# Hostname for the Keycloak server.
hostname={{ keycloak_quarkus_host }}
hostname-path={{ keycloak_quarkus_http_relative_path }}
# Cluster
#cache=ispn
#Defines the cache mechanism for high-availability. [local, ispn]
#cache-config-file=conf/cache-ispn.xml
#Defines the file from which cache configuration should be loaded from.
#cache-stack=tcp
#Define the default stack to use for cluster communication and node discovery. [tcp, udp, kubernetes, ec2, azure, google]
# Proxy
# The proxy address forwarding mode if the server is behind a reverse proxy. [edge, reencrypt, passthrough]
#proxy=
# Logging
# The format of log entries.
#log-format=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n
# The log level of the root category or a comma-separated list of individual categories and their levels.
#log-level=info

View File

@@ -0,0 +1,14 @@
# {{ ansible_managed }}
[Unit]
Description=Keycloak Server
After=network.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/keycloak
PIDFile={{ keycloak_quarkus_service_pidfile }}
ExecStart={{ keycloak.home }}/bin/kc.sh start
#--http-relative-path={{ keycloak_quarkus_http_relative_path }}
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,11 @@
---
keycloak:
home: "{{ keycloak_quarkus_home }}"
config_dir: "{{ keycloak_quarkus_config_dir }}"
bundle: "{{ keycloak_quarkus_archive }}"
service_name: "keycloak"
health_url: "http://localhost:8080/realms/master/.well-known/openid-configuration"
cli_path: "{{ keycloak_quarkus_home }}/bin/kcadm.sh"
service_user: "{{ keycloak_quarkus_service_user }}"
service_group: "{{ keycloak_quarkus_service_group }}"
offline_install: "{{ keycloak_quarkus_offline_install }}"

View File

@@ -1,7 +1,7 @@
keycloak_realm
==============
Create realms and clients in [keycloak](https://keycloak.org/) or [Red Hat Single Sing-On](https://access.redhat.com/products/red-hat-single-sign-on) services.
Create realms and clients in [keycloak](https://keycloak.org/) or [Red Hat Single Sign-On](https://access.redhat.com/products/red-hat-single-sign-on) services.
Role Defaults
@@ -30,8 +30,8 @@ The following are a set of _required_ variables for the role:
| Variable | Description |
|:---------|:------------|
|`keycloak_admin_password`| Password for the administration console user account |
|`keycloak_realm` | Name of the realm to be created |
|`keycloak_admin_password`| Password for the administration console user account |
The following variables are available for creating clients:

View File

@@ -10,7 +10,10 @@ keycloak_rhsso_enable: False
keycloak_admin_user: admin
keycloak_auth_realm: master
keycloak_auth_client: admin-cli
keycloak_context: /auth
# administrator console password, this is a required variable
keycloak_admin_password: ''
### Keycloak realms, clients, roles, federation
# list of clients to create in the realm

View File

@@ -4,8 +4,13 @@ argument_specs:
keycloak_host:
# line 3 of keycloak_realm/defaults/main.yml
default: "localhost"
description: "hostname for rest calls"
description: "Hostname for rest calls"
type: "str"
keycloak_context:
# line 5 of keycloak_realm/defaults/main.yml
default: "/auth"
description: "Context path for rest calls"
type: "str"
keycloak_http_port:
# line 4 of keycloak_realm/defaults/main.yml
default: 8080

View File

@@ -3,7 +3,7 @@ galaxy_info:
role_name: keycloak_realm
namespace: middleware_automation
author: Romain Pelisse, Guido Grazioli
description: Create realms and clients in keycloak or Red Hat Single Sing-On
description: Create realms and clients in keycloak or Red Hat Single Sign-On
company: Red Hat, Inc.
license: Apache License 2.0

View File

@@ -1,7 +1,7 @@
---
- name: Generate keycloak auth token
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
url: "{{ keycloak_url }}{{ keycloak_context }}/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
@@ -13,7 +13,7 @@
- name: "Determine if realm exists"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ keycloak_realm }}"
method: GET
status_code:
- 200
@@ -25,7 +25,7 @@
- name: Create Realm
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms"
method: POST
body: "{{ lookup('template','realm.json.j2') }}"
validate_certs: no
@@ -37,7 +37,7 @@
- name: Create user federation
community.general.keycloak_user_federation:
auth_keycloak_url: "{{ keycloak_url }}/auth"
auth_keycloak_url: "{{ keycloak_url }}{{ keycloak_context }}"
auth_realm: "{{ keycloak_auth_realm }}"
auth_username: "{{ keycloak_admin_user }}"
auth_password: "{{ keycloak_admin_password }}"
@@ -56,7 +56,7 @@
- name: Create or update a Keycloak client
community.general.keycloak_client:
auth_client_id: "{{ keycloak_auth_client }}"
auth_keycloak_url: "{{ keycloak_url }}/auth"
auth_keycloak_url: "{{ keycloak_url }}{{ keycloak_context }}"
auth_realm: "{{ keycloak_auth_realm }}"
auth_username: "{{ keycloak_admin_user }}"
auth_password: "{{ keycloak_admin_password }}"

View File

@@ -4,7 +4,7 @@
realm: "{{ client.realm }}"
client_id: "{{ client.name }}"
auth_client_id: "{{ keycloak_auth_client }}"
auth_keycloak_url: "{{ keycloak_url }}/auth"
auth_keycloak_url: "{{ keycloak_url }}{{ keycloak_context }}"
auth_realm: "{{ keycloak_auth_realm }}"
auth_username: "{{ keycloak_admin_user }}"
auth_password: "{{ keycloak_admin_password }}"

View File

@@ -1,7 +1,7 @@
---
- name: "Check if User Already Exists"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
validate_certs: no
headers:
Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
@@ -9,7 +9,7 @@
- name: "Create User"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ keycloak_realm }}/users"
method: POST
body:
enabled: true
@@ -27,7 +27,7 @@
- name: "Get User"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
validate_certs: no
headers:
Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
@@ -35,7 +35,7 @@
- name: "Update User Password"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users/{{ (keycloak_user.json | first).id }}/reset-password"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ keycloak_realm }}/users/{{ (keycloak_user.json | first).id }}/reset-password"
method: PUT
body:
type: password

View File

@@ -1,7 +1,7 @@
---
- name: "Get Realm for role"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ client_role.realm }}"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ client_role.realm }}"
method: GET
status_code:
- 200
@@ -12,7 +12,7 @@
- name: Check if Mapping is available
ansible.builtin.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"
url: "{{ keycloak_url }}{{ keycloak_context }}/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
@@ -23,7 +23,7 @@
- name: "Create Role Mapping"
ansible.builtin.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 }}"
url: "{{ keycloak_url }}{{ keycloak_context }}/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 }}"

View File

@@ -1,7 +1,7 @@
---
- name: "Get User {{ user.username }}"
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
url: "{{ keycloak_url }}{{ keycloak_context }}/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
headers:
validate_certs: no
Authorization: "Bearer {{ keycloak_auth_response.json.access_token }}"
@@ -9,7 +9,7 @@
- name: Refresh keycloak auth token
ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
url: "{{ keycloak_url }}{{ keycloak_context }}/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

View File

@@ -1,9 +1,6 @@
---
# vars file for keycloak_realm
# administrator console password, this is a required variable
keycloak_admin_password:
# name of the realm to create, this is a required variable
keycloak_realm: