Compare commits

..

130 Commits
1.0.1 ... 1.1.1

Author SHA1 Message Date
github-actions
821c256f04 Update changelog for release 1.1.1 2023-03-07 07:05:59 +00:00
Guido Grazioli
7abdd83ea4 ci: linter 2023-03-03 10:54:50 +01:00
Guido Grazioli
007094ab5b Merge pull request #53 from bbarun/patch-1
Update keycloak.conf.j2
2023-03-03 10:41:58 +01:00
Božo Barun
5cdaa7aabb Update keycloak.conf.j2
The documentation states that the path is relative to the /conf directory, which is true. So if one changes the contents of this file it would have no effect because the path would be non-existent. To make things worse, there would be no obvious error stating this and the configuration would be loaded from the defaults.
2023-01-26 15:27:57 +01:00
Guido Grazioli
808b944f19 Bump to v1.1.1 2023-01-09 09:46:47 +01:00
github-actions
ae95d69435 Update changelog for release 1.1.0 2023-01-09 08:36:24 +00:00
Guido Grazioli
73d7a46307 Merge pull request #51 from ansible-middleware/tweak_start_retries_and_delay
Variables to override service start retries and delay
2023-01-02 07:46:05 +01:00
Romain Pelisse
9196b234b6 Add missing 'java' keywords to galaxy.yml 2022-12-29 12:40:21 +01:00
Romain Pelisse
46d5af90ba Allow overrides for service start retries and delay 2022-12-29 12:40:21 +01:00
Guido Grazioli
8ed82d937c Merge pull request #50 from ansible-middleware/mol_one_req
molecule: centralize requirements
2022-12-21 07:07:13 +01:00
Guido Grazioli
842cb7bf23 molecule: update overridden template 2022-12-19 23:32:35 +01:00
Guido Grazioli
cd1c2ae3e7 keycloak: switch http-invoker from security-realm to http-authentication-factory 2022-12-19 23:09:43 +01:00
Guido Grazioli
2a219222bc Add missing ejb application-security-domain 2022-12-19 22:23:45 +01:00
Guido Grazioli
ab3247fc3b docs: update resources 2022-12-19 12:08:05 +01:00
Romain Pelisse
320f167bea molecule: centralize requirements 2022-12-19 08:56:25 +01:00
Guido Grazioli
5563317718 ci: update overridexml molecule override template 2022-12-16 16:28:11 +01:00
Guido Grazioli
e209507a3f Merge pull request #46 from guidograzioli/keycloak_19
Update keycloak to 18.0.2 - sso to 7.6.1
2022-12-16 12:51:39 +01:00
Guido Grazioli
b9560458d8 Merge branch 'main' into keycloak_19 2022-12-15 15:50:29 +01:00
Guido Grazioli
d7829f77df update sso version in molecule tests 2022-12-15 15:47:12 +01:00
Guido Grazioli
e17fda2da9 Merge pull request #47 from ansible-middleware/no_log
allows user to switch no_log to True for debugging purpose
2022-12-15 15:33:10 +01:00
Guido Grazioli
34cab23abe update configuration templates 2022-12-15 15:32:33 +01:00
Guido Grazioli
7c8db06378 set keycloak to 18.0.2, sso to 7.6.1 2022-12-15 14:38:04 +01:00
Romain Pelisse
699ab1a5c4 allows user to switch no_log to True for debugging purpose 2022-12-15 14:36:31 +01:00
Guido Grazioli
007464d6b3 Update keycloak to 19.0.3 2022-12-13 15:53:53 +01:00
Guido Grazioli
2054082b40 get rid of rhn_ids dict 2022-12-13 15:31:08 +01:00
Guido Grazioli
9157f83f96 Merge pull request #45 from generalpax/patch-1
keycloak_quarkus: variable to enable development mode
2022-12-13 15:23:46 +01:00
Guido Grazioli
6e4b224fe1 molecule: quarkus update verify urls 2022-12-13 15:07:11 +01:00
Guido Grazioli
2594fd9186 update molecule scenario 2022-12-13 14:48:12 +01:00
Guido Grazioli
853d4ab96b rebase and update documentation 2022-12-13 14:28:17 +01:00
Katzy
2df5fd22cf Update main.yml 2022-12-13 14:25:52 +01:00
Katzy
422986a8fd Enable this role to start keycloak in dev mode 2022-12-13 14:25:52 +01:00
Katzy
ad4d5dae68 Update keycloak.service.j2 2022-12-13 14:25:52 +01:00
Katzy
e624870e38 Fix hardcoded health_url to parameterized 2022-12-13 14:25:52 +01:00
Guido Grazioli
63dc369148 Add missing deps declarations 2022-12-13 12:31:03 +01:00
Guido Grazioli
f4fe9df97c ci: add noqa to commands 2022-12-13 11:49:36 +01:00
Guido Grazioli
b3b016bf3b Drop deprecated builtin.command arg 2022-12-13 11:39:57 +01:00
Guido Grazioli
3d0cfc9e42 ci: add bogus lint rule to warnings 2022-12-13 11:28:56 +01:00
Guido Grazioli
89fa82eddb ci: add new docs reqs 2022-12-13 11:27:18 +01:00
Guido Grazioli
c0d4c6211e ci: drop --docker from ansible-test sanity 2022-12-13 11:24:28 +01:00
Guido Grazioli
bdc1ad8b51 Add validation of realm client and id 2022-12-13 11:20:51 +01:00
Guido Grazioli
db111aaf3a add fqcn to firewalld tasks 2022-12-13 10:50:53 +01:00
Guido Grazioli
ab1c06a2e8 ci: set new ansible rule as warning 2022-10-19 17:27:00 +02:00
Guido Grazioli
c8a2283cc6 Merge pull request #44 from kabroxiko/patch-1
keycloak_quarkus: fix /var/log/keycloak symlink to keycloak log directory
2022-10-19 17:25:10 +02:00
kabroxiko
bea5062287 fix: Wrong file location
Fix:

Wrong quarkus log link and folder creation.

Replace:
keycloak -> /opt/keycloak/keycloak-19.0.2//opt/keycloak/keycloak-19.0.2/data/log

For:
keycloak -> /opt/keycloak/keycloak-19.0.2/data/log
2022-10-08 21:05:49 -03:00
Guido Grazioli
65da436d74 restart handler: orchestrate 2022-09-28 16:48:40 +02:00
Guido Grazioli
be582171ce restart handler: orchestrate 2022-09-28 16:30:26 +02:00
Guido Grazioli
a7fbce2990 New variable for binding of management ports 2022-09-28 15:33:30 +02:00
Guido Grazioli
dfc1912a99 jdbc_driver: switch from uri to get_url 2022-09-27 15:36:14 +02:00
Guido Grazioli
ec47a1c5a8 downstream: correctly interpolate defaults 2022-09-19 22:41:18 +02:00
Guido Grazioli
52e38f7398 Bump to 1.1.0 2022-09-19 22:10:03 +02:00
Guido Grazioli
69a8860551 Break dependency on wildfly/eap 2022-09-19 22:07:23 +02:00
Guido Grazioli
9f8b1c6d76 Merge pull request #42 from guidograzioli/downstream_rename
Rename variables from `infinispan_` prefix to `keycloak_infinispan_`
2022-09-19 17:38:02 +02:00
Guido Grazioli
5e89139870 Downstream variables 2022-09-19 17:11:56 +02:00
Guido Grazioli
38b5a02e95 Rename infinispan_ vars to keycloak_infinispan_, prepare downstrea 2022-09-19 15:42:01 +02:00
Guido Grazioli
9b2ea35184 ci: linter, workflows, galaxy, molecule 2022-09-19 15:41:12 +02:00
Romain Pelisse
ded44b084d quarkus scenario skip part if hera is used 2022-08-03 09:15:44 +02:00
github-actions
1b1127ed91 Update changelog for release 1.0.7 2022-07-06 12:10:08 +00:00
Guido Grazioli
9252433cc8 Merge pull request #39 from xabarin-forks/use_absolute_path_for_certs
keycloak_quarkus: use absolute path for certificate files
2022-07-05 14:06:02 +02:00
Xabier Davila
adb0a4da45 Fix molecule tests 2022-07-04 08:31:10 +02:00
Xabier Davila
41caa49cfc Use absolute path for certificate files 2022-07-01 10:31:18 +02:00
Guido Grazioli
d47e045f5e Merge pull request #38 from xabarin-forks/use_sudo_for_tasks_that_need_it
Use become for tasks that will otherwise fail
2022-06-30 16:43:11 +02:00
Xabier Davila
4baa61e0cf Use sudo for tasks that will otherwise fail 2022-06-30 16:15:48 +02:00
Guido Grazioli
065fb53eb2 Bump to 1.0.7 2022-06-01 17:33:29 +02:00
github-actions
713437343d Update changelog for release 1.0.6 2022-06-01 13:12:11 +00:00
Guido Grazioli
46f445560b Bump to 1.0.6 2022-05-31 19:10:20 +02:00
Guido Grazioli
76cbb4c676 keycloak_quarkus: add https to molecule test setup (#36)
* keycloak_quarkus: add https to molecule test setup

* move converge pre_tasks to prepare phase

* Update zipfile unarchive to cater for existing certs
2022-05-31 12:07:18 -05:00
Guido Grazioli
469036e9e7 keycloak_quarkus: set logfile path correctly under keycloak home (#35) 2022-05-31 03:47:29 -05:00
Guido Grazioli
8454f5c341 keycloak_quarkus: add selected java to PATH in systemd unit (#34) 2022-05-31 03:43:55 -05:00
github-actions
d5a63f55f9 Update changelog for release 1.0.5 2022-05-25 15:37:36 +00:00
Guido Grazioli
09a34567a7 Bump to 1.0.5, add EE setup ref 2022-05-19 09:38:47 +02:00
Harsha Cherukuri
bc63cbf649 Merge pull request #32 from guidograzioli/config_options
Update config options: keycloak and quarkus
2022-05-18 13:53:26 -04:00
Guido Grazioli
281767f505 add missing variable spec 2022-05-18 10:05:34 +02:00
Guido Grazioli
8bede6791e update 18.0.0, add JAVA_HOME check, runas systemd unit 2022-05-18 09:29:28 +02:00
Guido Grazioli
0ddbc66448 Add keycloak X playbook, update roles README 2022-05-17 19:30:13 +02:00
Guido Grazioli
31420fc24c update config options: keycloak and quarkus 2022-05-17 18:59:10 +02:00
github-actions
2cc835219c Update changelog for release 1.0.4 2022-05-11 12:23:41 +00:00
Guido Grazioli
9e3cd22484 Bump to 1.0.4 2022-05-11 14:05:43 +02:00
Guido Grazioli
9278d3440e ci: linter version update fixes 2022-05-11 11:33:52 +02:00
Guido Grazioli
3b45c133b8 fix incorrect downloaded archive filemode 2022-05-11 10:38:52 +02:00
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
98 changed files with 4323 additions and 672 deletions

View File

@@ -5,6 +5,8 @@ exclude_paths:
- molecule/
- .ansible-lint
- .yamllint
- meta/
- playbooks/roles/
rulesdir:
- ../../ansible-lint-custom-rules/rules/
@@ -16,12 +18,22 @@ enable_list:
warn_list:
- role_vars_start_with_role_name
- vars_in_vars_files_have_valid_names
- vars_should_not_be_used
- experimental
- ignore-errors
- no-handler
- fqcn-builtins
- no-log-password
- jinja[spacing]
- jinja[invalid]
- meta-no-tags
- name[template]
- name[casing]
- fqcn[action]
- schema[meta]
skip_list:
- vars_should_not_be_used
- file_is_small_enough
use_default_rules: true
parseable: true

View File

@@ -1,11 +1,16 @@
---
name: CI
"on":
on:
push:
branches:
- main
pull_request:
env:
COLORTERM: 'yes'
TERM: 'xterm-256color'
PYTEST_ADDOPTS: '--color=yes'
jobs:
ci:
runs-on: ubuntu-latest
@@ -29,18 +34,19 @@ jobs:
pip install yamllint 'molecule[docker]~=3.5.2' ansible-core flake8 ansible-lint voluptuous
pip install -r ansible_collections/middleware_automation/keycloak/requirements.txt
- name: Create default collection path
run: |
mkdir -p /home/runner/.ansible/
ln -s /home/runner/work/keycloak/keycloak /home/runner/.ansible/collections
- name: Install ansible-lint custom rules
uses: actions/checkout@v2
with:
repository: ansible-middleware/ansible-lint-custom-rules
path: ansible_collections/ansible-lint-custom-rules/
- name: Create default collection path
run: |
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 -v --color --python ${{ matrix.python_version }} --exclude changelogs/fragments/.gitignore --skip-test symlinks
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,22 @@ 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
mkdir -p /home/runner/.ansible/
ln -s /home/runner/work/keycloak/keycloak /home/runner/.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)}} }'

2
.gitignore vendored
View File

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

129
CHANGELOG.rst Normal file
View File

@@ -0,0 +1,129 @@
============================================
middleware_automation.keycloak Release Notes
============================================
.. contents:: Topics
This changelog describes changes after version 0.2.6.
v1.1.1
======
Bugfixes
--------
- keycloak-quarkus: fix ``cache-config-file`` path in keycloak.conf.j2 template `#53 <https://github.com/ansible-middleware/keycloak/pull/53>`_
v1.1.0
======
Minor Changes
-------------
- Update keycloak to 18.0.2 - sso to 7.6.1 `#46 <https://github.com/ansible-middleware/keycloak/pull/46>`_
- Variable ``keycloak_no_log`` controls ansible ``no_log`` parameter (for debugging purposes) `#47 <https://github.com/ansible-middleware/keycloak/pull/47>`_
- Variables to override service start retries and delay `#51 <https://github.com/ansible-middleware/keycloak/pull/51>`_
- keycloak_quarkus: variable to enable development mode `#45 <https://github.com/ansible-middleware/keycloak/pull/45>`_
Breaking Changes / Porting Guide
--------------------------------
- Rename variables from ``infinispan_`` prefix to ``keycloak_infinispan_`` `#42 <https://github.com/ansible-middleware/keycloak/pull/42>`_
Bugfixes
--------
- keycloak_quarkus: fix /var/log/keycloak symlink to keycloak log directory `#44 <https://github.com/ansible-middleware/keycloak/pull/44>`_
v1.0.7
======
Breaking Changes / Porting Guide
--------------------------------
- keycloak_quarkus: use absolute path for certificate files `#39 <https://github.com/ansible-middleware/keycloak/pull/39>`_
Bugfixes
--------
- keycloak_quarkus: use become for tasks that will otherwise fail `#38 <https://github.com/ansible-middleware/keycloak/pull/38>`_
v1.0.6
======
Bugfixes
--------
- keycloak_quarkus: add selected java to PATH in systemd unit `#34 <https://github.com/ansible-middleware/keycloak/pull/34>`_
- keycloak_quarkus: set logfile path correctly under keycloak home `#35 <https://github.com/ansible-middleware/keycloak/pull/35>`_
v1.0.5
======
Minor Changes
-------------
- Update config options: keycloak and quarkus `#32 <https://github.com/ansible-middleware/keycloak/pull/32>`_
v1.0.4
======
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,34 +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).
### Choosing between upstream project (Keycloak) and Red Hat Single Sign-On (RHSSO)
The general flag `keycloak_rhsso_enable` controls what to install between upstream (Keycloak, when `False`) or Red Hat Single Sign-On (when `True`).
The default value for the flag if `True` when Red Hat Network credentials are defined, `False` otherwise.
#### Install upstream (Keycloak) from keycloak releases
This is the default approach when RHN credentials are not defined. Keycloak is downloaded from keycloak builds (hosted on github.com) locally, and distributed to target nodes.
#### Install RHSSO from the Red Hat Customer Support Portal
Define the credentials as follows, and the default behaviour is to download a fresh archive of RHSSO on the controller node, then distribute to target nodes.
```yaml
rhn_username: '<customer_portal_username>'
rhn_password: '<customer_portal_password>'
# (keycloak_rhsso_enable defaults to True)
```
For full service configuration details, refer to the [keycloak role README](https://github.com/ansible-middleware/keycloak/blob/main/roles/keycloak/README.md).
#### Install from controller node (local source)
@@ -100,14 +79,12 @@ And depending on `keycloak_rhsso_enable`:
For RHSSO:
```yaml
keycloak_rhsso_enable: True
keycloak_rhsso_download_url: "https://<internal-nexus.private.net>/<path>/<to>/rh-sso-x.y.z-server-dist.zip"
sso_download_url: "https://<internal-nexus.private.net>/<path>/<to>/rh-sso-x.y.z-server-dist.zip"
```
For keycloak:
```yaml
keycloak_rhsso_enable: False
keycloak_download_url: "https://<internal-nexus.private.net>/<path>/<to>/keycloak-x.y.zip"
```
@@ -134,7 +111,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 +131,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

7
bindep.txt Normal file
View File

@@ -0,0 +1,7 @@
python39-devel [platform:rpm compile]
git-lfs [platform:rpm]
python3-netaddr [platform:rpm]
python3-lxml [platform:rpm]
python3-jmespath [platform:rpm]
python3-requests [platform:rpm]

142
changelogs/changelog.yaml Normal file
View File

@@ -0,0 +1,142 @@
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'
1.0.4:
release_date: '2022-05-11'
1.0.5:
changes:
minor_changes:
- 'Update config options: keycloak and quarkus `#32 <https://github.com/ansible-middleware/keycloak/pull/32>`_
'
fragments:
- 32.yaml
release_date: '2022-05-25'
1.0.6:
changes:
bugfixes:
- 'keycloak_quarkus: add selected java to PATH in systemd unit `#34 <https://github.com/ansible-middleware/keycloak/pull/34>`_
'
- 'keycloak_quarkus: set logfile path correctly under keycloak home `#35 <https://github.com/ansible-middleware/keycloak/pull/35>`_
'
fragments:
- 34.yaml
- 35.yaml
release_date: '2022-06-01'
1.0.7:
changes:
breaking_changes:
- 'keycloak_quarkus: use absolute path for certificate files `#39 <https://github.com/ansible-middleware/keycloak/pull/39>`_
'
bugfixes:
- 'keycloak_quarkus: use become for tasks that will otherwise fail `#38 <https://github.com/ansible-middleware/keycloak/pull/38>`_
'
fragments:
- 38.yaml
- 39.yaml
release_date: '2022-07-06'
1.1.0:
changes:
breaking_changes:
- 'Rename variables from ``infinispan_`` prefix to ``keycloak_infinispan_``
`#42 <https://github.com/ansible-middleware/keycloak/pull/42>`_
'
bugfixes:
- 'keycloak_quarkus: fix /var/log/keycloak symlink to keycloak log directory
`#44 <https://github.com/ansible-middleware/keycloak/pull/44>`_
'
minor_changes:
- 'Update keycloak to 18.0.2 - sso to 7.6.1 `#46 <https://github.com/ansible-middleware/keycloak/pull/46>`_
'
- 'Variable ``keycloak_no_log`` controls ansible ``no_log`` parameter (for debugging
purposes) `#47 <https://github.com/ansible-middleware/keycloak/pull/47>`_
'
- 'Variables to override service start retries and delay `#51 <https://github.com/ansible-middleware/keycloak/pull/51>`_
'
- 'keycloak_quarkus: variable to enable development mode `#45 <https://github.com/ansible-middleware/keycloak/pull/45>`_
'
fragments:
- 42.yaml
- 44.yaml
- 45.yaml
- 46.yaml
- 47.yaml
- 51.yaml
release_date: '2023-01-09'
1.1.1:
changes:
bugfixes:
- 'keycloak-quarkus: fix ``cache-config-file`` path in keycloak.conf.j2 template
`#53 <https://github.com/ansible-middleware/keycloak/pull/53>`_
'
fragments:
- 53.yaml
release_date: '2023-03-07'

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

@@ -21,6 +21,19 @@
<div class="wy-side-nav-search" >
<a href="#" class="icon icon-home"> Keycloak Ansible Collection</a>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Middleware Automation</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/infinispan/">Infinispan / Red Hat Data Grid</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/keycloak/">Keycloak / Red Hat Single Sign-On</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/wildfly/">Wildfly / Red Hat JBoss EAP</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/jws/">Tomcat / Red Hat JWS</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/amq/">ActiveMQ / Red Hat AMQ Broker</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/amq_streams/">Kafka / Red Hat AMQ Streams</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/redhat-csp-download/">Red Hat CSP Download</a></li>
<li class="toctree-l1"><a class="reference internal" href="https://ansible-middleware.github.io/ansible_collections_jcliff/">JCliff</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

View File

@@ -15,8 +15,8 @@ Welcome to Keycloak Collection documentation
:maxdepth: 2
:caption: Developer documentation
developing
testing
developing
releasing
.. toctree::
@@ -25,8 +25,15 @@ Welcome to Keycloak Collection documentation
Changelog <CHANGELOG>
Indices and tables
==================
.. toctree::
:maxdepth: 2
:caption: Middleware collections
* :ref:`genindex`
* :ref:`search`
Infinispan / Red Hat Data Grid <https://ansible-middleware.github.io/infinispan/>
Keycloak / Red Hat Single Sign-On <https://ansible-middleware.github.io/keycloak/>
Wildfly / Red Hat JBoss EAP <https://ansible-middleware.github.io/wildfly/>
Tomcat / Red Hat JWS <https://ansible-middleware.github.io/jws/>
ActiveMQ / Red Hat AMQ Broker <https://ansible-middleware.github.io/amq/>
Kafka / Red Hat AMQ Streams <https://ansible-middleware.github.io/amq_streams/>
Red Hat CSP Download <https://ansible-middleware.github.io/redhat-csp-download/>
JCliff <https://ansible-middleware.github.io/ansible_collections_jcliff/>

View File

@@ -1,4 +1,6 @@
antsibull>=0.17.0
antsibull-docs
antsibull-changelog
ansible-base>=2.10.12
sphinx-rtd-theme
git+https://github.com/felixfontein/ansible-basic-sphinx-ext

View File

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

View File

@@ -46,4 +46,3 @@ EOF
# run the playbook
ansible-playbook -i inventory playbooks/keycloak.yml
```

View File

@@ -1,7 +1,7 @@
---
namespace: middleware_automation
name: keycloak
version: "1.0.1"
version: "1.1.1"
readme: README.md
authors:
- Romain Pelisse <rpelisse@redhat.com>
@@ -20,14 +20,25 @@ tags:
- security
- infrastructure
- authentication
- java
dependencies:
"middleware_automation.redhat_csp_download": ">=1.2.1"
"middleware_automation.wildfly": ">=0.0.6"
"community.general": ">=5.6.0"
"ansible.posix": ">=1.4.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
- .gitignore
- .github
- .ansible-lint
- .yamllint
- '*.tar.gz'
- '*.zip'
- molecule
- changelogs
- docs/_gh_include
- docs/conf.py
- docs/roles.rst.template
- docs/requirements.yml

View File

@@ -0,0 +1,11 @@
---
version: 1
build_arg_defaults:
EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:stable-2.12-devel'
dependencies:
galaxy: requirements.yml
python: requirements.txt
system: bindep.txt
additional_build_steps:
append:
- RUN alternatives --set python /usr/bin/python3

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

@@ -1,7 +1,7 @@
---
dependency:
name: shell
command: ansible-galaxy collection install -r molecule/default/requirements.yml -p $HOME/.ansible/collections --force-with-deps
command: ansible-galaxy collection install -r molecule/requirements.yml -p $HOME/.ansible/collections --force-with-deps
driver:
name: docker
lint: |
@@ -16,7 +16,7 @@ platforms:
port_bindings:
- "8080/tcp"
- "8443/tcp"
- "8009/tcp"
- "8009/tcp"
provisioner:
name: ansible
config_options:
@@ -33,7 +33,7 @@ provisioner:
localhost:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
env:
ANSIBLE_FORCE_COLOR: "true"
ANSIBLE_FORCE_COLOR: "true"
verifier:
name: ansible
scenario:

View File

@@ -2,11 +2,19 @@
- 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
name:
- sudo
- java-1.8.0-openjdk
state: present
- name: Prepare
hosts: all
tasks:
- name: "Run preparation common to all scenario"
ansible.builtin.include_tasks: ../prepare.yml
vars:
assets:
- "{{ assets_server }}/sso/7.6.0/rh-sso-7.6.0-server-dist.zip"
- "{{ assets_server }}/sso/7.6.1/rh-sso-7.6.1-patch.zip"

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/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,9 @@
---
- name: Prepare
hosts: all
tasks:
- name: "Run preparation common to all scenario"
ansible.builtin.include_tasks: ../prepare.yml
vars:
assets:
- "{{ assets_server }}/sso/7.6.0/rh-sso-7.6.0-server-dist.zip"

1
molecule/overridexml/roles Symbolic link
View File

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

View File

@@ -0,0 +1,556 @@
<?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.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>
<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 http-authentication-factory="management-http-authentication">
<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"/>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
<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>
<http-authentication-factory name="application-http-authentication" security-domain="ApplicationDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="BASIC">
<mechanism-realm realm-name="ApplicationRealm"/>
</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" sasl-authentication-factory="application-sasl-authentication"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
<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 http-authentication-factory="application-http-authentication"/>
</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"

28
molecule/prepare.yml Normal file
View File

@@ -0,0 +1,28 @@
---
- name: Display Ansible version
ansible.builtin.debug:
msg: "Ansible version is {{ ansible_version.full }}"
- name: Install sudo
ansible.builtin.yum:
name:
- sudo
- iproute
state: present
- name: "Retrieve assets server from env"
ansible.builtin.set_fact:
assets_server: "{{ lookup('env','MIDDLEWARE_DOWNLOAD_RELEASE_SERVER_URL') }}"
- name: "Download and deploy jws zips from {{ assets_server }}"
ansible.builtin.get_url:
url: "{{ asset }}"
dest: "{{ lookup('env', 'PWD') }}"
validate_certs: no
delegate_to: localhost
loop: "{{ assets }}"
loop_control:
loop_var: asset
when:
- assets_server is defined
- assets_server | length > 0

View File

@@ -0,0 +1,45 @@
---
- name: Converge
hosts: all
vars:
keycloak_quarkus_admin_pass: "remembertochangeme"
keycloak_admin_password: "remembertochangeme"
keycloak_realm: TestRealm
keycloak_quarkus_host: instance
keycloak_quarkus_http_relative_path: ''
keycloak_quarkus_log: file
keycloak_quarkus_https_enabled: True
keycloak_quarkus_key_file: "{{ keycloak.home }}/conf/key.pem"
keycloak_quarkus_cert_file: "{{ keycloak.home }}/conf/cert.pem"
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,55 @@
---
dependency:
name: shell
command: ansible-galaxy collection install -r molecule/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"
published_ports:
- 0.0.0.0:8443:8443/tcp
provisioner:
name: ansible
config_options:
defaults:
interpreter_python: auto_silent
ssh_connection:
pipelining: false
playbooks:
prepare: prepare.yml
converge: converge.yml
verify: verify.yml
inventory:
host_vars:
localhost:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
env:
ANSIBLE_FORCE_COLOR: "true"
verifier:
name: ansible
scenario:
test_sequence:
- dependency
- lint
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- idempotence
- side_effect
- verify
- cleanup
- destroy

View File

@@ -0,0 +1,38 @@
---
- name: Prepare
hosts: all
tasks:
- name: Install sudo
ansible.builtin.yum:
name: sudo
state: present
- name: "Display hera_home if defined."
ansible.builtin.set_fact:
hera_home: "{{ lookup('env', 'HERA_HOME') }}"
- ansible.builtin.command: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes -subj '/CN=instance'
delegate_to: localhost
- block:
- ansible.builtin.lineinfile:
dest: /etc/hosts
line: "127.0.0.1 instance"
state: present
delegate_to: localhost
become: yes
when:
- hera_home is defined
- hera_home | length == 0
- ansible.builtin.file:
state: directory
path: /opt/keycloak/keycloak-18.0.0/conf/
- ansible.builtin.copy:
src: "{{ item }}"
dest: "/opt/keycloak/keycloak-18.0.0/conf/{{ item }}"
mode: 0444
loop:
- cert.pem
- key.pem

1
molecule/quarkus/roles Symbolic link
View File

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

View File

@@ -0,0 +1,35 @@
---
- 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"
- set_fact:
hera_home: "{{ lookup('env', 'HERA_HOME') }}"
- block:
- name: Fetch openID config
shell: |
curl https://instance:8443/realms/master/.well-known/openid-configuration -k | jq .
delegate_to: localhost
register: openid_config
- debug:
msg: " {{ openid_config.stdout | from_json }}"
delegate_to: localhost
- name: Verify endpoint URLs
assert:
that:
- (openid_config.stdout | from_json)["backchannel_authentication_endpoint"] == 'https://instance/realms/master/protocol/openid-connect/ext/ciba/auth'
- (openid_config.stdout | from_json)['issuer'] == 'https://instance/realms/master'
- (openid_config.stdout | from_json)['authorization_endpoint'] == 'https://instance/realms/master/protocol/openid-connect/auth'
- (openid_config.stdout | from_json)['token_endpoint'] == 'https://instance/realms/master/protocol/openid-connect/token'
delegate_to: localhost
when:
- hera_home is defined
- hera_home | length == 0

View File

@@ -2,9 +2,8 @@
collections:
- name: middleware_automation.redhat_csp_download
version: ">=1.2.1"
- name: middleware_automation.wildfly
version: ">=0.0.5"
- name: community.general
- name: ansible.posix
- name: community.docker
version: ">=1.9.1"

View File

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

View File

@@ -0,0 +1,68 @@
---
- name: Playbook for Keycloak Hosts
hosts: all
tasks:
- name: Keycloak Realm Role
ansible.builtin.include_role:
name: keycloak_realm
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_realm: TestRealm
keycloak_user_federation:
- realm: TestRealm
name: my-ldap
provider_id: ldap
provider_type: org.keycloak.storage.UserStorageProvider
config:
priority: '0'
enabled: true
cachePolicy: DEFAULT
batchSizeForSync: '1000'
editMode: READ_ONLY
importEnabled: true
syncRegistrations: false
vendor: other
usernameLDAPAttribute: uid
rdnLDAPAttribute: uid
uuidLDAPAttribute: entryUUID
userObjectClasses: inetOrgPerson, organizationalPerson
connectionUrl: ldaps://ldap.example.com:636
usersDn: ou=Users,dc=example,dc=com
authType: simple
bindDn: cn=directory reader
bindCredential: password
searchScope: '1'
validatePasswordPolicy: false
trustEmail: false
useTruststoreSpi: ldapsOnly
connectionPooling: true
pagination: true
allowKerberosAuthentication: false
debug: false
useKerberosForPasswordAuthentication: false
mappers:
- name: "full name"
providerId: "full-name-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
ldap.full.name.attribute: cn
read.only: true
write.only: false
keycloak_clients:
- name: TestClient1
client_id: TestClient1
roles:
- TestClient1Admin
- TestClient1User
realm: "{{ keycloak_realm }}"
public_client: True
web_origins:
- http://testclient1origin/application
- http://testclient1origin/other
users:
- username: TestUser
password: password
client_roles:
- client: TestClient1
role: TestClient1User
realm: "{{ keycloak_realm }}"

View File

@@ -0,0 +1,13 @@
---
- name: Playbook for Keycloak X Hosts
hosts: all
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_quarkus_host: localhost:8443
keycloak_quarkus_http_relative_path: ''
keycloak_quarkus_log: file
keycloak_quarkus_https_enabled: True
keycloak_quarkus_key_file: conf/key.pem
keycloak_quarkus_cert_file: conf/cert.pem
roles:
- middleware_automation.keycloak.keycloak_quarkus

View File

@@ -1,67 +1,26 @@
---
- name: Playbook for Keycloak Hosts
hosts: keycloak
tasks:
- name: Keycloak Realm Role
ansible.builtin.include_role:
name: middleware_automation.keycloak.keycloak_realm
vars:
keycloak_admin_password: "changeme"
keycloak_realm: TestRealm
keycloak_user_federation:
- realm: TestRealm
name: my-ldap
provider_id: ldap
provider_type: org.keycloak.storage.UserStorageProvider
config:
priority: '0'
enabled: true
cachePolicy: DEFAULT
batchSizeForSync: '1000'
editMode: READ_ONLY
importEnabled: true
syncRegistrations: false
vendor: other
usernameLDAPAttribute: uid
rdnLDAPAttribute: uid
uuidLDAPAttribute: entryUUID
userObjectClasses: inetOrgPerson, organizationalPerson
connectionUrl: ldaps://ldap.example.com:636
usersDn: ou=Users,dc=example,dc=com
authType: simple
bindDn: cn=directory reader
bindCredential: password
searchScope: '1'
validatePasswordPolicy: false
trustEmail: false
useTruststoreSpi: ldapsOnly
connectionPooling: true
pagination: true
allowKerberosAuthentication: false
debug: false
useKerberosForPasswordAuthentication: false
mappers:
- name: "full name"
providerId: "full-name-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
ldap.full.name.attribute: cn
read.only: true
write.only: false
keycloak_clients:
- name: TestClient1
roles:
- TestClient1Admin
- TestClient1User
realm: "{{ keycloak_realm }}"
public_client: True
web_origins:
- http://testclient1origin/application
- http://testclient1origin/other
users:
- username: TestUser
password: password
client_roles:
- client: TestClient1
role: TestClient1User
realm: "{{ keycloak_realm }}"
hosts: all
vars:
keycloak_admin_password: "remembertochangeme"
keycloak_realm: TestRealm
keycloak_clients:
- name: TestClient1
client_id: TestClient1
roles:
- TestClient1Admin
- TestClient1User
realm: "{{ keycloak_realm }}"
public_client: True
web_origins:
- http://testclient1origin/application
- http://testclient1origin/other
users:
- username: TestUser
password: password
client_roles:
- client: TestClient1
role: TestClient1User
realm: "{{ keycloak_realm }}"
roles:
- middleware_automation.keycloak.keycloak_realm

View File

@@ -1,14 +1,9 @@
---
- name: Playbook for Keycloak Hosts
hosts: keycloak
collections:
- middleware_automation.redhat_csp_download
vars:
keycloak_admin_password: "remembertochangeme"
sso_enable: True
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

@@ -2,6 +2,5 @@
collections:
- name: middleware_automation.redhat_csp_download
version: ">=1.2.1"
- name: middleware_automation.wildfly
version: ">=0.0.5"
- name: community.general
- name: ansible.posix

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
@@ -20,7 +20,6 @@ Dependencies
The roles depends on:
* the `redhat_csp_download` role from [middleware_automation.redhat_csp_download](https://github.com/ansible-middleware/redhat-csp-download) collection if Red Hat Single Sign-on zip have to be downloaded from RHN.
* the `wildfly_driver` role from [middleware_automation.wildfly](https://github.com/ansible-middleware/wildfly) collection
Versions
@@ -28,18 +27,19 @@ Versions
| RH-SSO VERSION | Release Date | Keycloak Version | EAP Version | Notes |
|:---------------|:------------------|:-----------------|:------------|:----------------|
|`7.5.0 GA` |September 20, 2021 |`15.0.2` | `7.4.0` |[Release Notes](https://access.redhat.com/documentation/en-us/red_hat_single_sign-on/7.5/html/release_notes/index)|
|`7.5.0 GA` |September 20, 2021 |`15.0.2` | `7.4.6` |[Release Notes](https://access.redhat.com/documentation/en-us/red_hat_single_sign-on/7.5/html/release_notes/index)|
|`7.6.0 GA` |June 30, 2022 |`18.0.3` | `7.4.6` |[Release Notes](https://access.redhat.com/documentation/en-us/red_hat_single_sign-on/7.6/html-single/release_notes/index)|
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 |
|:---------------|:------------------|:-----------------|:----------------|
|`7.5.0 GA` |January 20, 2022 |`7.5.1 GA` |[Release Notes](https://access.redhat.com/articles/6646321)|
|`7.5.0 GA` |January 20, 2022 |`7.5.3 GA` |[Release Notes](https://access.redhat.com/articles/6646321)|
|`7.6.0 GA` |November 11, 2022 |`7.6.1 GA` |[Release Notes](https://access.redhat.com/articles/6982711)|
Role Defaults
@@ -53,6 +53,7 @@ Role Defaults
|`keycloak_db_enabled`| Enable auto configuration for database backend | `True` if `keycloak_ha_enabled` is True, else `False` |
|`keycloak_admin_user`| Administration console user account | `admin` |
|`keycloak_bind_address`| Address for binding service ports | `0.0.0.0` |
|`keycloak_management_port_bind_address`| Address for binding management ports | `127.0.0.1` |
|`keycloak_host`| hostname | `localhost` |
|`keycloak_http_port`| HTTP port | `8080` |
|`keycloak_https_port`| TLS HTTP port | `8443` |
@@ -60,29 +61,25 @@ 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
| Variable | Description | Default |
|:---------|:------------|:---------|
|`keycloak_rhsso_enable`| Enable Red Hat Single Sign-on installation | `False` |
|`keycloak_offline_install` | perform an offline install | `False`|
|`keycloak_download_url`| Download URL for keycloak | `https://github.com/keycloak/keycloak/releases/download/<version>/<archive>`|
|`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_version`| keycloak.org package version | `18.0.2` |
|`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=` |
|`keycloak_configure_firewalld` | Ensure firewalld is running and configure keycloak ports | `False` |
@@ -90,21 +87,18 @@ Role Defaults
| Variable | Description | Default |
|:---------|:------------|:--------|
|`keycloak_archive` | keycloak install archive filename | `keycloak-{{ keycloak_version }}.zip` |
|`keycloak_archive` | keycloak install archive filename | `keycloak-legacy-{{ keycloak_version }}.zip` |
|`keycloak_download_url_9x` | Download URL for keycloak (deprecated) | `https://downloads.jboss.org/keycloak/{{ keycloak_version }}/{{ keycloak_archive }}` |
|`keycloak_installdir` | Installation path | `{{ keycloak_dest }}/keycloak-{{ keycloak_version }}` |
|`keycloak_rhsso_archive` | Red Hat SSO install archive filename | `rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip` |
|`keycloak_rhsso_installdir`| Installation path for Red Hat SSO | `{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version | regex_replace('^([0-9])\.([0-9]*).*', '\1.\2') }}` |
|`keycloak_rhsso_download_url`| Full download URI for Red Hat SSO | `{{ keycloak_rhn_url }}{{ rhsso_rhn_id }}` |
|`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` |
|`keycloak_url` | URL for configuration rest calls | `http://{{ keycloak_host }}:{{ keycloak_http_port }}` |
|`keycloak_management_url` | URL for management console rest calls | `http://{{ keycloak_host }}:{{ keycloak_management_http_port }}` |
|`rhsso_rhn_id` | Customer Portal product ID for Red Hat SSO | `{{ rhsso_rhn_ids[keycloak_rhsso_version].id }}` |
Role Variables
@@ -114,7 +108,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,15 +117,14 @@ 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` |
|`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` |
|`infinispan_sasl_mechanism`| Authentication type | `SCRAM-SHA-512` |
|`infinispan_use_ssl`| Enable hotrod TLS communication | `False` |
|`infinispan_trust_store_path`| Path to truststore with infinispan server certificate | `/etc/pki/java/cacerts` |
|`infinispan_trust_store_password`| Password for opening truststore | `changeit` |
|`keycloak_jdbc_engine` | backend database engine when db is enabled: [ postgres, mariadb ] | `postgres` |
|`keycloak_infinispan_url` | URL for the infinispan remote-cache server | `localhost:11122` |
|`keycloak_infinispan_user` | username for connecting to infinispan | `supervisor` |
|`keycloak_infinispan_pass` | password for connecting to infinispan | `supervisor` |
|`keycloak_infinispan_sasl_mechanism`| Authentication type | `SCRAM-SHA-512` |
|`keycloak_infinispan_use_ssl`| Enable hotrod TLS communication | `False` |
|`keycloak_infinispan_trust_store_path`| Path to truststore with infinispan server certificate | `/etc/pki/java/cacerts` |
|`keycloak_infinispan_trust_store_password`| Password for opening truststore | `changeit` |
The following variables are _required_ only when `keycloak_db_enabled` is True:
@@ -143,46 +137,20 @@ The following variables are _required_ only when `keycloak_db_enabled` is True:
|`keycloak_db_pass` | password for connecting to postgres | `keycloak-pass` |
Example Playbooks
Example Playbook
-----------------
_NOTE_: use ansible vaults or other security systems for storing credentials.
* The following is an example playbook that makes use of the role to install keycloak from remote:
```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"
```
* The following is an example playbook that makes use of the role to install Red Hat Single Sign-On from RHN:
```yaml
---
- name: Playbook for RHSSO
hosts: keycloak
collections:
- middleware_automation.redhat_csp_download
roles:
- redhat_csp_download
tasks:
- name: Keycloak Role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
rhn_username: '<customer portal username>'
rhn_password: '<customer portal password>'
roles:
- middleware_automation.keycloak.keycloak
```
@@ -198,49 +166,11 @@ _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
```
* This playbook installs Red Hat Single Sign-On from an alternate url:
```yaml
---
- hosts: keycloak
collections:
- middleware_automation.keycloak
tasks:
- name: Keycloak Role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
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:
```yaml
---
- hosts: keycloak
collections:
- middleware_automation.keycloak
tasks:
- name: Keycloak Role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
keycloak_rhsso_enable: True
keycloak_offline_install: True
# This should be the filename of rhsso zip file on Ansible node: rh-sso-7.5-server-dist.zip
```
License
-------

View File

@@ -1,37 +1,34 @@
---
### Configuration specific to keycloak
keycloak_version: 15.0.2
keycloak_archive: "keycloak-{{ keycloak_version }}.zip"
keycloak_download_url: "https://github.com/keycloak/keycloak/releases/download/{{ keycloak_version }}/{{ keycloak_archive }}"
keycloak_version: 18.0.2
keycloak_archive: "keycloak-legacy-{{ keycloak_version }}.zip"
keycloak_download_url: "https://github.com/keycloak/keycloak/releases/download/{{ keycloak_version }}/{{ keycloak_archive }}"
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
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 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 }}"
# whether to install from local archive; filename must be keycloak_archive or keycloak_rhsso_archive depending on keycloak_rhsso_enable
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_jboss_home: "{{ 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_service_name: keycloak
keycloak_service_desc: Keycloak
keycloak_service_start_delay: 10
keycloak_service_start_retries: 25
keycloak_configure_firewalld: False
### administrator console password
keycloak_admin_password: ''
### Common configuration settings
keycloak_bind_address: 0.0.0.0
keycloak_host: localhost
@@ -39,6 +36,7 @@ keycloak_http_port: 8080
keycloak_https_port: 8443
keycloak_ajp_port: 8009
keycloak_jgroups_port: 7600
keycloak_management_port_bind_address: 127.0.0.1
keycloak_management_http_port: 9990
keycloak_management_https_port: 9993
keycloak_java_opts: "-Xms1024m -Xmx2048m"
@@ -58,17 +56,19 @@ 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
infinispan_pass: supervisor
infinispan_url: localhost
infinispan_sasl_mechanism: SCRAM-SHA-512
infinispan_use_ssl: False
keycloak_infinispan_user: supervisor
keycloak_infinispan_pass: supervisor
keycloak_infinispan_url: localhost
keycloak_infinispan_sasl_mechanism: SCRAM-SHA-512
keycloak_infinispan_use_ssl: False
# if ssl is enabled, import ispn server certificate here
infinispan_trust_store_path: /etc/pki/java/cacerts
infinispan_trust_store_password: changeit
keycloak_infinispan_trust_store_path: /etc/pki/java/cacerts
keycloak_infinispan_trust_store_password: changeit
### database backend engine: values [ 'postgres', 'mariadb' ]
keycloak_jdbc_engine: postgres
@@ -85,3 +85,5 @@ keycloak_default_jdbc:
mariadb:
url: 'jdbc:mariadb://localhost:3306/keycloak'
version: 2.7.4
# role specific vars
keycloak_no_log: True

View File

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

View File

@@ -3,12 +3,12 @@ argument_specs:
options:
keycloak_version:
# line 3 of keycloak/defaults/main.yml
default: "15.0.2"
default: "18.0.2"
description: "keycloak.org package version"
type: "str"
keycloak_archive:
# line 4 of keycloak/defaults/main.yml
default: "keycloak-{{ keycloak_version }}.zip"
default: "keycloak-legacy-{{ keycloak_version }}.zip"
description: "keycloak install archive filename"
type: "str"
keycloak_configure_firewalld:
@@ -31,56 +31,19 @@ argument_specs:
default: "{{ keycloak_dest }}/keycloak-{{ keycloak_version }}"
description: "Installation path"
type: "str"
keycloak_rhsso_version:
# line 10 of keycloak/defaults/main.yml
default: "7.5.0"
description: "Red Hat Single Sign-On version"
type: "str"
rhsso_rhn_id:
# line 11 of keycloak/defaults/main.yml
default: "{{ rhsso_rhn_ids[keycloak_rhsso_version].id }}"
description: "Customer Portal product ID for Red Hat SSO"
type: "str"
keycloak_rhsso_archive:
# line 12 of keycloak/defaults/main.yml
default: "rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip"
description: "ed Hat SSO install archive filename"
type: "str"
keycloak_rhsso_apply_patches:
# line 16 of keycloak/defaults/main.yml
default: true
description: "Install RHSSO more recent cumulative patch"
type: "bool"
keycloak_rhsso_installdir:
# line 13 of keycloak/defaults/main.yml
default: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version | regex_replace('^([0-9])\\.([0-9]*).*', '\\1.\\2') }}"
description: "Installation path for Red Hat SSO"
type: "str"
keycloak_rhn_url:
# line 14 of keycloak/defaults/main.yml
default: "https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId="
description: "Base download URI for customer portal"
type: "str"
keycloak_rhsso_download_url:
# line 15 of keycloak/defaults/main.yml
default: "{{ keycloak_rhn_url }}{{ rhsso_rhn_id }}"
description: "Full download URI for Red Hat SSO"
type: "str"
keycloak_rhsso_enable:
# line 18 of keycloak/defaults/main.yml
default: "{{ True if rhsso_rhn_id is defined and rhn_username is defined and rhn_password is defined else False }}"
description: "Enable Red Hat Single Sign-on installation"
type: "str"
keycloak_offline_install:
# line 20 of keycloak/defaults/main.yml
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"
@@ -88,7 +51,7 @@ argument_specs:
type: "str"
keycloak_jboss_home:
# line 25 of keycloak/defaults/main.yml
default: "{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}"
default: "{{ keycloak_installdir }}"
description: "Installation work directory"
type: "str"
keycloak_config_dir:
@@ -106,6 +69,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"
@@ -126,6 +94,10 @@ argument_specs:
default: "0.0.0.0"
description: "Address for binding service ports"
type: "str"
keycloak_management_port_bind_address:
default: "127.0.0.1"
description: "Address for binding the managemnt ports"
type: "str"
keycloak_host:
# line 35 of keycloak/defaults/main.yml
default: "localhost"
@@ -211,37 +183,37 @@ argument_specs:
default: "http://localhost"
description: "Frontend URL for keycloak endpoints when a reverse proxy is used"
type: "str"
infinispan_user:
keycloak_infinispan_user:
# line 62 of keycloak/defaults/main.yml
default: "supervisor"
description: "Username for connecting to infinispan"
type: "str"
infinispan_pass:
keycloak_infinispan_pass:
# line 63 of keycloak/defaults/main.yml
default: "supervisor"
description: "Password for connecting to infinispan"
type: "str"
infinispan_url:
keycloak_infinispan_url:
# line 64 of keycloak/defaults/main.yml
default: "localhost"
description: "URL for the infinispan remote-cache server"
type: "str"
infinispan_sasl_mechanism:
keycloak_infinispan_sasl_mechanism:
# line 65 of keycloak/defaults/main.yml
default: "SCRAM-SHA-512"
description: "Authentication type to infinispan server"
type: "str"
infinispan_use_ssl:
keycloak_infinispan_use_ssl:
# line 66 of keycloak/defaults/main.yml
default: false
description: "Enable hotrod client TLS communication"
type: "bool"
infinispan_trust_store_path:
keycloak_infinispan_trust_store_path:
# line 68 of keycloak/defaults/main.yml
default: "/etc/pki/java/cacerts"
description: "TODO document argument"
type: "str"
infinispan_trust_store_password:
keycloak_infinispan_trust_store_password:
# line 69 of keycloak/defaults/main.yml
default: "changeit"
description: "Path to truststore containing infinispan server certificate"
@@ -286,3 +258,85 @@ argument_specs:
default: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
description: "URL for management console rest calls"
type: "str"
keycloak_service_name:
default: "keycloak"
description: "systemd service name for keycloak"
type: "str"
keycloak_service_desc:
default: "Keycloak"
description: "systemd description for keycloak"
type: "str"
keycloak_service_start_delay:
default: "10"
description: "Expected delay in ms before the service is expected to be available after start."
type: "int"
keycloak_service_start_retries:
default: "25"
description: "How many time should Ansible retry to connect to the service after it was started, before failing."
type: "int"
keycloak_no_log:
default: true
type: "bool"
description: "Changes default behavior for no_log for debugging purpose, do not change for production system."
downstream:
options:
sso_version:
default: "7.6.0"
description: "Red Hat Single Sign-On version"
type: "str"
sso_rhn_id:
default: "104539"
description: "Customer Portal product ID for Red Hat SSO"
type: "str"
sso_archive:
default: "rh-sso-{{ sso_version }}-server-dist.zip"
description: "Red Hat SSO install archive filename"
type: "str"
sso_dest:
default: "/opt/sso"
description: "Root installation directory"
type: "str"
sso_installdir:
default: "{{ sso_dest }}/rh-sso-{{ sso_version.split('.')[0] }}.{{ sso_version.split('.')[1] }}"
description: "Installation path for Red Hat SSO"
type: "str"
sso_rhn_url:
default: 'https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId='
description: "Base download URI for customer portal"
type: "str"
sso_download_url:
default: "{{ sso_rhn_url }}{{ sso_rhn_id }}"
description: "Full download URI for Red Hat SSO"
type: "str"
sso_apply_patches:
default: False
description: "Install Red Hat SSO most recent cumulative patch"
type: "bool"
sso_enable:
default: True
description: "Enable Red Hat Single Sign-on installation"
type: "str"
sso_offline_install:
default: True
description: "Perform an offline install"
type: "bool"
sso_service_name:
default: "sso"
description: "systemd service name for Single Sign-On"
type: "str"
sso_service_desc:
default: "Red Hat Single Sign-On"
description: "systemd description for Red Hat Single Sign-On"
type: "str"
sso_patch_version:
default: "7.6.1"
description: "Red Hat Single Sign-On latest cumulative patch version"
type: "str"
sso_patch_bundle:
default: "rh-sso-{{ sso_patch_version }}-patch.zip"
description: "Red Hat SSO patch archive filename"
type: "str"
sso_patch_rhn_id:
default: "104867"
description: "Customer Portal product ID for Red Hat SSO latest cumulative patch"
type: "str"

View File

@@ -1,13 +1,12 @@
---
collections:
- middleware_automation.redhat_csp_download
- middleware_automation.wildfly
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 +22,7 @@ galaxy_info:
- keycloak
- redhat
- rhel
- rhn
- sso
- sso
- authentication
- identity
- security

View File

@@ -0,0 +1,20 @@
---
- name: Check packages to be installed
block:
- name: "Check if packages are already installed" # noqa command-instead-of-module this runs faster
ansible.builtin.command: "rpm -q {{ packages_list | join(' ') }}"
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,9 +12,9 @@
enabled: yes
state: started
- name: Configure firewall for keycloak ports
- name: "Configure firewall for {{ keycloak.service_name }} ports"
become: yes
firewalld:
ansible.posix.firewalld:
port: "{{ item }}"
permanent: true
state: enabled

View File

@@ -16,26 +16,27 @@
path: "{{ keycloak_jboss_home }}"
register: existing_deploy
- block:
- name: Stop the old keycloak service
- name: Stop and restart if existing deployment exists and install forced
when: existing_deploy.stat.exists and keycloak_force_install | bool
block:
- 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 +44,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 +59,7 @@
archive: "{{ keycloak_dest }}/{{ keycloak.bundle }}"
- name: Check download archive path
become: yes
ansible.builtin.stat:
path: "{{ archive }}"
register: archive_path
@@ -70,15 +72,16 @@
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: 0644
delegate_to: localhost
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- not keycloak_rhsso_enable
- not sso_enable is defined or not sso_enable
- not keycloak_offline_install
- name: Perform download from RHN
@@ -93,22 +96,23 @@
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- keycloak_rhsso_enable
- sso_enable is defined and sso_enable
- not keycloak_offline_install
- keycloak_rhn_url in keycloak_rhsso_download_url
- keycloak_rhn_url in keycloak_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: 0644
delegate_to: localhost
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- keycloak_rhsso_enable
- sso_enable is defined and sso_enable
- not keycloak_offline_install
- not keycloak_rhn_url in keycloak_rhsso_download_url
- not keycloak_rhn_url in keycloak_download_url
- name: Check downloaded archive
ansible.builtin.stat:
@@ -123,7 +127,7 @@
dest: "{{ archive }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
mode: 0640
register: new_version_downloaded
when:
- not archive_path.stat.exists
@@ -137,7 +141,7 @@
register: path_to_workdir
become: yes
- name: "Extract {{ 'Red Hat Single Sign-On' if keycloak_rhsso_enable else 'Keycloak' }} archive on target"
- name: "Extract {{ keycloak_service_desc }} archive on target"
ansible.builtin.unarchive:
remote_src: yes
src: "{{ archive }}"
@@ -168,29 +172,20 @@
# driver and configuration
- name: "Install {{ keycloak_jdbc_engine }} driver"
ansible.builtin.include_role:
name: middleware_automation.wildfly.wildfly_driver
vars:
wildfly_user: "{{ keycloak_service_user }}"
jdbc_driver_module_dir: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}"
jdbc_driver_version: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_version }}"
jdbc_driver_jar_filename: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_filename }}"
jdbc_driver_jar_url: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_url }}"
jdbc_driver_jar_installation_path: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}/{{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_filename }}"
jdbc_driver_module_name: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}"
ansible.builtin.include_tasks: jdbc_driver.yml
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

@@ -0,0 +1,36 @@
---
- name: "Check module directory: {{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}"
ansible.builtin.stat:
path: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}"
register: dest_path
become: yes
- name: "Set up module dir for JDBC Driver {{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}"
ansible.builtin.file:
path: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}"
state: directory
recurse: yes
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
become: yes
when:
- not dest_path.stat.exists
- name: "Retrieve JDBC Driver from {{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_url }}"
ansible.builtin.get_url:
url: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_url }}"
dest: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}/{{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_filename }}"
group: "{{ keycloak_service_group }}"
owner: "{{ keycloak_service_user }}"
mode: 0640
become: yes
- name: "Deploy module.xml for JDBC Driver"
ansible.builtin.template:
src: "templates/jdbc_driver_module.xml.j2"
dest: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}/module.xml"
group: "{{ keycloak_service_group }}"
owner: "{{ keycloak_service_user }}"
mode: 0640
become: yes

View File

@@ -24,7 +24,9 @@
- name: Include patch install tasks
ansible.builtin.include_tasks: rhsso_patch.yml
when: keycloak_rhsso_apply_patches and keycloak_rhsso_enable
when:
- sso_apply_patches is defined and sso_apply_patches
- sso_enable is defined and sso_enable
tags:
- install
- patch
@@ -34,9 +36,11 @@
state: link
src: "{{ keycloak_jboss_home }}/standalone/log"
dest: /var/log/keycloak
become: yes
- block:
- name: Check admin credentials by generating a token
- name: Set admin credentials and restart if not already created
block:
- 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:
@@ -10,21 +18,29 @@
- 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
- (rhn_username is defined and sso_enable is defined and sso_enable) or not sso_enable is defined or not sso_enable or keycloak_offline_install
- (rhn_password is defined and sso_enable is defined and sso_enable) or not sso_enable is defined or not sso_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' }}"
success_msg: "Installing {{ keycloak_service_desc }}"
- 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,7 +1,27 @@
---
- name: "Restart and enable keycloack service"
- name: "Restart and enable {{ keycloak.service_name }} service"
ansible.builtin.systemd:
name: keycloak
enabled: yes
state: restarted
become: yes
delegate_to: "{{ ansible_play_hosts | first }}"
run_once: True
- 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
delegate_to: "{{ ansible_play_hosts | first }}"
run_once: True
retries: "{{ keycloak_service_start_retries }}"
delay: "{{ keycloak_service_start_delay }}"
- name: "Restart and enable {{ keycloak.service_name }} service"
ansible.builtin.systemd:
name: keycloak
enabled: yes
state: restarted
become: yes
when: inventory_hostname != ansible_play_hosts | first

View File

@@ -2,7 +2,7 @@
## check remote patch archive
- name: Set download patch archive path
ansible.builtin.set_fact:
patch_archive: "{{ keycloak_dest }}/{{ keycloak.patch_bundle }}"
patch_archive: "{{ keycloak_dest }}/{{ sso_patch_bundle }}"
- name: Check download patch archive path
ansible.builtin.stat:
@@ -11,8 +11,8 @@
- name: Perform download from RHN
middleware_automation.redhat_csp_download.redhat_csp_download:
url: "{{ keycloak_rhn_url }}{{ rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.id }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.patch_bundle }}"
url: "{{ keycloak_rhn_url }}{{ sso_patch_rhn_id }}"
dest: "{{ local_path.stat.path }}/{{ sso_patch_bundle }}"
username: "{{ rhn_username }}"
password: "{{ rhn_password }}"
no_log: "{{ omit_rhn_output | default(true) }}"
@@ -21,17 +21,17 @@
- patch_archive_path is defined
- patch_archive_path.stat is defined
- not patch_archive_path.stat.exists
- keycloak_rhsso_enable
- sso_enable is defined and sso_enable
- not keycloak_offline_install
## copy and unpack
- name: Copy patch archive to target nodes
ansible.builtin.copy:
src: "{{ local_path.stat.path }}/{{ keycloak.patch_bundle }}"
src: "{{ local_path.stat.path }}/{{ sso_patch_bundle }}"
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
@@ -48,9 +48,9 @@
when:
- cli_result is defined
- cli_result.stdout is defined
- rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.v not in cli_result.stdout
- sso_patch_version not in cli_result.stdout
block:
- name: "Apply patch {{ rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.v }} to server"
- name: "Apply patch {{ sso_patch_version }} to server"
ansible.builtin.include_tasks: rhsso_cli.yml
vars:
query: "patch apply {{ patch_archive }}"
@@ -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
@@ -78,10 +78,10 @@
- name: "Verify installed patch version"
ansible.builtin.assert:
that:
- rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.v not in cli_result.stdout
- sso_patch_version not in cli_result.stdout
fail_msg: "Patch installation failed"
success_msg: "Patch installation successful"
- name: "Skipping patch"
debug:
msg: "Latest cumulative patch {{ rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.v }} already installed, skipping patch installation."
ansible.builtin.debug:
msg: "Latest cumulative patch {{ sso_patch_version }} already installed, skipping patch installation."

View File

@@ -1,15 +1,15 @@
---
- 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
until: keycloak_status.status == 200
retries: 25
delay: 10
retries: "{{ keycloak_service_start_retries }}"
delay: "{{ keycloak_service_start_delay }}"

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

@@ -0,0 +1,761 @@
<?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.clustering.jgroups"/>
<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>
<logger category="org.keycloak.cluster.infinispan">
<level name="DEBUG"/>
</logger>
<logger category="org.keycloak.connections.infinispan">
<level name="DEBUG"/>
</logger>
<logger category="org.keycloak.models.cache.infinispan">
<level name="DEBUG"/>
</logger>
<logger category="org.keycloak.models.sessions.infinispan">
<level name="DEBUG"/>
</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/ExampleDS" pool-name="ExampleDS" 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>
<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}}">
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<connection-url>{{ keycloak_jdbc[keycloak_jdbc_engine].connection_url }}</connection-url>
<driver>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}</driver>
<pool>
<max-pool-size>20</max-pool-size>
</pool>
<security>
<user-name>{{ keycloak_jdbc[keycloak_jdbc_engine].db_user }}</user-name>
<password>{{ keycloak_jdbc[keycloak_jdbc_engine].db_password }}</password>
</security>
{% else %}
<connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
{% endif %}
</datasource>
<drivers>
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<driver name="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}" module="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}">
<driver-class>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_class }}</driver-class>
<xa-datasource-class>{{ keycloak_jdbc[keycloak_jdbc_engine].xa_datasource_class }}</xa-datasource-class>
</driver>
{% endif %}
<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/ExampleDS" 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="distributable" 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="dist" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan">
<transport lock-timeout="60000"/>
<distributed-cache name="dist">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan">
<transport lock-timeout="60000"/>
<local-cache name="realms">
<heap-memory size="10000"/>
</local-cache>
<local-cache name="users">
<heap-memory size="10000"/>
</local-cache>
{% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens", "authenticationSessions" ] %}
<distributed-cache name="{{ cachename }}">
<remote-store cache="{{ cachename }}"
remote-servers="remote-cache"
passivation="false"
fetch-state="false"
purge="false"
preload="false"
shared="true">
<property name="rawValues">true</property>
<property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
<property name="remoteStoreSecurityEnabled">false</property>
<property name="infinispan.client.hotrod.auth_username">{{ keycloak_remotecache.username }}</property>
<property name="infinispan.client.hotrod.auth_password">{{ keycloak_remotecache.password }}</property>
<property name="infinispan.client.hotrod.auth_realm">{{ keycloak_remotecache.realm | default('default') }}</property>
<property name="infinispan.client.hotrod.auth_server_name">{{ keycloak_remotecache.server_name }}</property>
<property name="infinispan.client.hotrod.sasl_mechanism">{{ keycloak_remotecache.sasl_mechanism }}</property>
<property name="infinispan.client.hotrod.use_ssl">{{ keycloak_remotecache.use_ssl }}</property>
<property name="infinispan.client.hotrod.trust_store_file_name">{{ keycloak_remotecache.trust_store_path }}</property>
<property name="infinispan.client.hotrod.trust_store_type">JKS</property>
<property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password }}</property>
<property name="infinispan.client.hotrod.client_intelligence">TOPOLOGY_AWARE</property>
</remote-store>
</distributed-cache>
{% endfor %}
<replicated-cache name="work">
<remote-store cache="work"
remote-servers="remote-cache"
passivation="false"
fetch-state="false"
purge="false"
preload="false"
shared="true">
<property name="rawValues">true</property>
<property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
<property name="remoteStoreSecurityEnabled">false</property>
<property name="infinispan.client.hotrod.auth_username">{{ keycloak_remotecache.username }}</property>
<property name="infinispan.client.hotrod.auth_password">{{ keycloak_remotecache.password }}</property>
<property name="infinispan.client.hotrod.auth_realm">{{ keycloak_remotecache.realm | default('default') }}</property>
<property name="infinispan.client.hotrod.auth_server_name">{{ keycloak_remotecache.server_name }}</property>
<property name="infinispan.client.hotrod.sasl_mechanism">{{ keycloak_remotecache.sasl_mechanism }}</property>
<property name="infinispan.client.hotrod.use_ssl">{{ keycloak_remotecache.use_ssl }}</property>
<property name="infinispan.client.hotrod.trust_store_file_name">{{ keycloak_remotecache.trust_store_path }}</property>
<property name="infinispan.client.hotrod.trust_store_type">JKS</property>
<property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password }}</property>
<property name="infinispan.client.hotrod.client_intelligence">TOPOLOGY_AWARE</property>
</remote-store>
</replicated-cache>
<local-cache name="authorization">
<heap-memory size="10000"/>
</local-cache>
<local-cache name="keys">
<heap-memory size="1000"/>
<expiration max-idle="3600000"/>
</local-cache>
</cache-container>
<cache-container name="server" default-cache="default" aliases="singleton cluster" modules="org.wildfly.clustering.server">
<transport lock-timeout="60000"/>
<replicated-cache name="default">
<transaction mode="BATCH"/>
</replicated-cache>
</cache-container>
<cache-container name="web" default-cache="dist" modules="org.wildfly.clustering.web.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="sso">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
</replicated-cache>
<distributed-cache name="dist">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
<file-store/>
</distributed-cache>
<distributed-cache name="routing"/>
</cache-container>
<cache-container name="hibernate" modules="org.infinispan.hibernate-cache">
<transport lock-timeout="60000"/>
<local-cache name="local-query">
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<invalidation-cache name="entity">
<transaction mode="NON_XA"/>
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</invalidation-cache>
<replicated-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:jgroups:8.0">
<channels default="ee">
<channel name="ee" stack="tcp" cluster="ejb"/>
</channels>
<stacks>
<stack name="tcp">
<transport site="${jboss.node.name}" type="TCP" socket-binding="jgroups-tcp"/>
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<protocol type="JDBC_PING">
<property name="datasource_jndi_name">java:jboss/datasources/KeycloakDS</property>
<property name="initialize_sql">{{ keycloak_jdbc[keycloak_jdbc_engine].initialize_db }}</property>
<property name="insert_single_sql">INSERT INTO JGROUPSPING (own_addr, cluster_name, ping_data) values (?, ?, ?)</property>
<property name="delete_single_sql">DELETE FROM JGROUPSPING WHERE own_addr=? AND cluster_name=?</property>
<property name="select_all_pingdata_sql">SELECT ping_data FROM JGROUPSPING WHERE cluster_name=?</property>
</protocol>
{% endif %}
<protocol type="MERGE3"/>
<protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST3"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS">
<property name="join_timeout">30000</property>
</protocol>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
</stack>
</stacks>
</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>
{% if keycloak_ha_enabled %}
<spi name="dblock">
<provider name="jpa" enabled="true">
<properties>
<property name="lockWaitTimeout" value="900"/>
</properties>
</provider>
</spi>
{% endif %}
<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}"/>
{% if keycloak_modcluster.enabled %}
<subsystem xmlns="urn:jboss:domain:modcluster:5.0">
<proxy name="default" advertise="false" listener="ajp" proxies="proxy1">
<dynamic-load-provider>
<load-metric type="cpu"/>
</dynamic-load-provider>
</proxy>
</subsystem>
{% endif %}
<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="{{ inventory_hostname | default('${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">
<ajp-listener name="ajp" socket-binding="ajp"/>
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" proxy-address-forwarding="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<http-invoker security-realm="ApplicationRealm"/>
<filter-ref name="proxy-peer"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<filters>
<filter name="proxy-peer" module="io.undertow.core"
class-name="io.undertow.server.handlers.ProxyPeerAddressHandler"/>
</filters>
</subsystem>
<subsystem xmlns="urn:jboss:domain:weld:4.0"/>
</profile>
<interfaces>
<interface name="management">
<inet-address value="{{ keycloak_management_port_bind_address }}"/>
</interface>
<interface name="jgroups">
{% if ansible_default_ipv4 is defined %}
<subnet-match value="{{ (ansible_default_ipv4.network + '/' + ansible_default_ipv4.netmask) | ipaddr('net') }}"/>
{% else %}
<any-address />
{% endif %}
</interface>
<interface name="public">
<inet-address value="{{ keycloak_bind_address }}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="ajp" port="{{ keycloak_ajp_port }}"/>
<socket-binding name="http" port="{{ keycloak_http_port }}"/>
<socket-binding name="https" port="{{ keycloak_https_port }}"/>
<socket-binding name="management-http" interface="management" port="{{ keycloak_management_http_port }}"/>
<socket-binding name="management-https" interface="management" port="{{ keycloak_management_https_port }}"/>
<socket-binding name="jgroups-tcp" interface="jgroups" port="{{ keycloak_jgroups_port }}"/>
<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>
{% if keycloak_modcluster.enabled %}
<outbound-socket-binding name="proxy1">
<remote-destination host="{{ keycloak_modcluster.reverse_proxy_url | default('localhost') }}" port="6666"/>
</outbound-socket-binding>
{% endif %}
<outbound-socket-binding name="remote-cache">
<remote-destination host="{{ keycloak_remotecache.server_name | default('localhost') }}" port="${remote.cache.port:11222}"/>
</outbound-socket-binding>
</socket-binding-group>
</server>

View File

@@ -0,0 +1,658 @@
<?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/ExampleDS" pool-name="ExampleDS" 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>
<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}}">
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<connection-url>{{ keycloak_jdbc[keycloak_jdbc_engine].connection_url }}</connection-url>
<driver>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}</driver>
<pool>
<max-pool-size>20</max-pool-size>
</pool>
<security>
<user-name>{{ keycloak_jdbc[keycloak_jdbc_engine].db_user }}</user-name>
<password>{{ keycloak_jdbc[keycloak_jdbc_engine].db_password }}</password>
</security>
{% else %}
<connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
{% endif %}
</datasource>
<drivers>
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<driver name="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}" module="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}">
<driver-class>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_class }}</driver-class>
<xa-datasource-class>{{ keycloak_jdbc[keycloak_jdbc_engine].xa_datasource_class }}</xa-datasource-class>
</driver>
{% endif %}
<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/ExampleDS" 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>
{% if keycloak_ha_enabled %}
<spi name="dblock">
<provider name="jpa" enabled="true">
<properties>
<property name="lockWaitTimeout" value="900"/>
</properties>
</provider>
</spi>
{% endif %}
<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}"/>
{% if keycloak_modcluster.enabled %}
<subsystem xmlns="urn:jboss:domain:modcluster:5.0">
<proxy name="default" advertise="false" listener="ajp" proxies="proxy1">
<dynamic-load-provider>
<load-metric type="cpu"/>
</dynamic-load-provider>
</proxy>
</subsystem>
{% endif %}
<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">
<ajp-listener name="ajp" socket-binding="ajp"/>
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<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="{{ keycloak_management_port_bind_address }}"/>
</interface>
<interface name="public">
<inet-address value="{{ keycloak_bind_address }}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="ajp" port="{{ keycloak_ajp_port }}"/>
<socket-binding name="http" port="{{ keycloak_http_port }}"/>
<socket-binding name="https" port="{{ keycloak_https_port }}"/>
<socket-binding name="management-http" interface="management" port="{{ keycloak_management_http_port }}"/>
<socket-binding name="management-https" interface="management" port="{{ keycloak_management_https_port }}"/>
<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>
{% if keycloak_modcluster.enabled %}
<outbound-socket-binding name="proxy1">
<remote-destination host="{{ keycloak_modcluster.reverse_proxy_url | default('localhost') }}" port="6666"/>
</outbound-socket-binding>
{% endif %}
</socket-binding-group>
</server>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}">
<resources>
<resource-root path="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_jar_filename }}"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>

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

@@ -16,7 +16,6 @@
<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"/>
@@ -31,31 +30,6 @@
<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"/>
@@ -70,8 +44,8 @@
</logger>
</audit-log>
<management-interfaces>
<http-interface security-realm="ManagementRealm">
<http-upgrade enabled="true"/>
<http-interface http-authentication-factory="management-http-authentication">
<http-upgrade enabled="true" sasl-authentication-factory="management-sasl-authentication"/>
<socket-binding http="management-http"/>
</http-interface>
</management-interfaces>
@@ -244,6 +218,9 @@
</thread-pool>
</thread-pools>
<default-security-domain value="other"/>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
<default-missing-method-permissions-deny-access value="true"/>
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/>
@@ -317,6 +294,13 @@
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<http-authentication-factory name="application-http-authentication" security-domain="ApplicationDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="BASIC">
<mechanism-realm realm-name="ApplicationRealm"/>
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<provider-http-server-mechanism-factory name="global"/>
</http>
<sasl>
@@ -644,41 +628,9 @@
<remote-naming/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:remoting:4.0">
<http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
<http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-sasl-authentication"/>
</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>
@@ -701,10 +653,10 @@
<server name="default-server">
<ajp-listener name="ajp" socket-binding="ajp"/>
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" proxy-address-forwarding="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<https-listener name="https" socket-binding="https" ssl-context="applicationSSC" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<http-invoker security-realm="ApplicationRealm"/>
<http-invoker http-authentication-factory="application-http-authentication"/>
<filter-ref name="proxy-peer"/>
</host>
</server>
@@ -715,6 +667,9 @@
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
<filters>
<filter name="proxy-peer" module="io.undertow.core"
class-name="io.undertow.server.handlers.ProxyPeerAddressHandler"/>
@@ -724,7 +679,7 @@
</profile>
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
<inet-address value="{{ keycloak_management_port_bind_address }}"/>
</interface>
<interface name="jgroups">
{% if ansible_default_ipv4 is defined %}
@@ -734,7 +689,7 @@
{% endif %}
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
<inet-address value="{{ keycloak_bind_address }}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">

View File

@@ -15,7 +15,6 @@
<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"/>
@@ -30,31 +29,6 @@
<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"/>
@@ -69,8 +43,8 @@
</logger>
</audit-log>
<management-interfaces>
<http-interface security-realm="ManagementRealm">
<http-upgrade enabled="true"/>
<http-interface http-authentication-factory="management-http-authentication">
<http-upgrade enabled="true" sasl-authentication-factory="management-sasl-authentication"/>
<socket-binding http="management-http"/>
</http-interface>
</management-interfaces>
@@ -231,6 +205,9 @@
</thread-pool>
</thread-pools>
<default-security-domain value="other"/>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
<default-missing-method-permissions-deny-access value="true"/>
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/>
@@ -304,6 +281,13 @@
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<http-authentication-factory name="application-http-authentication" security-domain="ApplicationDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="BASIC">
<mechanism-realm realm-name="ApplicationRealm"/>
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<provider-http-server-mechanism-factory name="global"/>
</http>
<sasl>
@@ -557,41 +541,9 @@
<remote-naming/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:remoting:4.0">
<http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
<http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-sasl-authentication"/>
</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>
@@ -614,10 +566,10 @@
<server name="default-server">
<ajp-listener name="ajp" socket-binding="ajp"/>
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<https-listener name="https" socket-binding="https" ssl-context="applicationSSC" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<http-invoker security-realm="ApplicationRealm"/>
<http-invoker http-authentication-factory="application-http-authentication"/>
</host>
</server>
<servlet-container name="default">
@@ -627,15 +579,18 @@
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
</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}"/>
<inet-address value="{{ keycloak_management_port_bind_address }}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
<inet-address value="{{ keycloak_bind_address }}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">

View File

@@ -1,15 +1,5 @@
---
# required variables for keycloak
# administrator console password
keycloak_admin_password:
# internal variables below
rhsso_rhn_ids:
'7.5.0':
id: '101971'
latest_cp:
id: '103836'
v: '7.5.1'
# locations
keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
@@ -19,11 +9,11 @@ keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http
keycloak:
home: "{{ keycloak_jboss_home }}"
config_dir: "{{ keycloak_config_dir }}"
bundle: "{{ keycloak_rhsso_archive if keycloak_rhsso_enable else keycloak_archive }}"
patch_bundle: "rh-sso-{{ rhsso_rhn_ids[keycloak_rhsso_version].latest_cp.v }}-patch.zip"
service_name: "{{ 'rhsso' if keycloak_rhsso_enable else 'keycloak' }}"
bundle: "{{ keycloak_archive }}"
service_name: "{{ keycloak_service_name }}"
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:
@@ -56,7 +46,7 @@ keycloak_jdbc:
driver_jar_filename: "mariadb-java-client-{{ keycloak_jdbc_driver_version }}.jar"
driver_jar_url: "https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/{{ keycloak_jdbc_driver_version }}/mariadb-java-client-{{ keycloak_jdbc_driver_version }}.jar"
connection_url: "{{ keycloak_jdbc_url }}"
db_user: "{{ keycloak_db_user }}"
db_user: "{{ keycloak_db_user }}"
db_password: "{{ keycloak_db_pass }}"
initialize_db: >
CREATE TABLE IF NOT EXISTS JGROUPSPING (
@@ -76,11 +66,11 @@ keycloak_modcluster:
# infinispan
keycloak_remotecache:
enabled: "{{ keycloak_ha_enabled }}"
username: "{{ infinispan_user }}"
password: "{{ infinispan_pass }}"
username: "{{ keycloak_infinispan_user }}"
password: "{{ keycloak_infinispan_pass }}"
realm: default
sasl_mechanism: "{{ infinispan_sasl_mechanism }}"
server_name: "{{ infinispan_url }}"
use_ssl: "{{ infinispan_use_ssl }}"
trust_store_path: "{{ infinispan_trust_store_path }}"
trust_store_password: "{{ infinispan_trust_store_password }}"
sasl_mechanism: "{{ keycloak_infinispan_sasl_mechanism }}"
server_name: "{{ keycloak_infinispan_url }}"
use_ssl: "{{ keycloak_infinispan_use_ssl }}"
trust_store_path: "{{ keycloak_infinispan_trust_store_path }}"
trust_store_password: "{{ keycloak_infinispan_trust_store_password }}"

View File

@@ -0,0 +1,120 @@
keycloak_quarkus
================
Install [keycloak](https://keycloak.org/) >= 17.0.0 (quarkus) server configurations.
Role Defaults
-------------
* Installation options
| Variable | Description | Default |
|:---------|:------------|:--------|
|`keycloak_quarkus_version`| keycloak.org package version | `17.0.1` |
* 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_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_java_home`| JAVA_HOME of installed JRE, leave empty for using specified keycloak_quarkus_jvm_package RPM path | `None` |
|`keycloak_quarkus_java_opts`| Additional JVM options | `-Xms1024m -Xmx2048m` |
|`keycloak_quarkus_frontend_url`| Service public URL | `http://localhost:8080/auth` |
|`keycloak_quarkus_http_relative_path` | Service context path | `auth` |
|`keycloak_quarkus_http_enabled`| Enable listener on HTTP port | `True` |
|`keycloak_quarkus_https_enabled`| Enable listener on HTTPS port | `False` |
|`keycloak_quarkus_key_file`| The file path to a private key in PEM format | `{{ keycloak.home }}/conf/server.key.pem` |
|`keycloak_quarkus_cert_file`| The file path to a server certificate or certificate chain in PEM format | `{{ keycloak.home }}/conf/server.crt.pem` |
* 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_health_enabled`| If the server should expose health check endpoints | `True` |
|`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 }}` |
|`keycloak_quarkus_log`| Enable one or more log handlers in a comma-separated list | `file` |
|`keycloak_quarkus_log_level`| The log level of the root category or a comma-separated list of individual categories and their levels | `info` |
|`keycloak_quarkus_log_file`| Set the log file path and filename relative to keycloak home | `data/log/keycloak.log` |
|`keycloak_quarkus_log_format`| Set a format specific to file log entries | `%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n` |
|`keycloak_quarkus_proxy_mode`| The proxy address forwarding mode if the server is behind a reverse proxy | `edge` |
|`keycloak_quarkus_start_dev`| Whether to start the service in development mode (start-dev) | `False` |
Role Variables
--------------
| Variable | Description | Required |
|:---------|:------------|----------|
|`keycloak_quarkus_admin_pass`| Password of console admin account | `yes` |
License
-------
Apache License 2.0
Author Information
------------------
* [Guido Grazioli](https://github.com/guidograzioli)

View File

@@ -0,0 +1,88 @@
---
### Configuration specific to keycloak
keycloak_quarkus_version: 18.0.0
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_java_home:
keycloak_quarkus_dest: /opt/keycloak
keycloak_quarkus_home: "{{ keycloak_quarkus_installdir }}"
keycloak_quarkus_config_dir: "{{ keycloak_quarkus_home }}/conf"
keycloak_quarkus_start_dev: False
keycloak_quarkus_service_user: keycloak
keycloak_quarkus_service_group: keycloak
keycloak_quarkus_service_pidfile: "/run/keycloak.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_enabled: True
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"
### TLS/HTTPS configuration
keycloak_quarkus_https_enabled: False
keycloak_quarkus_key_file: "{{ keycloak.home }}/conf/server.key.pem"
keycloak_quarkus_cert_file: "{{ keycloak.home }}/conf/server.crt.pem"
### 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
# proxy address forwarding mode if the server is behind a reverse proxy. [edge, reencrypt, passthrough]
keycloak_quarkus_proxy_mode: edge
keycloak_quarkus_metrics_enabled: False
keycloak_quarkus_health_enabled: True
### 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
### logging configuration
keycloak_quarkus_log: file
keycloak_quarkus_log_level: info
keycloak_quarkus_log_file: data/log/keycloak.log
keycloak_quarkus_log_format: '%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n'

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,250 @@
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_java_home:
description: "JAVA_HOME of installed JRE, leave empty for using specified keycloak_jvm_package RPM path"
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_enabled:
default: true
description: "Enable listener on HTTP port"
type: "bool"
keycloak_quarkus_http_port:
# line 29 of defaults/main.yml
default: 8080
description: "HTTP port"
type: "int"
keycloak_quarkus_https_enabled:
default: false
description: "Enable listener on HTTPS port"
type: "bool"
keycloak_quarkus_key_file:
default: "{{ keycloak.home }}/conf/server.key.pem"
description: "The file path to a private key in PEM format"
type: "str"
keycloak_quarkus_cert_file:
default: "{{ keycloak.home }}/conf/server.crt.pem"
description: "The file path to a server certificate or certificate chain in PEM format"
type: "str"
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_health_enabled:
default: true
description: "If the server should expose health check endpoints"
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"
keycloak_quarkus_log:
default: "file"
type: "str"
description: "Enable one or more log handlers in a comma-separated list"
keycloak_quarkus_log_level:
default: "info"
type: "str"
description: "The log level of the root category or a comma-separated list of individual categories and their levels"
keycloak_quarkus_log_file:
default: "data/log/keycloak.log"
type: "str"
description: "Set the log file path and filename relative to keycloak home"
keycloak_quarkus_log_format:
default: '%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n'
type: "str"
description: "Set a format specific to file log entries"
keycloak_quarkus_proxy_mode:
default: 'edge'
type: "str"
description: "The proxy address forwarding mode if the server is behind a reverse proxy"
keycloak_quarkus_start_dev:
default: False
type: "bool"
description: "Whether to start the service in development mode (start-dev)"

View File

@@ -0,0 +1,26 @@
---
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,20 @@
---
- name: Check packages to be installed
block:
- name: "Check if packages are already installed" # noqa command-instead-of-module this runs faster
ansible.builtin.command: "rpm -q {{ packages_list | join(' ') }}"
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 | join(',') }}"
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
ansible.posix.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 }}/bin/"
ansible.builtin.stat:
path: "{{ keycloak.home }}/bin/"
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 }}/bin/"
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
become: yes
when:
- (not path_to_workdir.stat.exists) or new_version_downloaded.changed
notify:
- restart keycloak
- name: Inform decompression was not executed
ansible.builtin.debug:
msg: "{{ keycloak.home }} already exists and version unchanged, skipping decompression"
when:
- (not new_version_downloaded.changed) and path_to_workdir.stat.exists

View File

@@ -0,0 +1,69 @@
---
# 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
become: yes
notify:
- restart keycloak
- name: "Configure quarkus config for keycloak service"
ansible.builtin.template:
src: quarkus.properties.j2
dest: "{{ keycloak.home }}/conf/quarkus.properties"
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
mode: 0644
become: yes
notify:
- restart keycloak
- name: Ensure logdirectory exists
ansible.builtin.file:
state: directory
path: "{{ keycloak.log.file | dirname }}"
owner: "{{ keycloak.service_user }}"
group: "{{ keycloak.service_group }}"
mode: 0775
become: yes
- 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
- name: Link default logs directory
ansible.builtin.file:
state: link
src: "{{ keycloak.log.file | dirname }}"
dest: /var/log/keycloak
force: yes
become: yes

View File

@@ -0,0 +1,25 @@
---
- 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: 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,40 @@
---
- name: Determine JAVA_HOME for selected JVM RPM # noqa blocked_modules
ansible.builtin.shell: |
set -o pipefail
rpm -ql {{ keycloak_quarkus_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"
become: yes
ansible.builtin.template:
src: keycloak-sysconfig.j2
dest: /etc/sysconfig/keycloak
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"
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,5 @@
# {{ ansible_managed }}
KEYCLOAK_ADMIN={{ keycloak_quarkus_admin_user }}
KEYCLOAK_ADMIN_PASSWORD='{{ keycloak_quarkus_admin_pass }}'
PATH={{ keycloak_java_home | default(keycloak_rpm_java_home, true) }}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JAVA_HOME={{ keycloak_java_home | default(keycloak_rpm_java_home, true) }}

View File

@@ -0,0 +1,47 @@
# {{ ansible_managed }}
{% if keycloak_quarkus_db_enabled %}
# Database
db={{ keycloak_quarkus_jdbc_engine }}
db-url={{ keycloak_quarkus_jdbc_url }}
db-username={{ keycloak_quarkus_db_user }}
db-password={{ keycloak_quarkus_db_pass }}
{% endif %}
# Observability
metrics-enabled={{ keycloak_quarkus_metrics_enabled }}
health-enabled={{ keycloak_quarkus_health_enabled }}
# HTTP
http-enabled={{ keycloak_quarkus_http_enabled }}
http-port={{ keycloak_quarkus_http_port }}
# HTTPS
https-port={{ keycloak_quarkus_https_port }}
{% if keycloak_quarkus_https_enabled %}
https-certificate-file={{ keycloak_quarkus_cert_file}}
https-certificate-key-file={{ keycloak_quarkus_key_file }}
{% endif %}
# Hostname for the Keycloak server.
hostname={{ keycloak_quarkus_host }}
hostname-path={{ keycloak_quarkus_http_relative_path }}
# Cluster
{% if keycloak_quarkus_ha_enabled %}
cache=ispn
cache-config-file=cache-ispn.xml
cache-stack=tcp
{% endif %}
# Proxy
proxy={{ keycloak_quarkus_proxy_mode }}
# 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
# Logging
#log-format=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n
log={{ keycloak_quarkus_log }}
log-level={{ keycloak.log.level }}
log-file={{ keycloak.log.file }}
log-file-format={{ keycloak.log.format }}

View File

@@ -0,0 +1,18 @@
# {{ ansible_managed }}
[Unit]
Description=Keycloak Server
After=network.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/keycloak
PIDFile={{ keycloak_quarkus_service_pidfile }}
{% if keycloak_quarkus_start_dev %}
ExecStart={{ keycloak.home }}/bin/kc.sh start-dev
{% else %}
ExecStart={{ keycloak.home }}/bin/kc.sh start --auto-build --log={{ keycloak_quarkus_log }}
{% endif %}
User={{ keycloak.service_user }}
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,19 @@
# {{ ansible_managed }}
{% if keycloak_quarkus_ha_enabled %}
quarkus.infinispan-client.server-list={{ keycloak_quarkus_ispn_url }}
quarkus.infinispan-client.client-intelligence=HASH_DISTRIBUTION_AWARE
quarkus.infinispan-client.use-auth=true
quarkus.infinispan-client.auth-username={{ keycloak_quarkus_ispn_user }}
quarkus.infinispan-client.auth-password={{ keycloak_quarkus_ispn_pass }}
quarkus.infinispan-client.auth-realm=default
quarkus.infinispan-client.auth-server-name=infinispan
quarkus.infinispan-client.sasl-mechanism={{ keycloak_quarkus_ispn_sasl_mechanism }}
{% if keycloak_quarkus_ispn_use_ssl %}
quarkus.infinispan-client.trust-store={{ keycloak_quarkus_ispn_trust_store_path }}
quarkus.infinispan-client.trust-store-password={{ keycloak_quarkus_ispn_trust_store_password }}
quarkus.infinispan-client.trust-store-type=jks
{% endif %}
#quarkus.infinispan-client.use-schema-registration=true
#quarkus.infinispan-client.auth-client-subject
#quarkus.infinispan-client.auth-callback-handler
{% endif %}

View File

@@ -0,0 +1,15 @@
---
keycloak:
home: "{{ keycloak_quarkus_home }}"
config_dir: "{{ keycloak_quarkus_config_dir }}"
bundle: "{{ keycloak_quarkus_archive }}"
service_name: "keycloak"
health_url: "http://{{ keycloak_quarkus_host }}:{{ keycloak_quarkus_http_port }}/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 }}"
log:
file: "{{ keycloak_quarkus_home }}/{{ keycloak_quarkus_log_file }}"
level: "{{ keycloak_quarkus_log_level }}"
format: "{{ keycloak_quarkus_log_format }}"

View File

@@ -1,20 +1,20 @@
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
-------------
| Variable | Description | Default |
|:---------|:------------|:---------|
|:---------|:------------|:--------|
|`keycloak_admin_user`| Administration console user account | `admin` |
|`keycloak_host`| hostname | `localhost` |
|`keycloak_context`| Context path for rest calls | `/auth` |
|`keycloak_http_port`| HTTP port | `8080` |
|`keycloak_https_port`| TLS HTTP port | `8443` |
|`keycloak_auth_realm`| Name of the main authentication realm | `master` |
|`keycloak_rhsso_enable`| Define service is an upstream(Keycloak) or RHSSO | `master` |
|`keycloak_management_http_port`| Management port | `9990` |
|`keycloak_auth_client`| Authentication client for configuration REST calls | `admin-cli` |
|`keycloak_client_public`| Configure a public realm client | `True` |
@@ -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:
@@ -71,6 +71,8 @@ Refer to [docs](https://docs.ansible.com/ansible/latest/collections/community/ge
```yaml
- name: <name of the client>
id: <id of the client>
client_id: <id of the client>
roles: <keycloak_client_default_roles>
realm: <name of the realm that contains the client>
public_client: <true for public, false for confidential>
@@ -78,6 +80,9 @@ Refer to [docs](https://docs.ansible.com/ansible/latest/collections/community/ge
users: <keycloak_client_users>
```
`name` and either `id` or `client_id` are required.
* `keycloak_client_users`, a list of:
```yaml

View File

@@ -4,13 +4,15 @@ keycloak_host: localhost
keycloak_http_port: 8080
keycloak_https_port: 8443
keycloak_management_http_port: 9990
keycloak_rhsso_enable: False
### Keycloak administration console user
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
@@ -21,11 +26,6 @@ argument_specs:
default: 9990
description: "Management port"
type: "int"
keycloak_rhsso_enable:
# line 7 of keycloak_realm/defaults/main.yml
default: false
description: "Enable Red Hat Single Sign-on"
type: "bool"
keycloak_admin_user:
# line 10 of keycloak_realm/defaults/main.yml
default: "admin"
@@ -91,3 +91,25 @@ argument_specs:
default: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
description: "URL for management console rest calls"
type: "str"
downstream:
options:
sso_version:
default: "7.5.0"
description: "Red Hat Single Sign-On version"
type: "str"
sso_dest:
default: "/opt/sso"
description: "Root installation directory"
type: "str"
sso_installdir:
default: "{{ sso_dest }}/rh-sso-{{ sso_version.split('.')[0] }}.{{ sso_version.split('.')[1] }}"
description: "Installation path for Red Hat SSO"
type: "str"
sso_apply_patches:
default: False
description: "Install Red Hat SSO most recent cumulative patch"
type: "bool"
sso_enable:
default: True
description: "Enable Red Hat Single Sign-on installation"
type: "str"

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,11 +1,11 @@
---
- 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
no_log: True
no_log: "{{ keycloak_no_log | default('True') }}"
register: keycloak_auth_response
until: keycloak_auth_response.status == 200
retries: 5
@@ -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,9 +25,9 @@
- 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') }}"
body: "{{ lookup('template', 'realm.json.j2') }}"
validate_certs: no
body_format: json
headers:
@@ -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 }}"
@@ -48,15 +48,26 @@
provider_type: "{{ item.provider_type | default(org.keycloak.storage.UserStorageProvider) }}"
config: "{{ item.config }}"
mappers: "{{ item.mappers | default(omit) }}"
no_log: True
no_log: "{{ keycloak_no_log | default('True') }}"
register: create_user_federation_result
loop: "{{ keycloak_user_federation | flatten }}"
when: keycloak_user_federation is defined
- name: Validate Keycloak clients
ansible.builtin.assert:
that:
- item.name is defined and item.name | length > 0
- (item.client_id is defined and item.client_id | length > 0) or (item.id is defined and item.id | length > 0)
fail_msg: "For each keycloak client, attributes `name` and either `id` or `client_id` is required"
quiet: True
loop: "{{ keycloak_clients | flatten }}"
loop_control:
label: "{{ item.name | default('unnamed client') }}"
- 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 }}"
@@ -80,7 +91,7 @@
public_client: "{{ item.public_client | default(False) }}"
protocol: "{{ item.protocol | default(omit) }}"
state: present
no_log: True
no_log: "{{ keycloak_no_log | default('True') }}"
register: create_client_result
loop: "{{ keycloak_clients | flatten }}"
when: (item.name is defined and item.client_id is defined) or (item.name is defined and item.id is defined)
@@ -97,4 +108,4 @@
loop: "{{ keycloak_clients | flatten }}"
loop_control:
loop_var: client
when: "'users' in client"
when: "'users' in client"

View File

@@ -4,10 +4,10 @@
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 }}"
state: present
loop: "{{ client.roles | flatten }}"
no_log: True
no_log: "{{ keycloak_no_log | default('True') }}"

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,12 +9,12 @@
- 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
register: keycloak_auth_response
no_log: True
no_log: "{{ keycloak_no_log | default('True') }}"
until: keycloak_auth_response.status == 200
retries: 5
delay: 2

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: