Compare commits

...

103 Commits

Author SHA1 Message Date
Guido Grazioli
0bc81cc781 chore: add build ignores / fix release tag names 2022-03-01 19:05:28 +01:00
Guido Grazioli
60c5a42ae4 Merge pull request #16 from hcherukuri/main
Bump version to 1.0.0 to satisfy Automation hub
2022-03-01 19:00:38 +01:00
Harsha Cherukuri
2073c90e1d Bump version to 1.0.0 to statisfy Automation hub 2022-03-01 12:44:09 -05:00
Harsha Cherukuri
ffd146d392 Merge pull request #15 from guidograzioli/fqcn-builtins
fix: use FQCN
2022-03-01 12:42:09 -05:00
Guido Grazioli
78f225b10c chore: reword collection tags not accepted by galaxy 2022-03-01 10:46:06 +01:00
Guido Grazioli
a043021e48 docs: add automated doc generation 2022-03-01 10:22:12 +01:00
Guido Grazioli
a0ea9c62a7 update galaxy tags 2022-02-24 17:37:31 +01:00
Guido Grazioli
b90684a44a fix: use FQCN 2022-02-24 15:00:10 +01:00
Guido Grazioli
73bbca9fc1 drop ansible-lint offline option 2022-02-16 10:47:56 +01:00
Guido Grazioli
124c8ae0ad Fix linter errors 2022-02-16 10:47:56 +01:00
Guido Grazioli
bce963923d Update lint config and paths 2022-02-16 10:47:56 +01:00
Guido Grazioli
147ee5214e add lint skip_list and molecule setup 2022-02-16 10:47:56 +01:00
Guido Grazioli
042089d100 READMEs updated by helper scripts 2022-02-16 10:47:56 +01:00
Guido Grazioli
ac62d2e43d Merge pull request #11 from guidograzioli/polish_argument_specs
document argument_specs
2022-02-10 08:41:04 +01:00
Guido Grazioli
662918f5f8 Bump version to v0.2.4 2022-02-09 15:14:56 +01:00
Guido Grazioli
e0664d53a9 fix: copy from local only if target not existing 2022-02-09 15:06:40 +01:00
Guido Grazioli
20f321c628 document argument_specs 2022-02-09 11:19:49 +01:00
Guido Grazioli
9cafd431fb fix: add missing default 2022-02-08 16:46:18 +01:00
Guido Grazioli
f74d504b53 Add roles argument_specs.yml 2022-02-08 16:28:17 +01:00
Guido Grazioli
c853df5745 fix: ci 2022-02-08 15:25:36 +01:00
Guido Grazioli
a800517422 chore: update dep on jcliff -> wildfly 2022-02-08 15:15:27 +01:00
Guido Grazioli
cbb8ed4993 Start work on 0.2.3 2022-02-01 13:29:03 +01:00
Guido Grazioli
318bb10cbc bump version 0.2.2 2022-02-01 13:28:19 +01:00
Guido Grazioli
cc6ddd3959 Merge pull request #10 from motaparthipavankumar/user-federation
User federation
2022-02-01 12:50:04 +01:00
Guido Grazioli
d3887ae9bd move client roles check out of loop 2022-02-01 09:19:26 +01:00
root
81005141c5 User federation 2022-01-31 14:16:36 -06:00
Guido Grazioli
ce6982ad51 fix: typo 2022-01-31 17:21:57 +01:00
Guido Grazioli
c2314ad068 fix: dict check for client users 2022-01-31 17:02:49 +01:00
Guido Grazioli
47751a2f39 Merge pull request #9 from guidograzioli/prerelease_0.2.0
Prerelease 0.2.0
2022-01-28 15:45:49 +01:00
Guido Grazioli
b73f187930 fix: unpack archive only if needed 2022-01-28 15:18:49 +01:00
Guido Grazioli
99c14a79da fix: prefix match for alternate url download 2022-01-28 14:46:12 +01:00
Guido Grazioli
eaea4567cf Bump to 0.2.0 2022-01-27 16:34:52 +01:00
Guido Grazioli
dbad4ea086 Update documentation 2022-01-27 16:34:06 +01:00
Guido Grazioli
c5ee73cffc gitignore locally downloaded archives 2022-01-27 15:38:04 +01:00
Guido Grazioli
6a28da3736 simplify download logic, merge remaining install tasks 2022-01-27 15:38:03 +01:00
Guido Grazioli
0f02037746 move health url fact to variables 2022-01-27 15:38:03 +01:00
Guido Grazioli
8882b36c83 fix: template ports 2022-01-27 15:38:03 +01:00
Guido Grazioli
8895bc8e1f remove unused vars, document used vars 2022-01-27 15:38:03 +01:00
Guido Grazioli
34c18888c9 add ansible_managed macro to templates 2022-01-27 15:38:03 +01:00
Guido Grazioli
906ba3c577 refactor offline install, rhsso patch install 2022-01-27 15:38:03 +01:00
Guido Grazioli
11fb2cc43b rework docs, add python requirements 2022-01-27 15:38:03 +01:00
Guido Grazioli
44f0952afe setup demo repository triggers 2022-01-27 15:38:02 +01:00
Guido Grazioli
82fb60509b Merge pull request #8 from motaparthipavankumar/create-clients-enhancement
Client Creation Enhancement
2022-01-27 15:34:55 +01:00
root
2324d4070e Addressed review comments 2022-01-27 08:17:30 -06:00
Guido Grazioli
73a98ccfa6 Start work on v0.1.9 2022-01-20 21:04:37 +01:00
Guido Grazioli
3df7a1a2e1 fix: dblock for db migration / fix: ejb dist caches 2022-01-20 20:56:49 +01:00
root
0fdd89d571 Updated keycloak_realm/tasks/manage_client_roles.yml 2022-01-19 11:41:20 -06:00
Guido Grazioli
4a28e1914e Open jgroups port in firewall 2022-01-19 17:23:42 +01:00
root
bd84d99fd1 Updated keycloak_realm/tasks/main.yml 2022-01-19 10:14:00 -06:00
root
249e1840bb Updated molecule 2022-01-19 10:14:00 -06:00
root
8da1483354 Client Creation Enhancement 2022-01-19 10:13:55 -06:00
Guido Grazioli
18e002bf27 Merge pull request #7 from motaparthipavankumar/stable
Local/Remote Source Support & User Federation Implementation
2022-01-19 17:08:28 +01:00
Pavan Kumar Motaparthi
a309f7caae Merge branch 'ansible-middleware:main' into stable 2022-01-18 17:03:54 -06:00
Pavan Kumar Motaparthi
a1f483afe9 Merge pull request #4 from motaparthipavankumar/keycloak-realm-enhancement
User Federation changes
2022-01-18 11:23:00 -06:00
Pavan Kumar Motaparthi
59618c7c0c Merge pull request #3 from motaparthipavankumar/local-source-support
Local path & source URL installation support
2022-01-18 11:22:44 -06:00
root
247d8b8a22 User Federation changes 2022-01-17 15:53:16 -06:00
root
ce26ceeed0 Code review comments 2022-01-14 13:54:10 -06:00
Pavan Kumar Motaparthi
7b376e0681 Update README.md
Co-authored-by: Andrew Block <andy.block@gmail.com>
2022-01-14 09:42:29 -06:00
Pavan Kumar Motaparthi
9113cfe886 Update README.md
Co-authored-by: Andrew Block <andy.block@gmail.com>
2022-01-14 09:42:23 -06:00
Guido Grazioli
f1eec2596d Start work on v0.1.8 2022-01-14 14:14:38 +01:00
Guido Grazioli
ff77535293 Merge pull request #6 from ansible-middleware/keycloak_update_15_0_2
Keycloak update 15 0 2
2022-01-14 11:35:23 +01:00
Guido Grazioli
d4634fcebc update new download location 2022-01-14 11:10:08 +01:00
Guido Grazioli
d7597771cf Drop service logfile, symlink log directory instead 2022-01-14 10:14:24 +01:00
Guido Grazioli
94aecfcd87 Rename/merge templates and update install task 2022-01-14 10:09:10 +01:00
Guido Grazioli
7a989f7771 Move former templates and update docs 2022-01-14 10:06:43 +01:00
Guido Grazioli
5fa9243bcd fix: keycloak_frontend_url needs scheme 2022-01-14 09:54:26 +01:00
Guido Grazioli
1b44b47d1c Revert layout for collection sanity checks 2022-01-13 20:16:44 +01:00
Guido Grazioli
8a9cb79fa4 Update CI ansible collection download path 2022-01-13 20:08:41 +01:00
Guido Grazioli
4294746263 Update molecule dependency task to force correct path 2022-01-13 17:52:21 +01:00
Guido Grazioli
bcd82a5ae5 Add variable for frontendUrl (for revproxy scenario) 2022-01-13 17:38:11 +01:00
root
ef81faefdf Download source via url 2022-01-12 09:13:53 -06:00
root
4217ba6e7f Local path installation support 2022-01-11 09:28:02 -06:00
Guido Grazioli
ead4688ce6 Start work on v0.1.7 2022-01-10 17:50:28 +01:00
Guido Grazioli
406075df89 Bump and update README 2022-01-10 17:49:23 +01:00
Guido Grazioli
26be376b5c Template preferIPv4Stack, add health check after handler 2022-01-10 17:37:14 +01:00
Guido Grazioli
3cd69821c0 Bump version, document python3 netaddr dependency 2022-01-10 14:26:54 +01:00
Guido Grazioli
eba0d84a2b Add health port to keycloak-ispn, polish templates 2022-01-10 14:21:39 +01:00
Guido Grazioli
57f2472283 Update template versions in keycloak-ispn scenario 2022-01-10 11:43:08 +01:00
Guido Grazioli
c32b95898c Fix keycloak-infinispan standalone template versions 2022-01-10 09:53:55 +01:00
Guido Grazioli
0105924ec6 Merge pull request #5 from motaparthipavankumar/main
Separate playbooks for installation and configuration
2022-01-07 17:29:43 +01:00
motaparthipavankumar
249754f5f5 Merge pull request #2 from motaparthipavankumar/enhancement
Removed anisble_hosts file & Updated README.md
2022-01-07 10:09:55 -06:00
root
c78aaece81 Removed anisble_hosts file & Updated README.md 2022-01-07 10:09:25 -06:00
motaparthipavankumar
f748cf92b0 Merge pull request #1 from motaparthipavankumar/enhancement
Separated Keycloak installation and configuration
2022-01-07 09:17:46 -06:00
root
00e6b3601b Updated README.md 2022-01-07 09:16:38 -06:00
root
4cb021fe2c Separate playbooks for installation and configuration 2022-01-07 09:16:38 -06:00
Guido Grazioli
eb849021a9 Merge pull request #4 from sabre1041/roles-path
Added roles path
2022-01-07 10:01:01 +01:00
Andrew Block
2ccfc07f5d Added roles path 2022-01-05 23:33:28 -06:00
Guido Grazioli
c7e88e7cc2 Fix broken links in top README 2022-01-05 15:53:56 +01:00
Guido Grazioli
b5d2e9e236 Start work on v0.1.4 2022-01-05 15:24:53 +01:00
Guido Grazioli
53c5ef645a Parametrize jdbc driver version 2022-01-05 13:55:19 +01:00
Guido Grazioli
967d68898a JVM as variable, name all tasks, update README 2022-01-04 16:01:37 +01:00
Guido Grazioli
15d3411f45 Add configuration for hotrod TLS 2022-01-04 14:30:28 +01:00
Guido Grazioli
5eba1c12e4 Bind jgroups to any-address when ansible facts not defined 2021-12-31 12:31:08 +01:00
Guido Grazioli
52ca7083a4 Merge pull request #3 from ansible-middleware/refactor_standalone_xml
Allow to change default standalone.xml path and name
2021-12-30 16:47:16 +01:00
Romain Pelisse
cfb8f7c6fb Allow to change default standalone.xml path and name 2021-12-30 16:22:41 +01:00
Guido Grazioli
af157fd516 Start work on v0.1.3 2021-12-30 12:53:42 +01:00
Guido Grazioli
daa5396a47 Switch collection dep from jcliff to wildfly 2021-12-30 12:24:59 +01:00
Guido Grazioli
d663dea5c9 Merge pull request #2 from ansible-middleware/display_health_url
Enhance wait message with keycloak healthcheck URL
2021-12-30 10:47:33 +01:00
Romain Pelisse
543e82cb9f Enhance wait message with keycloak healthcheck URL 2021-12-29 18:30:58 +01:00
Guido Grazioli
496c902427 fix db init sql for postgresql 2021-12-29 16:30:36 +01:00
Guido Grazioli
c81976a0ce Start work on v0.1.2 2021-12-23 09:31:09 +01:00
Guido Grazioli
c061e664b3 Complete galaxy_info metadata 2021-12-23 09:30:13 +01:00
Guido Grazioli
434f92ae9b Start work on v0.1.1 2021-12-22 16:47:08 +01:00
63 changed files with 2350 additions and 925 deletions

27
.ansible-lint Normal file
View File

@@ -0,0 +1,27 @@
# .ansible-lint
exclude_paths:
- .cache/
- .github/
- molecule/
- .ansible-lint
- .yamllint
rulesdir:
- ../../ansible-lint-custom-rules/rules/
enable_list:
- fqcn-builtins # opt-in
- no-log-password # opt-in
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
use_default_rules: true
parseable: true

48
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,48 @@
---
name: 🐛 Bug report
about: Create a report to help us improve
---
##### SUMMARY
<!-- Explain the problem briefly -->
##### ISSUE TYPE
- Bug Report
##### ANSIBLE VERSION
<!-- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version"-->
```
```
##### COLLECTION VERSION
<!-- Paste, BELOW THIS COMMENT, verbatim output from "ansible-galaxy collection list"-->
<!-- If using virtual environments or execution environments, remember to activate them-->
```
```
##### STEPS TO REPRODUCE
<!-- List the steps to reproduce the problem, using a minimal test-case. -->
<!-- Paste example playbook below -->
```yaml
```
##### EXPECTED RESULTS
<!-- What did you expect to happen when running the steps above? -->
##### ACTUAL RESULTS
<!-- What actually happened? If possible run with extra verbosity (-vvvv) and diff (--diff) -->
<!-- Please also include check mode (--check --diff) output if the API returns an error -->
<!-- Be sure to mask any sensitive information -->
<!--- Paste verbatim command output between quotes below -->
```
```

View File

@@ -0,0 +1,12 @@
---
name: ✨ Feature request
about: Suggest an idea for this project
---
##### SUMMARY
<!--- Explain the problem briefly -->
##### ISSUE TYPE
- Feature Idea

View File

@@ -27,11 +27,17 @@ jobs:
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install yamllint 'molecule[docker]~=3.5.2' ansible-core flake8 ansible-lint voluptuous 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 symlink - 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: | run: |
mkdir -p /home/runner/.ansible mkdir -p /home/runner/.ansible/collections/ansible_collections
ln -s /home/runner/work/middleware_automation/keycloak /home/runner/.ansible/collections
- name: Run sanity tests - name: Run sanity tests
run: ansible-test sanity --docker -v --color --python ${{ matrix.python_version }} run: ansible-test sanity --docker -v --color --python ${{ matrix.python_version }}

75
.github/workflows/docs.yml vendored Normal file
View File

@@ -0,0 +1,75 @@
---
name: Documentation
on:
push:
branches:
- main
tags:
- "[0-9]+.[0-9]+.[0-9]+"
env:
COLORTERM: 'yes'
TERM: 'xterm-256color'
PYTEST_ADDOPTS: '--color=yes'
jobs:
docs:
runs-on: ubuntu-latest
if: github.repository == 'ansible-middleware/keycloak'
permissions:
actions: write
checks: write
contents: write
deployments: write
packages: write
pages: write
steps:
- name: Check out code
uses: actions/checkout@v2
with:
path: ansible_collections/middleware_automation/keycloak
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install doc dependencies
run: |
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
- name: Create default collection path
run: |
mkdir -p /home/runner/.ansible/collections/ansible_collections
- name: Create doc directories and resources
run: |
mkdir -p ./docs/plugins ./docs/roles
cat ./docs/roles.rst.template > ./docs/roles/index.rst
antsibull-docs collection --use-current --squash-hierarchy --dest-dir docs/plugins middleware_automation.keycloak
for role_readme in roles/*/README.md; do ln -f -s ../../$role_readme ./docs/roles/$(basename $(dirname $role_readme)).md; echo " * :doc:\`$(basename $(dirname $role_readme))\`" >> ./docs/roles/index.rst; done
working-directory: ansible_collections/middleware_automation/keycloak
- name: Run sphinx
run: |
sphinx-build -M html . _build -v
working-directory: ansible_collections/middleware_automation/keycloak/docs/
- name: Commit docs
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git checkout gh-pages
rm -rf $(basename ${GITHUB_REF})
mv docs/_build/html $(basename ${GITHUB_REF})
ln --force --no-dereference --symbolic main latest
git show origin/main:docs/_gh_include/header.inc > index.html
(echo main; echo latest; dirname *.*.*/index.html | sort --version-sort --reverse) | xargs -I@@ -n1 echo '<li class="toctree-l1"><a class="reference internal" href="@@/">@@</a></li>' >> index.html
git show origin/main:docs/_gh_include/footer.inc >> index.html
git add $(basename ${GITHUB_REF}) latest index.html
git commit -m "Update docs for $(basename ${GITHUB_REF})" || true
git push origin gh-pages
working-directory: ansible_collections/middleware_automation/keycloak/

View File

@@ -1,15 +1,16 @@
---
name: Release collection name: Release collection
on: on:
push: push:
tags: tags:
- "*.*.*" - "[0-9]+.[0-9]+.[0-9]+"
jobs: jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - name: Checkout code
uses: actions/checkout@v2
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v1 uses: actions/setup-python@v1
with: with:
@@ -30,9 +31,23 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
files: "*.tar.gz" files: "*.tar.gz"
body: "Release ${{ steps.get_version.outputs.TAG_VERSION }}" body: "Release v${{ steps.get_version.outputs.TAG_VERSION }}"
- name: Publish collection - name: Publish collection
env: env:
ANSIBLE_GALAXY_API_KEY: ${{ secrets.ANSIBLE_GALAXY_API_KEY }} ANSIBLE_GALAXY_API_KEY: ${{ secrets.ANSIBLE_GALAXY_API_KEY }}
run: | run: |
ansible-galaxy collection publish *.tar.gz --api-key $ANSIBLE_GALAXY_API_KEY ansible-galaxy collection publish *.tar.gz --api-key $ANSIBLE_GALAXY_API_KEY
dispatch:
needs: release
strategy:
matrix:
repo: ['ansible-middleware/cross-dc-rhsso-demo', 'ansible-middleware/flange-demo']
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.TRIGGERING_PAT }}
repository: ${{ matrix.repo }}
event-type: "Dependency released - Keycloak"
client-payload: '{ "github": ${{toJson(github)}} }'

9
.gitignore vendored
View File

@@ -1 +1,10 @@
*.tar.gz *.tar.gz
*.zip
.tmp
.cache
docs/plugins/
docs/roles/
docs/_build/
.pytest_cache/
.mypy_cache/
*.retry

14
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,14 @@
## Contributor's Guidelines
- All YAML files named with '.yml' extension
- Use spaces around jinja variables. `{{ var }}` over `{{var}}`
- Variables that are internal to the role should be lowercase and start with the role name
- Keep roles self contained - Roles should avoid including tasks from other roles when possible
- Plays should do nothing more than include a list of roles, except where `pre_tasks` and `post_tasks` are required, when possible
- Separators - Use valid names, ie. underscores (e.g. `my_role` `my_playbook`) not dashes (`my-role`)
- Paths - When defining paths, do not include trailing slashes (e.g. `my_path: /foo` not `my_path: /foo/`); when concatenating paths, follow the same convention (e.g. `{{ my_path }}/bar` not `{{ my_path }}bar`)
- Indentation - Use 2 spaces for each indent
- `vars/` vs `defaults/` - internal or interpolated variables that don't need to change or be overridden by user go in `vars/`, those that a user would likely override, go under `defaults/` directory
- All role arguments have a specification in `meta/argument_specs.yml`
- All playbooks/roles should be focused on compatibility with Ansible Tower

134
README.md
View File

@@ -1,4 +1,4 @@
# Ansible Collection - keycloak # Ansible Collection - middleware_automation.keycloak
[![Build Status](https://github.com/ansible-middleware/keycloak/workflows/CI/badge.svg?branch=main)](https://github.com/ansible-middleware/keycloak/actions/workflows/ci.yml) [![Build Status](https://github.com/ansible-middleware/keycloak/workflows/CI/badge.svg?branch=main)](https://github.com/ansible-middleware/keycloak/actions/workflows/ci.yml)
@@ -13,7 +13,8 @@ This collection has been tested against following Ansible versions: **>=2.9.10**
Plugins and modules within a collection may be tested with only specific Ansible versions. A collection may contain metadata that identifies these versions. Plugins and modules within a collection may be tested with only specific Ansible versions. A collection may contain metadata that identifies these versions.
<!--end requires_ansible--> <!--end requires_ansible-->
## Installation and Usage
## Installation
### Installing the Collection from Ansible Galaxy ### Installing the Collection from Ansible Galaxy
@@ -29,28 +30,139 @@ collections:
- name: middleware_automation.keycloak - name: middleware_automation.keycloak
``` ```
### Choosing between Red Hat products and upstream project The keycloak collection also depends on the following python packages to be present on the controller host:
The roles supports installing Red Hat Single Sign-On from the Customer Portal, when the following variables are defined: * netaddr
``` A requirement file is provided to install:
pip install -r requirements.txt
### Included roles
* [`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.
## Usage
### 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.
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_username: '<customer_portal_username>'
rhn_password: '<customer_portal_password>' rhn_password: '<customer_portal_password>'
rhsso_rhn_id: '<sso_product_id>' # (keycloak_rhsso_enable defaults to True)
``` ```
where `sso_product_id` is the ID for the specific Red Hat Single Sign-On version, ie. _101971_ will install version _7.5_)
#### Install from controller node (local source)
Making the keycloak zip archive (or the RHSSO zip archive), available to the playbook repository root directory, and setting `keycloak_offline_install` to `True`, allows to skip
the download tasks. The local path for the archive matches the downloaded archive path, so it is also used as a cache when multiple hosts are provisioned in a cluster.
```yaml
keycloak_offline_install: True
```
And depending on `keycloak_rhsso_enable`:
* `True`: install RHSSO using file rh-sso-x.y.z-server-dist.zip
* `False`: install keycloak using file keycloak-x.y.zip
## Included roles #### Install from alternate sources (like corporate Nexus, artifactory, proxy, etc)
* `keycloak`: role for installing the service. For RHSSO:
* `keycloak_realm`: role for configuring a realm, with clients and users, in an installed service.
```yaml
keycloak_rhsso_enable: True
keycloak_rhsso_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"
```
### Example installation command
Execute the following command from the source root directory
```
ansible-playbook -i <ansible_hosts> -e @rhn-creds.yml playbooks/keycloak.yml -e keycloak_admin_password=<changeme>
```
- `keycloak_admin_password` Password for the administration console user account.
- `ansible_hosts` is the inventory, below is an example inventory for deploying to localhost
```
[keycloak]
localhost ansible_connection=local
```
## Configuration
### 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).
### Example configuration command
Execute the following command from the source root directory:
```bash
ansible-playbook -i <ansible_hosts> playbooks/keycloak_realm.yml -e keycloak_admin_password=<changeme> -e keycloak_realm=test
```
- `keycloak_admin_password` password for the administration console user account.
- `keycloak_realm` name of the realm to be created/used.
- `ansible_hosts` is the inventory, below is an example inventory for deploying to localhost
```
[keycloak]
localhost ansible_connection=local
```
For full configuration details, refer to the [keycloak_realm role README](roles/keycloak_realm/README.md).
## Support
Keycloak collection v1.0.0 is a Beta release and for [Technical Preview](https://access.redhat.com/support/offerings/techpreview). If you have any issues or questions related to collection, please don't hesitate to contact us on Ansible-middleware-core@redhat.com or open an issue on https://github.com/ansible-middleware/keycloak/issues
## License ## License
Apache License v2.0 or later Apache License v2.0 or later
See [LICENCE](LICENSE) to view the full text. See [LICENSE](LICENSE) to view the full text.

1
docs/README.md Symbolic link
View File

@@ -0,0 +1 @@
../README.md

View File

@@ -0,0 +1,21 @@
</ul>
</div>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2022, Red Hat, Inc..</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
</body>
</html>

View File

@@ -0,0 +1,43 @@
<!doctype html>
<html>
<head>
<title>Keycloak Ansible Collection documentation index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://ansible-middleware.github.io/keycloak/main/_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="https://ansible-middleware.github.io/keycloak/main/_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="https://ansible-middleware.github.io/keycloak/main/_static/ansible-basic-sphinx-ext.css" type="text/css" />
<script data-url_root="./" id="documentation_options" src="https://ansible-middleware.github.io/keycloak/main/_static/documentation_options.js"></script>
<script src="https://ansible-middleware.github.io/keycloak/main/_static/jquery.js"></script>
<script src="https://ansible-middleware.github.io/keycloak/main/_static/underscore.js"></script>
<script src="https://ansible-middleware.github.io/keycloak/main/_static/doctools.js"></script>
<script src="https://ansible-middleware.github.io/keycloak/main/_static/js/theme.js"></script>
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="#" class="icon icon-home"> Keycloak Ansible Collection</a>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="#" class="icon icon-home"></a> &raquo;</li>
<li>Welcome to Keycloak Collection documentation</li>
<li class="wy-breadcrumbs-aside"></li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="welcome-to-keycloak-collection-documentation">
<h1>Welcome to Keycloak Collection documentation<a class="headerlink" href="#welcome-to-keycloak-collection-documentation" title="Permalink to this headline"></a></h1>
<div class="toctree-wrapper compound">
<p class="caption" role="heading"><span class="caption-text">Pick collection version:</span></p>
<ul>

170
docs/conf.py Normal file
View File

@@ -0,0 +1,170 @@
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import datetime
import os
import sys
sys.path.insert(0, os.path.abspath('../plugins/module_utils/'))
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'Keycloak Ansible Collection'
copyright = '{y}, Red Hat, Inc.'.format(y=datetime.date.today().year)
author = 'Red Hat, Inc.'
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = ''
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'myst_parser',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'ansible_basic_sphinx_ext',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ['.rst', '.md']
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path .
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.tmp']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
highlight_language = 'YAML+Jinja'
# -- Options for HTML output -------------------------------------------------
html_theme_path = ['_themes']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
# html_theme = 'alabaster'
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'KeycloakCollectionDoc'
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'KeycloakCollection.tex', 'Red Hat Single Sign-On Ansible Collection Documentation',
'Red Hat, Inc.', 'manual'),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'keycloakcollection', 'Red Hat Single Sign-On Ansible Collection Documentation',
[author], 1)
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'KeycloakCollection', 'Red Hat Single Sign-On Ansible Collection Documentation',
author, 'KeycloakCollection', 'One line description of project.',
'Miscellaneous'),
]
# -- Extension configuration -------------------------------------------------
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('https://docs.python.org/2', None), 'ansible': ('https://docs.ansible.com/ansible/latest/', None)}

1
docs/developing.md Symbolic link
View File

@@ -0,0 +1 @@
../CONTRIBUTING.md

32
docs/index.rst Normal file
View File

@@ -0,0 +1,32 @@
.. Red Hat middleware_automation Keycloak Ansible Collection documentation main file
Welcome to Keycloak Collection documentation
============================================
.. toctree::
:maxdepth: 2
:caption: User documentation
README
plugins/index
roles/index
.. toctree::
:maxdepth: 2
:caption: Developer documentation
developing
testing
releasing
.. toctree::
:maxdepth: 2
:caption: General
Changelog <CHANGELOG>
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`

5
docs/requirements.txt Normal file
View File

@@ -0,0 +1,5 @@
antsibull>=0.17.0
ansible-base>=2.10.12
sphinx-rtd-theme
git+https://github.com/felixfontein/ansible-basic-sphinx-ext
myst-parser

3
docs/roles.rst.template Normal file
View File

@@ -0,0 +1,3 @@
Role Index
==========

View File

@@ -1,22 +1,33 @@
---
namespace: middleware_automation namespace: middleware_automation
name: keycloak name: keycloak
version: "0.1.0" version: "1.0.0"
readme: README.md readme: README.md
authors: authors:
- Romain Pelisse <rpelisse@redhat.com> - Romain Pelisse <rpelisse@redhat.com>
- Guido Grazioli <ggraziol@redhat.com> - Guido Grazioli <ggraziol@redhat.com>
- Pavan Kumar Motaparthi <pmotapar@redhat.com>
description: Install and configure a keycloak, or Red Hat Single Sign-on, service. description: Install and configure a keycloak, or Red Hat Single Sign-on, service.
license_file: "LICENSE" license_file: "LICENSE"
tags: tags:
- keycloak - keycloak
- redhat - redhat
- rhel - rhel
- rhn
- sso - sso
- openid
- application
- identity
- security
- infrastructure
- authentication
dependencies: dependencies:
"middleware_automation.redhat_csp_download": ">=1.2.1" "middleware_automation.redhat_csp_download": ">=1.2.1"
"middleware_automation.jcliff": ">=0.0.19" "middleware_automation.wildfly": ">=0.0.6"
repository: https://github.com/ansible-middleware/keycloak repository: https://github.com/ansible-middleware/keycloak
documentation: https://github.com/ansible-middleware/keycloak documentation: https://ansible-middleware.github.io/keycloak
homepage: https://github.com/ansible-middleware/keycloak homepage: https://github.com/ansible-middleware/keycloak
issues: https://github.com/ansible-middleware/keycloak/issues issues: https://github.com/ansible-middleware/keycloak/issues
build_ignore:
- molecule
- docs
- .github

View File

@@ -40,3 +40,4 @@
public_client: "{{ keycloak_client_public }}" public_client: "{{ keycloak_client_public }}"
web_origins: "{{ keycloak_client_web_origins }}" web_origins: "{{ keycloak_client_web_origins }}"
users: "{{ keycloak_client_users }}" users: "{{ keycloak_client_users }}"
client_id: TestClient

View File

@@ -1,8 +1,12 @@
--- ---
dependency: dependency:
name: galaxy name: shell
command: ansible-galaxy collection install -r molecule/default/requirements.yml -p $HOME/.ansible/collections --force-with-deps
driver: driver:
name: docker name: docker
lint: |
ansible-lint --version
ansible-lint -v
platforms: platforms:
- name: instance - name: instance
image: registry.access.redhat.com/ubi8/ubi-init:latest image: registry.access.redhat.com/ubi8/ubi-init:latest

View File

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

View File

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

View File

@@ -5,6 +5,6 @@
- name: Populate service facts - name: Populate service facts
ansible.builtin.service_facts: ansible.builtin.service_facts:
- name: Check if keycloak service started - name: Check if keycloak service started
assert: ansible.builtin.assert:
that: that:
- ansible_facts.services["keycloak.service"]["state"] == "running" - ansible_facts.services["keycloak.service"]["state"] == "running"

View File

@@ -2,35 +2,10 @@
- name: Playbook for Keycloak Hosts - name: Playbook for Keycloak Hosts
hosts: keycloak hosts: keycloak
collections: collections:
- middleware_automation.redhat_csp_download - middleware_automation.keycloak
roles:
- redhat_csp_download
tasks: tasks:
- name: Keycloak Role - name: Include keycloak role
include_role: ansible.builtin.include_role:
name: keycloak name: middleware_automation.keycloak.keycloak
vars: vars:
keycloak_admin_password: "changeme" keycloak_admin_password: "changeme"
- name: Keycloak Realm Role
include_role:
name: keycloak_realm
vars:
keycloak_admin_password: "changeme"
keycloak_realm: TestRealm
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 }}"

View File

@@ -0,0 +1,67 @@
---
- 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 }}"

14
playbooks/rhsso.yml Normal file
View File

@@ -0,0 +1,14 @@
---
- name: Playbook for Keycloak Hosts
hosts: keycloak
collections:
- middleware_automation.redhat_csp_download
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

1
playbooks/roles Symbolic link
View File

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

6
requirements.txt Normal file
View File

@@ -0,0 +1,6 @@
#################################################
# python dependencies required to be installed
# on the controller host with:
# pip install -r requirements.txt
#
netaddr

View File

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

View File

@@ -4,21 +4,95 @@ 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 Sing-On](https://access.redhat.com/products/red-hat-single-sign-on) server configurations.
Requirements
------------
This role requires the `python3-netaddr` library installed on the controller node.
* to install via yum/dnf: `dnf install python3-netaddr`
* or via pip: `pip install netaddr==0.8.0`
* or via the collection: `pip install -r requirements.txt`
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
--------
| 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)|
Role Defaults Role Defaults
------------- -------------
* Service configuration
| Variable | Description | Default | | Variable | Description | Default |
|:---------|:------------|:---------| |:---------|:------------|:---------|
|`keycloak_ha_enabled`| enable auto configuration for database backend, clustering and remote caches on infinispan | `False` | |`keycloak_ha_enabled`| Enable auto configuration for database backend, clustering and remote caches on infinispan | `False` |
|`keycloak_db_enabled`| enable auto configuration for database backend | `True` if keycloak_ha_enabled is True, else `False` | |`keycloak_db_enabled`| Enable auto configuration for database backend | `True` if `keycloak_ha_enabled` is True, else `False` |
|`keycloak_admin_user`| Administration console user account | `admin` | |`keycloak_admin_user`| Administration console user account | `admin` |
|`keycloak_bind_address`| address for binding service ports | `0.0.0.0` |`keycloak_bind_address`| Address for binding service ports | `0.0.0.0` |
|`keycloak_host`| hostname | `localhost` |`keycloak_host`| hostname | `localhost` |
|`keycloak_http_port`| HTTP port | `8080` |`keycloak_http_port`| HTTP port | `8080` |
|`keycloak_https_port`| TLS HTTP port | `8443` |`keycloak_https_port`| TLS HTTP port | `8443` |
|`keycloak_management_http_port`| management port | `9990` |`keycloak_ajp_port`| AJP port | `8009` |
|`keycloak_management_https_port`| TLS management port | `9993` |`keycloak_jgroups_port`| jgroups cluster tcp port | `7600` |
|`keycloak_java_opts`| | `-Xms1024m -Xmx20480m -XX:MaxPermSize=768m` |`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` |
* 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_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=` |
* Miscellaneous configuration
| Variable | Description | Default |
|:---------|:------------|:--------|
|`keycloak_archive` | keycloak install archive filename | `keycloak-{{ 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_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] }}` |
Role Variables Role Variables
-------------- --------------
@@ -30,48 +104,39 @@ The following are a set of _required_ variables for the role:
|`keycloak_admin_password`| Password for the administration console user account | |`keycloak_admin_password`| Password for the administration console user account |
The following variables are _required_ only when keycloak_ha_enabled is True: The following variables are _required_ only when `keycloak_ha_enabled` is True:
| Variable | Description | Default | | Variable | Description | Default |
|:---------|:------------|:---------| |:---------|:------------|:---------|
|`keycloak_modcluster_url` | URL for the modcluster reverse proxy | `localhost` | |`keycloak_modcluster_url` | URL for the modcluster reverse proxy | `localhost` |
|`keycloak_frontend_url` | frontend URL for keycloak endpoints when a reverse proxy is used | `http://localhost` |
|`keycloak_jdbc_engine` | backend database flavour when db is enabled: [ postgres, mariadb ] | `postgres` | |`keycloak_jdbc_engine` | backend database flavour when db is enabled: [ postgres, mariadb ] | `postgres` |
|`infinispan_url` | URL for the infinispan remote-cache server | `localhost:11122` | |`infinispan_url` | URL for the infinispan remote-cache server | `localhost:11122` |
|`infinispan_user` | username for connecting to infinispan | `supervisor` | |`infinispan_user` | username for connecting to infinispan | `supervisor` |
|`infinispan_pass` | password 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` |
The following variables are _required_ only when keycloak_db_enabled is True and keycloak_jdbc_engine is postgres: The following variables are _required_ only when `keycloak_db_enabled` is True:
| Variable | Description | Default | | Variable | Description | Default |
|:---------|:------------|:---------| |:---------|:------------|:---------|
|`postgres_jdbc_url` | URL for the postgres backend database | `jdbc:postgresql://localhost:5432/keycloak` | |`keycloak_jdbc_url` | URL for the postgres backend database | `jdbc:postgresql://localhost:5432/keycloak` |
|`postgres_db_user` | username for connecting to postgres | `keycloak-user` | |`keycloak_jdbc_driver_version`| Version for the JDBC driver to download | `9.4.1212` |
|`postgres_db_pass` | password for connecting to postgres | `keycloak-pass` | |`keycloak_db_user` | username for connecting to postgres | `keycloak-user` |
|`keycloak_db_pass` | password for connecting to postgres | `keycloak-pass` |
The following variables are _required_ only when keycloak_db_enabled is True and keycloak_jdbc_engine is mariadb: Example Playbooks
-----------------
| Variable | Description | Default | _NOTE_: use ansible vaults or other security systems for storing credentials.
|:---------|:------------|:---------|
|`mariadb_jdbc_url` | URL for the mariadb backend database | `jdbc:mariadb://localhost:3306/keycloak` |
|`mariadb_db_user` | username for connecting to mariadb | `keycloak-user` |
|`mariadb_db_pass` | password for connecting to mariadb | `keycloak-pass` |
Dependencies * The following is an example playbook that makes use of the role to install keycloak from remote:
------------
The roles depends on:
* the redhat_csp_download role from [middleware_automation.redhat_csp_download](https://github.com/ansible-middleware/redhat-csp-download) collection
* the wildfly_driver role from [middleware_automation.jcliff](https://github.com/ansible-middleware/ansible_collections_jcliff) collection
Example Playbook
----------------
The following is an example playbook that makes use of the role to install keycloak
```yaml ```yaml
--- ---
@@ -86,6 +151,83 @@ The following is an example playbook that makes use of the role to install keycl
keycloak_admin_password: "changeme" keycloak_admin_password: "changeme"
``` ```
* The following is an example playbook that makes use of the role to install 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>'
```
* The following example playbook makes use of the role to install keycloak from the controller node:
```yaml
---
- hosts: ...
collections:
- middleware_automation.keycloak
tasks:
- name: Include keycloak role
include_role:
name: keycloak
vars:
keycloak_admin_password: "changeme"
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 License
------- -------
@@ -97,3 +239,4 @@ Author Information
* [Guido Grazioli](https://github.com/guidograzioli) * [Guido Grazioli](https://github.com/guidograzioli)
* [Romain Pelisse](https://github.com/rpelisse) * [Romain Pelisse](https://github.com/rpelisse)
* [Pavan Kumar Motaparthi](https://github.com/motaparthipavankumar)

View File

@@ -1,34 +1,46 @@
--- ---
### Configuration specific to keycloak ### Configuration specific to keycloak
keycloak_version: 9.0.2 keycloak_version: 15.0.2
keycloak_archive: keycloak-{{ keycloak_version }}.zip keycloak_archive: "keycloak-{{ keycloak_version }}.zip"
keycloak_download_url: https://downloads.jboss.org/keycloak/{{ keycloak_version }}/{{ keycloak_archive }} 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 }}" keycloak_installdir: "{{ keycloak_dest }}/keycloak-{{ keycloak_version }}"
### Configuration specific to Red Hat Single Sing-On ### Configuration specific to Red Hat Single Sing-On
keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined else False }}" keycloak_rhsso_version: 7.5.0
keycloak_rhsso_version: 7.5 rhsso_rhn_id: "{{ rhsso_rhn_ids[keycloak_rhsso_version] }}"
keycloak_rhsso_archive: rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip keycloak_rhsso_archive: "rh-sso-{{ keycloak_rhsso_version }}-server-dist.zip"
keycloak_rhsso_installdir: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version }}" keycloak_rhsso_installdir: "{{ keycloak_dest }}/rh-sso-{{ keycloak_rhsso_version | regex_replace('^([0-9])\\.([0-9]*).*', '\\1.\\2') }}"
keycloak_rhsso_base_url: 'https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId=' keycloak_rhn_url: 'https://access.redhat.com/jbossnetwork/restricted/softwareDownload.html?softwareId='
keycloak_rhsso_download_url: "{{ keycloak_rhn_url }}{{ rhsso_rhn_id }}"
### 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 ### Install location and service settings
jvm_package: java-1.8.0-openjdk-devel
keycloak_dest: /opt/keycloak keycloak_dest: /opt/keycloak
keycloak_jboss_home: "{{ keycloak_rhsso_installdir if rhsso_rhn_id is defined else keycloak_installdir }}" keycloak_jboss_home: "{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}"
keycloak_config_dir: "{{ keycloak_jboss_home }}/standalone/configuration" keycloak_config_dir: "{{ keycloak_jboss_home }}/standalone/configuration"
keycloak_config_standalone_xml: "keycloak.xml"
keycloak_config_path_to_standalone_xml: "{{ keycloak_jboss_home }}/standalone/configuration/{{ keycloak_config_standalone_xml }}"
keycloak_service_user: keycloak keycloak_service_user: keycloak
keycloak_service_group: keycloak keycloak_service_group: keycloak
keycloak_service_pidfile: "/run/keycloak.pid" keycloak_service_pidfile: "/run/keycloak.pid"
keycloak_service_logfile: "{{ keycloak_dest }}/keycloak.log"
### Keycloak configuration settings ### Common configuration settings
keycloak_bind_address: 0.0.0.0 keycloak_bind_address: 0.0.0.0
keycloak_host: localhost keycloak_host: localhost
keycloak_http_port: 8080 keycloak_http_port: 8080
keycloak_https_port: 8443 keycloak_https_port: 8443
keycloak_ajp_port: 8009
keycloak_jgroups_port: 7600
keycloak_management_http_port: 9990 keycloak_management_http_port: 9990
keycloak_management_https_port: 9993 keycloak_management_https_port: 9993
keycloak_java_opts: "-Xms1024m -Xmx20480m -XX:MaxPermSize=768m" keycloak_java_opts: "-Xms1024m -Xmx2048m"
keycloak_prefer_ipv4: True
### Enable configuration for database backend, clustering and remote caches on infinispan ### Enable configuration for database backend, clustering and remote caches on infinispan
keycloak_ha_enabled: False keycloak_ha_enabled: False
@@ -44,18 +56,30 @@ keycloak_force_install: False
### mod_cluster reverse proxy ### mod_cluster reverse proxy
keycloak_modcluster_url: localhost keycloak_modcluster_url: localhost
keycloak_frontend_url: http://localhost
### infinispan remote caches access ### infinispan remote caches access (hotrod)
infinispan_user: supervisor infinispan_user: supervisor
infinispan_pass: supervisor infinispan_pass: supervisor
infinispan_url: localhost infinispan_url: localhost
infinispan_sasl_mechanism: SCRAM-SHA-512
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
### database backend engine: values [ 'postgres', 'mariadb' ] ### database backend engine: values [ 'postgres', 'mariadb' ]
keycloak_jdbc_engine: postgres keycloak_jdbc_engine: postgres
### database backend credentials ### database backend credentials
postgres_jdbc_url: 'jdbc:postgresql://localhost:5432/keycloak' keycloak_db_user: keycloak-user
postgres_db_user: keycloak-user keycloak_db_pass: keycloak-pass
postgres_db_pass: keycloak-pass keycloak_jdbc_url: "{{ keycloak_default_jdbc[keycloak_jdbc_engine].url }}"
mariadb_jdbc_url: 'jdbc:mariadb://localhost:3306/keycloak' keycloak_jdbc_driver_version: "{{ keycloak_default_jdbc[keycloak_jdbc_engine].version }}"
mariadb_db_user: keycloak-user # override the variables above, following defaults show minimum supported versions
mariadb_db_pass: keycloak-pass keycloak_default_jdbc:
postgres:
url: 'jdbc:postgresql://localhost:5432/keycloak'
version: 9.4.1212
mariadb:
url: 'jdbc:mariadb://localhost:3306/keycloak'
version: 2.7.4

View File

@@ -1,3 +1,3 @@
--- ---
- name: restart keycloak - name: restart keycloak
include_tasks: restart_keycloak.yml ansible.builtin.include_tasks: restart_keycloak.yml

View File

@@ -0,0 +1,278 @@
argument_specs:
main:
options:
keycloak_version:
# line 3 of keycloak/defaults/main.yml
default: "15.0.2"
description: "keycloak.org package version"
type: "str"
keycloak_archive:
# line 4 of keycloak/defaults/main.yml
default: "keycloak-{{ keycloak_version }}.zip"
description: "keycloak install archive filename"
type: "str"
keycloak_download_url:
# line 5 of keycloak/defaults/main.yml
default: "https://github.com/keycloak/keycloak/releases/download/{{ keycloak_version }}/{{ keycloak_archive }}"
description: "Download URL for keycloak"
type: "str"
keycloak_download_url_9x:
# line 6 of keycloak/defaults/main.yml
default: "https://downloads.jboss.org/keycloak/{{ keycloak_version }}/{{ keycloak_archive }}"
description: "Download URL for keycloak (deprecated)"
type: "str"
keycloak_installdir:
# line 7 of keycloak/defaults/main.yml
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] }}"
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_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:
# line 23 of keycloak/defaults/main.yml
default: "java-1.8.0-openjdk-devel"
description: "RHEL java package runtime rpm"
type: "str"
keycloak_dest:
# line 24 of keycloak/defaults/main.yml
default: "/opt/keycloak"
description: "Root installation directory"
type: "str"
keycloak_jboss_home:
# line 25 of keycloak/defaults/main.yml
default: "{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}"
description: "Installation work directory"
type: "str"
keycloak_config_dir:
# line 26 of keycloak/defaults/main.yml
default: "{{ keycloak_jboss_home }}/standalone/configuration"
description: "Path for configuration"
type: "str"
keycloak_config_standalone_xml:
# line 27 of keycloak/defaults/main.yml
default: "keycloak.xml"
description: "Service configuration filename"
type: "str"
keycloak_config_path_to_standalone_xml:
# line 28 of keycloak/defaults/main.yml
default: "{{ keycloak_jboss_home }}/standalone/configuration/{{ keycloak_config_standalone_xml }}"
description: "Custom path for configuration"
type: "str"
keycloak_service_user:
# line 29 of keycloak/defaults/main.yml
default: "keycloak"
description: "posix account username"
type: "str"
keycloak_service_group:
# line 30 of keycloak/defaults/main.yml
default: "keycloak"
description: "posix account group"
type: "str"
keycloak_service_pidfile:
# line 31 of keycloak/defaults/main.yml
default: "/run/keycloak.pid"
description: "PID file path for service"
type: "str"
keycloak_bind_address:
# line 34 of keycloak/defaults/main.yml
default: "0.0.0.0"
description: "Address for binding service ports"
type: "str"
keycloak_host:
# line 35 of keycloak/defaults/main.yml
default: "localhost"
description: "Hostname for service"
type: "str"
keycloak_http_port:
# line 36 of keycloak/defaults/main.yml
default: 8080
description: "Listening HTTP port"
type: "int"
keycloak_https_port:
# line 37 of keycloak/defaults/main.yml
default: 8443
description: "Listening HTTPS port"
type: "int"
keycloak_ajp_port:
# line 38 of keycloak/defaults/main.yml
default: 8009
description: "Listening AJP port"
type: "int"
keycloak_jgroups_port:
# line 39 of keycloak/defaults/main.yml
default: 7600
description: "jgroups cluster tcp port"
type: "int"
keycloak_management_http_port:
# line 40 of keycloak/defaults/main.yml
default: 9990
description: "Management port (http)"
type: "int"
keycloak_management_https_port:
# line 41 of keycloak/defaults/main.yml
default: 9993
description: "Management port (https)"
type: "int"
keycloak_java_opts:
# line 42 of keycloak/defaults/main.yml
default: "-Xms1024m -Xmx2048m"
description: "Additional JVM options"
type: "str"
keycloak_prefer_ipv4:
# line 43 of keycloak/defaults/main.yml
default: true
description: "Prefer IPv4 stack and addresses for port binding"
type: "bool"
keycloak_ha_enabled:
# line 46 of keycloak/defaults/main.yml
default: false
description: "Enable auto configuration for database backend, clustering and remote caches on infinispan"
type: "bool"
keycloak_db_enabled:
# line 48 of keycloak/defaults/main.yml
default: "{{ True if keycloak_ha_enabled else False }}"
description: "Enable auto configuration for database backend"
type: "str"
keycloak_admin_user:
# line 51 of keycloak/defaults/main.yml
default: "admin"
description: "Administration console user account"
type: "str"
keycloak_auth_realm:
# line 52 of keycloak/defaults/main.yml
default: "master"
description: "Name for rest authentication realm"
type: "str"
keycloak_auth_client:
# line 53 of keycloak/defaults/main.yml
default: "admin-cli"
description: "Authentication client for configuration REST calls"
type: "str"
keycloak_force_install:
# line 55 of keycloak/defaults/main.yml
default: false
description: "Remove pre-existing versions of service"
type: "bool"
keycloak_modcluster_url:
# line 58 of keycloak/defaults/main.yml
default: "localhost"
description: "URL for the modcluster reverse proxy"
type: "str"
keycloak_frontend_url:
# line 59 of keycloak/defaults/main.yml
default: "http://localhost"
description: "Frontend URL for keycloak endpoints when a reverse proxy is used"
type: "str"
infinispan_user:
# line 62 of keycloak/defaults/main.yml
default: "supervisor"
description: "Username for connecting to infinispan"
type: "str"
infinispan_pass:
# line 63 of keycloak/defaults/main.yml
default: "supervisor"
description: "Password for connecting to infinispan"
type: "str"
infinispan_url:
# line 64 of keycloak/defaults/main.yml
default: "localhost"
description: "URL for the infinispan remote-cache server"
type: "str"
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:
# line 66 of keycloak/defaults/main.yml
default: false
description: "Enable hotrod client TLS communication"
type: "bool"
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:
# line 69 of keycloak/defaults/main.yml
default: "changeit"
description: "Path to truststore containing infinispan server certificate"
type: "str"
keycloak_jdbc_engine:
# line 72 of keycloak/defaults/main.yml
default: "postgres"
description: "Backend database flavour when db is enabled: [ postgres, mariadb ]"
type: "str"
keycloak_db_user:
# line 74 of keycloak/defaults/main.yml
default: "keycloak-user"
description: "Username for connecting to database"
type: "str"
keycloak_db_pass:
# line 75 of keycloak/defaults/main.yml
default: "keycloak-pass"
description: "Password for connecting to database"
type: "str"
keycloak_jdbc_url:
# line 76 of keycloak/defaults/main.yml
default: "{{ keycloak_default_jdbc[keycloak_jdbc_engine].url }}"
description: "URL for connecting to backend database"
type: "str"
keycloak_jdbc_driver_version:
# line 77 of keycloak/defaults/main.yml
default: "{{ keycloak_default_jdbc[keycloak_jdbc_engine].version }}"
description: "Version for the JDBC driver to download"
type: "str"
keycloak_admin_password:
# line 4 of keycloak/vars/main.yml
required: true
description: "Password for the administration console user account"
type: "str"
keycloak_url:
# line 12 of keycloak/vars/main.yml
default: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
description: "URL for configuration rest calls"
type: "str"
keycloak_management_url:
# line 13 of keycloak/vars/main.yml
default: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
description: "URL for management console rest calls"
type: "str"

View File

@@ -1,3 +1,27 @@
---
collections: collections:
- middleware_automation.redhat_csp_download - middleware_automation.redhat_csp_download
- middleware_automation.jcliff - 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
company: Red Hat, Inc.
license: Apache License 2.0
min_ansible_version: "2.9"
platforms:
- name: EL
versions:
- 8
galaxy_tags:
- keycloak
- redhat
- rhel
- rhn
- sso

View File

@@ -1,75 +0,0 @@
---
- assert:
that:
- zipfile_dest is defined
- rhn_id_file is defined
- rhn_username is defined
- rhn_password is defined
quiet: true
- set_fact:
rhn_download_url: "{{ keycloak_rhsso_base_url }}{{ rhn_id_file }}"
- name: "Check zipfile dest directory {{ zipfile_dest }}"
stat:
path: "{{ zipfile_dest }}"
register: archive_path
- name: "Install zipfile from RHN: {{ rhn_download_url }}"
redhat_csp_download:
url: "{{ rhn_download_url }}"
dest: "{{ zipfile_dest }}"
username: "{{ rhn_username }}"
password: "{{ rhn_password }}"
no_log: "{{ omit_rhn_output | default(true) }}"
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- name: "Check zipfile dest directory {{ zipfile_dest }}"
stat:
path: "{{ zipfile_dest }}"
register: path_to_downloaded_artefact
- block:
- file:
path: "{{ work_dir }}"
state: directory
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
- name: "Check directory {{ target_dir }}"
stat:
path: "{{ target_dir }}"
register: target_dir_state
- assert:
that:
- target_dir_state is defined
- target_dir_state.stat is defined
fail_msg: "Directory layout for {{ target_dir }} is invalid."
quiet: true
- name: "Decompress {{ zipfile_dest }} into {{ work_dir }} (results in {{ target_dir }}."
unarchive:
src: "{{ zipfile_dest }}"
dest: "{{ work_dir }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_user }}"
remote_src: yes
creates: "{{ target_dir }}"
when:
- not target_dir_state.stat.exists
- debug:
msg: "{{ target_dir }} already exists, skipping decompressing {{ zipfile_dest }}"
when:
- target_dir_state.stat.exists
when:
- path_to_downloaded_artefact is defined
- path_to_downloaded_artefact.stat is defined
- path_to_downloaded_artefact.stat.exists
- target_dir is defined
- work_dir is defined

View File

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

View File

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

View File

@@ -7,12 +7,12 @@
- name: Enable and start the firewalld service - name: Enable and start the firewalld service
become: yes become: yes
systemd: ansible.builtin.systemd:
name: firewalld name: firewalld
enabled: yes enabled: yes
state: started state: started
- name: Configure firewall for jdg ports - name: Configure firewall for keycloak ports
become: yes become: yes
firewalld: firewalld:
port: "{{ item }}" port: "{{ item }}"
@@ -24,4 +24,5 @@
- "{{ keycloak_https_port }}/tcp" - "{{ keycloak_https_port }}/tcp"
- "{{ keycloak_management_http_port }}/tcp" - "{{ keycloak_management_http_port }}/tcp"
- "{{ keycloak_management_https_port }}/tcp" - "{{ keycloak_management_https_port }}/tcp"
- "8009/tcp" - "{{ keycloak_jgroups_port }}/tcp"
- "{{ keycloak_ajp_port }}/tcp"

View File

@@ -1,5 +1,6 @@
--- ---
- assert: - name: Validate parameters
ansible.builtin.assert:
that: that:
- keycloak_jboss_home is defined - keycloak_jboss_home is defined
- keycloak_service_user is defined - keycloak_service_user is defined
@@ -9,39 +10,34 @@
- keycloak_version is defined - keycloak_version is defined
quiet: true quiet: true
- set_fact: - name: Check for an existing deployment
keycloak_service_group: "{{ keycloak_service_user }}"
when:
- not keycloak_service_group is defined
- name: check for an existing deployment
become: yes become: yes
stat: ansible.builtin.stat:
path: "{{ keycloak_jboss_home }}" path: "{{ keycloak_jboss_home }}"
register: existing_deploy register: existing_deploy
- block: - block:
- name: stop the old keycloak service - name: Stop the old keycloak service
become: yes become: yes
ignore_errors: yes ignore_errors: yes
systemd: ansible.builtin.systemd:
name: keycloak name: keycloak
state: stopped state: stopped
- name: remove the old Keycloak deployment - name: Remove the old Keycloak deployment
become: yes become: yes
file: ansible.builtin.file:
path: "{{ keycloak_jboss_home }}" path: "{{ keycloak_jboss_home }}"
state: absent state: absent
when: existing_deploy.stat.exists and keycloak_force_install|bool 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 become: yes
stat: ansible.builtin.stat:
path: "{{ keycloak_jboss_home }}" path: "{{ keycloak_jboss_home }}"
- name: create Keycloak service user/group - name: create Keycloak service user/group
become: yes become: yes
user: ansible.builtin.user:
name: "{{ keycloak_service_user }}" name: "{{ keycloak_service_user }}"
home: /opt/keycloak home: /opt/keycloak
system: yes system: yes
@@ -49,73 +45,131 @@
- name: create Keycloak install location - name: create Keycloak install location
become: yes become: yes
file: ansible.builtin.file:
dest: "{{ keycloak_dest }}" dest: "{{ keycloak_dest }}"
state: directory state: directory
owner: "{{ keycloak_service_user }}" owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}" group: "{{ keycloak_service_group }}"
mode: 0750 mode: 0750
- block: ## check remote archive
- set_fact: - name: Set download archive path
archive: "{{ keycloak_dest }}/{{ keycloak_archive }}" ansible.builtin.set_fact:
- name: "Check archive directory {{ archive }}" archive: "{{ keycloak_dest }}/{{ keycloak.bundle }}"
stat:
path: "{{ archive }}"
register: archive_path
- name: download Keycloak archive to target - name: Check download archive path
get_url: ansible.builtin.stat:
url: "{{ keycloak_download_url }}" path: "{{ archive }}"
dest: "{{ keycloak_dest }}" register: archive_path
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- name: extract Keycloak archive on target ## download to controller
unarchive: - name: Check local download archive path
remote_src: yes ansible.builtin.stat:
src: "{{ archive }}" path: "{{ lookup('env', 'PWD') }}"
dest: "{{ keycloak_dest }}" register: local_path
creates: "{{ keycloak_jboss_home }}" delegate_to: localhost
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}" - name: Download keycloak archive
notify: ansible.builtin.get_url:
- restart keycloak url: "{{ keycloak_download_url }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
delegate_to: localhost
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- not keycloak_rhsso_enable
- not keycloak_offline_install
- name: Perform download from RHN
middleware_automation.redhat_csp_download.redhat_csp_download:
url: "{{ keycloak_rhsso_download_url }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
username: "{{ rhn_username }}"
password: "{{ rhn_password }}"
no_log: "{{ omit_rhn_output | default(true) }}"
delegate_to: localhost
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- keycloak_rhsso_enable
- not keycloak_offline_install
- keycloak_rhn_url in keycloak_rhsso_download_url
- name: Download rhsso archive from alternate location
ansible.builtin.get_url:
url: "{{ keycloak_rhsso_download_url }}"
dest: "{{ local_path.stat.path }}/{{ keycloak.bundle }}"
delegate_to: localhost
when:
- archive_path is defined
- archive_path.stat is defined
- not archive_path.stat.exists
- keycloak_rhsso_enable
- not keycloak_offline_install
- not keycloak_rhn_url in keycloak_rhsso_download_url
- 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 become: yes
when: not keycloak_rhsso_enable
- block: - name: "Check target directory: {{ keycloak.home }}"
- assert: ansible.builtin.stat:
that: path: "{{ keycloak.home }}"
- rhsso_rhn_id is defined register: path_to_workdir
quiet: true
fail_msg: "Can't install RHSSO without RHN ID."
- name: create download directory
file:
path: /opt/apps
state: directory
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
mode: 0750
- include_tasks: download_from_rhn.yml
vars:
rhn_id_file: "{{ rhsso_rhn_id }}"
zipfile_dest: "{{ keycloak_dest }}/{{ keycloak_rhsso_archive }}"
work_dir: "{{ keycloak_dest }}"
target_dir: "{{ keycloak_jboss_home }}"
become: yes become: yes
when: keycloak_rhsso_enable
- name: "Extract {{ 'Red Hat Single Sign-On' if keycloak_rhsso_enable else 'Keycloak' }} archive on target"
ansible.builtin.unarchive:
remote_src: yes
src: "{{ archive }}"
dest: "{{ keycloak_dest }}"
creates: "{{ keycloak.home }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
become: yes
when:
- new_version_downloaded.changed or not path_to_workdir.stat.exists
notify:
- restart keycloak
- name: Inform decompression was not executed
ansible.builtin.debug:
msg: "{{ keycloak.home }} already exists and version unchanged, skipping decompression"
when:
- not new_version_downloaded.changed and path_to_workdir.stat.exists
- name: "Reown installation directory to {{ keycloak_service_user }}"
ansible.builtin.file:
path: "{{ keycloak.home }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
recurse: true
become: yes
changed_when: false
# driver and configuration
- name: "Install {{ keycloak_jdbc_engine }} driver" - name: "Install {{ keycloak_jdbc_engine }} driver"
include_role: ansible.builtin.include_role:
name: wildfly_driver name: middleware_automation.wildfly.wildfly_driver
tasks_from: jdbc_driver.yml
vars: vars:
wildfly_user: "{{ keycloak_service_user }}" wildfly_user: "{{ keycloak_service_user }}"
jdbc_driver_module_dir: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}" jdbc_driver_module_dir: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_dir }}"
@@ -126,11 +180,11 @@
jdbc_driver_module_name: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}" jdbc_driver_module_name: "{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}"
when: keycloak_jdbc[keycloak_jdbc_engine].enabled when: keycloak_jdbc[keycloak_jdbc_engine].enabled
- name: "Deploy Keycloak's standalone.xml" - name: "Deploy {{ keycloak.service_name }} config to {{ keycloak_config_path_to_standalone_xml }}"
become: yes become: yes
template: ansible.builtin.template:
src: "{{ 'templates/standalone-rhsso.xml.j2' if keycloak_rhsso_enable else 'templates/standalone.xml.j2' }}" src: templates/standalone.xml.j2
dest: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml" dest: "{{ keycloak_config_path_to_standalone_xml }}"
owner: "{{ keycloak_service_user }}" owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}" group: "{{ keycloak_service_group }}"
mode: 0640 mode: 0640
@@ -138,11 +192,11 @@
- restart keycloak - restart keycloak
when: not keycloak_remotecache.enabled when: not keycloak_remotecache.enabled
- name: "Deploy Keycloak's standalone.xml with remote cache store" - name: "Deploy {{ keycloak.service_name }} config with remote cache store to {{ keycloak_config_path_to_standalone_xml }}"
become: yes become: yes
template: ansible.builtin.template:
src: "{{ 'templates/standalone-rhsso-jdg.xml.j2' if keycloak_rhsso_enable else 'templates/standalone-infinispan.xml.j2' }}" src: templates/standalone-infinispan.xml.j2
dest: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml" dest: "{{ keycloak_config_path_to_standalone_xml }}"
owner: "{{ keycloak_service_user }}" owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}" group: "{{ keycloak_service_group }}"
mode: 0640 mode: 0640

View File

@@ -1,18 +1,26 @@
--- ---
# tasks file for keycloak # tasks file for keycloak
- name: Prerequisites - name: Check prerequisites
include_tasks: prereqs.yml ansible.builtin.include_tasks: prereqs.yml
tags: tags:
- prereqs - prereqs
- include_tasks: tasks/install.yml - name: Include install tasks
ansible.builtin.include_tasks: tasks/install.yml
- include_tasks: tasks/systemd.yml - name: Include systemd tasks
ansible.builtin.include_tasks: tasks/systemd.yml
- name: Link default logs directory
ansible.builtin.file:
state: link
src: "{{ keycloak_jboss_home }}/standalone/log"
dest: /var/log/keycloak
- block: - block:
- name: Check admin credentials by generating a token - name: Check admin credentials by generating a token
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token" url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
method: POST method: POST
body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password" body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password"
@@ -22,14 +30,22 @@
retries: 2 retries: 2
delay: 2 delay: 2
rescue: rescue:
- name: create Keycloak admin user - name: "Create {{ keycloak.service_name }} admin user"
command: ansible.builtin.command:
args: args:
argv: argv:
- "{{ keycloak_jboss_home }}/bin/add-user-keycloak.sh" - "{{ keycloak_jboss_home }}/bin/add-user-keycloak.sh"
- -rmaster - "-rmaster"
- -u{{ keycloak_admin_user }} - "-u{{ keycloak_admin_user }}"
- -p{{ keycloak_admin_password }} - "-p{{ keycloak_admin_password }}"
changed_when: yes
become: yes become: yes
- name: restart keycloak - name: "Restart {{ keycloak.service_name }}"
include_tasks: tasks/restart_keycloak.yml ansible.builtin.include_tasks: tasks/restart_keycloak.yml
- 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

@@ -1,29 +1,30 @@
--- ---
- name: "Validate configuration" - name: Validate configuration
assert: ansible.builtin.assert:
that: that:
- (keycloak_ha_enabled and keycloak_db_enabled) or (not keycloak_ha_enabled and keycloak_db_enabled) or (not keycloak_ha_enabled and not keycloak_db_enabled) - (keycloak_ha_enabled and keycloak_db_enabled) or (not keycloak_ha_enabled and keycloak_db_enabled) or (not keycloak_ha_enabled and not keycloak_db_enabled)
quiet: True quiet: True
fail_msg: "Cannot install HA setup without a backend database service. Check keycloak_ha_enabled and keycloak_db_enabled" fail_msg: "Cannot install HA setup without a backend database service. Check keycloak_ha_enabled and keycloak_db_enabled"
success_msg: "{{ 'Configuring HA' if keycloak_ha_enabled else 'Configuring standalone' }}" success_msg: "{{ 'Configuring HA' if keycloak_ha_enabled else 'Configuring standalone' }}"
- name: "Validate credentials" - name: Validate credentials
assert: ansible.builtin.assert:
that: that:
- (rhn_username is defined and rhsso_rhn_id is defined) or rhsso_rhn_id is not defined - (rhn_username is defined and keycloak_rhsso_enable) or not keycloak_rhsso_enable or keycloak_offline_install
- (rhn_password is defined and rhsso_rhn_id is defined) or rhsso_rhn_id is not defined - (rhn_password is defined and keycloak_rhsso_enable) or not keycloak_rhsso_enable or keycloak_offline_install
quiet: True quiet: True
fail_msg: "Cannot install Red Hat SSO without RHN credentials. Check rhn_username and rhn_password are defined" 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 rhsso_rhn_id is defined else 'Installing keycloak.org' }}" success_msg: "{{ 'Installing Red Hat Single Sign-On' if keycloak_rhsso_enable else 'Installing keycloak.org' }}"
- set_fact: - name: Set required packages facts
ansible.builtin.set_fact:
required_packages: required_packages:
- "{{ jvm_package | default('java-1.8.0-openjdk-devel') }}" - "{{ jvm_package }}"
- unzip - unzip
- procps-ng - procps-ng
- initscripts - initscripts
- name: "Ensures required packages are installed" - name: Ensures required packages are installed
ansible.builtin.include_tasks: fastpackages/install.yml ansible.builtin.include_tasks: fastpackages/install.yml
vars: vars:
packages_list: "{{ required_packages }}" packages_list: "{{ required_packages }}"

View File

@@ -1,6 +1,6 @@
--- ---
- name: "Restart and enable keycloack service" - name: "Restart and enable keycloack service"
systemd: ansible.builtin.systemd:
name: keycloak name: keycloak
enabled: yes enabled: yes
state: restarted state: restarted

View File

@@ -1,6 +1,6 @@
--- ---
- name: "Stop SSO service" - name: "Stop SSO service"
systemd: ansible.builtin.systemd:
name: keycloak name: keycloak
enabled: yes enabled: yes
state: stopped state: stopped

View File

@@ -1,6 +1,6 @@
- name: configure keycloak service script wrapper - name: configure keycloak service script wrapper
become: yes become: yes
template: ansible.builtin.template:
src: keycloak-service.sh.j2 src: keycloak-service.sh.j2
dest: "{{ keycloak_dest }}/keycloak-service.sh" dest: "{{ keycloak_dest }}/keycloak-service.sh"
owner: root owner: root
@@ -11,7 +11,7 @@
- name: configure sysconfig file for keycloak service - name: configure sysconfig file for keycloak service
become: yes become: yes
template: ansible.builtin.template:
src: keycloak-sysconfig.j2 src: keycloak-sysconfig.j2
dest: /etc/sysconfig/keycloak dest: /etc/sysconfig/keycloak
owner: root owner: root
@@ -21,7 +21,7 @@
- restart keycloak - restart keycloak
- name: configure systemd unit file for keycloak service - name: configure systemd unit file for keycloak service
template: ansible.builtin.template:
src: keycloak.service.j2 src: keycloak.service.j2
dest: /etc/systemd/system/keycloak.service dest: /etc/systemd/system/keycloak.service
owner: root owner: root
@@ -34,32 +34,35 @@
- name: reload systemd - name: reload systemd
become: yes become: yes
systemd: ansible.builtin.systemd:
daemon_reload: yes daemon_reload: yes
when: systemdunit.changed when: systemdunit.changed
- name: start keycloak - name: start keycloak
systemd: ansible.builtin.systemd:
name: keycloak name: keycloak
enabled: yes enabled: yes
state: started state: started
become: yes become: yes
- command: "systemctl status keycloak" - name: Check service status
ansible.builtin.command: "systemctl status keycloak"
register: keycloak_service_status register: keycloak_service_status
changed_when: False changed_when: False
- assert: - name: Verify service status
ansible.builtin.assert:
that: that:
- keycloak_service_status is defined - keycloak_service_status is defined
- keycloak_service_status.stdout is defined - keycloak_service_status.stdout is defined
- meta: flush_handlers - name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: Wait until Keycloak becomes active - name: "Wait until Keycloak becomes active {{ keycloak.health_url }}"
uri: ansible.builtin.uri:
url: "{{ keycloak_management_url }}/health" url: "{{ keycloak.health_url }}"
register: keycloak_status register: keycloak_status
until: keycloak_status.status == 200 until: keycloak_status.status == 200
retries: 20 retries: 25
delay: 10 delay: 10

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<server xmlns="urn:jboss:domain:16.0"> <server xmlns="urn:jboss:domain:10.0">
<extensions> <extensions>
<extension module="org.jboss.as.clustering.infinispan"/> <extension module="org.jboss.as.clustering.infinispan"/>
<extension module="org.jboss.as.clustering.jgroups"/> <extension module="org.jboss.as.clustering.jgroups"/>
@@ -23,9 +23,10 @@
<extension module="org.wildfly.extension.bean-validation"/> <extension module="org.wildfly.extension.bean-validation"/>
<extension module="org.wildfly.extension.core-management"/> <extension module="org.wildfly.extension.core-management"/>
<extension module="org.wildfly.extension.elytron"/> <extension module="org.wildfly.extension.elytron"/>
<extension module="org.wildfly.extension.health"/>
<extension module="org.wildfly.extension.io"/> <extension module="org.wildfly.extension.io"/>
<extension module="org.wildfly.extension.metrics"/> <extension module="org.wildfly.extension.microprofile.config-smallrye"/>
<extension module="org.wildfly.extension.microprofile.health-smallrye"/>
<extension module="org.wildfly.extension.microprofile.metrics-smallrye"/>
<extension module="org.wildfly.extension.request-controller"/> <extension module="org.wildfly.extension.request-controller"/>
<extension module="org.wildfly.extension.security.manager"/> <extension module="org.wildfly.extension.security.manager"/>
<extension module="org.wildfly.extension.undertow"/> <extension module="org.wildfly.extension.undertow"/>
@@ -44,7 +45,8 @@
<security-realm name="ApplicationRealm"> <security-realm name="ApplicationRealm">
<server-identities> <server-identities>
<ssl> <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"/> <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> </ssl>
</server-identities> </server-identities>
<authentication> <authentication>
@@ -141,7 +143,7 @@
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/> <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
<subsystem xmlns="urn:jboss:domain:core-management:1.0"/> <subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
<subsystem xmlns="urn:jboss:domain:datasources:6.0"> <subsystem xmlns="urn:jboss:domain:datasources:5.0">
<datasources> <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}}"> <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> <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
@@ -152,15 +154,15 @@
</security> </security>
</datasource> </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}}"> <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 %} {% if keycloak_jdbc.postgres.enabled %}
<connection-url>{{ keycloak_jdbc[keycloak_jdbc_engine].connection_url }}</connection-url> <connection-url>{{ keycloak_jdbc.postgres.connection_url }}</connection-url>
<driver>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}</driver> <driver>{{ keycloak_jdbc.postgres.driver_module_name }}</driver>
<pool> <pool>
<max-pool-size>20</max-pool-size> <max-pool-size>20</max-pool-size>
</pool> </pool>
<security> <security>
<user-name>{{ keycloak_jdbc[keycloak_jdbc_engine].db_user }}</user-name> <user-name>{{ keycloak_jdbc.postgres.db_user }}</user-name>
<password>{{ keycloak_jdbc[keycloak_jdbc_engine].db_password }}</password> <password>{{ keycloak_jdbc.postgres.db_password }}</password>
</security> </security>
{% else %} {% else %}
<connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url> <connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
@@ -172,10 +174,10 @@
{% endif %} {% endif %}
</datasource> </datasource>
<drivers> <drivers>
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %} {% if keycloak_jdbc.postgres.enabled %}
<driver name="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}" module="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}"> <driver name="{{ keycloak_jdbc.postgres.driver_module_name }}" module="{{ keycloak_jdbc.postgres.driver_module_name }}">
<driver-class>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_class }}</driver-class> <driver-class>org.postgresql.Driver</driver-class>
<xa-datasource-class>{{ keycloak_jdbc[keycloak_jdbc_engine].xa_datasource_class }}</xa-datasource-class> <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver> </driver>
{% endif %} {% endif %}
<driver name="h2" module="com.h2database.h2"> <driver name="h2" module="com.h2database.h2">
@@ -187,7 +189,7 @@
<subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0"> <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}"/> <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>
<subsystem xmlns="urn:jboss:domain:ee:6.0"> <subsystem xmlns="urn:jboss:domain:ee:4.0">
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement> <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<concurrent> <concurrent>
<context-services> <context-services>
@@ -197,15 +199,17 @@
<managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/> <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
</managed-thread-factories> </managed-thread-factories>
<managed-executor-services> <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-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/>
</managed-executor-services> </managed-executor-services>
<managed-scheduled-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-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
</managed-scheduled-executor-services> </managed-scheduled-executor-services>
</concurrent> </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"/> <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>
<subsystem xmlns="urn:jboss:domain:ejb3:9.0"> <subsystem xmlns="urn:jboss:domain:ejb3:6.0">
<session-bean> <session-bean>
<stateless> <stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
@@ -232,7 +236,7 @@
<file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/> <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
</data-stores> </data-stores>
</timer-service> </timer-service>
<remote cluster="ejb" connectors="http-remoting-connector" thread-pool-name="default"> <remote cluster="ejb" connector-ref="http-remoting-connector" thread-pool-name="default">
<channel-creation-options> <channel-creation-options>
<option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/> <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
</channel-creation-options> </channel-creation-options>
@@ -248,7 +252,7 @@
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/> <statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/> <log-system-exceptions value="true"/>
</subsystem> </subsystem>
<subsystem xmlns="urn:wildfly:elytron:13.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto"> <subsystem xmlns="urn:wildfly:elytron:8.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
<providers> <providers>
<aggregate-providers name="combined-providers"> <aggregate-providers name="combined-providers">
<providers name="elytron"/> <providers name="elytron"/>
@@ -357,7 +361,7 @@
</key-store> </key-store>
</key-stores> </key-stores>
<key-managers> <key-managers>
<key-manager name="applicationKM" key-store="applicationKS" generate-self-signed-certificate-host="localhost"> <key-manager name="applicationKM" key-store="applicationKS">
<credential-reference clear-text="password"/> <credential-reference clear-text="password"/>
</key-manager> </key-manager>
</key-managers> </key-managers>
@@ -366,25 +370,24 @@
</server-ssl-contexts> </server-ssl-contexts>
</tls> </tls>
</subsystem> </subsystem>
<subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/> <subsystem xmlns="urn:jboss:domain:infinispan:9.0">
<subsystem xmlns="urn:jboss:domain:infinispan:12.0"> <cache-container name="ejb" default-cache="passivation" aliases="sfsb" module="org.wildfly.clustering.ejb.infinispan">
<cache-container name="ejb" default-cache="passivation" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan">
<local-cache name="passivation"> <local-cache name="passivation">
<locking isolation="REPEATABLE_READ"/> <locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
<file-store passivation="true" purge="false"/> <file-store passivation="true" purge="false"/>
</local-cache> </local-cache>
</cache-container> </cache-container>
<cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan"> <cache-container name="keycloak" module="org.keycloak.keycloak-model-infinispan">
<transport lock-timeout="60000"/> <transport lock-timeout="60000"/>
<local-cache name="realms"> <local-cache name="realms">
<heap-memory size="10000"/> <object-memory size="10000"/>
</local-cache> </local-cache>
<local-cache name="users"> <local-cache name="users">
<heap-memory size="10000"/> <object-memory size="10000"/>
</local-cache> </local-cache>
<local-cache name="authenticationSessions"/> <local-cache name="authenticationSessions"/>
{% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens" ] %} {% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens" ] %}
<distributed-cache name="{{ cachename }}"> <distributed-cache name="{{ cachename }}">
<remote-store cache="{{ cachename }}" <remote-store cache="{{ cachename }}"
remote-servers="remote-cache" remote-servers="remote-cache"
@@ -405,9 +408,10 @@
<property name="infinispan.client.hotrod.trust_store_file_name">{{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}</property> <property name="infinispan.client.hotrod.trust_store_file_name">{{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}</property>
<property name="infinispan.client.hotrod.trust_store_type">JKS</property> <property name="infinispan.client.hotrod.trust_store_type">JKS</property>
<property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password | default("changeme") }}</property> <property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password | default("changeme") }}</property>
<property name="infinispan.client.hotrod.client_intelligence">TOPOLOGY_AWARE</property>
</remote-store> </remote-store>
</distributed-cache> </distributed-cache>
{% endfor %} {% endfor %}
<replicated-cache name="work"> <replicated-cache name="work">
<remote-store cache="work" <remote-store cache="work"
remote-servers="remote-cache" remote-servers="remote-cache"
@@ -428,22 +432,23 @@
<property name="infinispan.client.hotrod.trust_store_file_name">{{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}</property> <property name="infinispan.client.hotrod.trust_store_file_name">{{ keycloak_remotecache.trust_store_path | default('/etc/truststore/truststore.jks') }}</property>
<property name="infinispan.client.hotrod.trust_store_type">JKS</property> <property name="infinispan.client.hotrod.trust_store_type">JKS</property>
<property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password | default("changeme") }}</property> <property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password | default("changeme") }}</property>
<property name="infinispan.client.hotrod.client_intelligence">TOPOLOGY_AWARE</property>
</remote-store> </remote-store>
</replicated-cache> </replicated-cache>
<local-cache name="authorization"> <local-cache name="authorization">
<heap-memory size="10000"/> <object-memory size="10000"/>
</local-cache> </local-cache>
<local-cache name="keys"> <local-cache name="keys">
<heap-memory size="1000"/> <object-memory size="1000"/>
<expiration max-idle="3600000"/> <expiration max-idle="3600000"/>
</local-cache> </local-cache>
</cache-container> </cache-container>
<cache-container name="server" default-cache="default" modules="org.wildfly.clustering.server"> <cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
<local-cache name="default"> <local-cache name="default">
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
</local-cache> </local-cache>
</cache-container> </cache-container>
<cache-container name="web" default-cache="passivation" modules="org.wildfly.clustering.web.infinispan"> <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
<local-cache name="passivation"> <local-cache name="passivation">
<locking isolation="REPEATABLE_READ"/> <locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
@@ -455,13 +460,13 @@
</local-cache> </local-cache>
<local-cache name="routing"/> <local-cache name="routing"/>
</cache-container> </cache-container>
<cache-container name="hibernate" modules="org.infinispan.hibernate-cache"> <cache-container name="hibernate" module="org.infinispan.hibernate-cache">
<local-cache name="entity"> <local-cache name="entity">
<heap-memory size="10000"/> <object-memory size="10000"/>
<expiration max-idle="100000"/> <expiration max-idle="100000"/>
</local-cache> </local-cache>
<local-cache name="local-query"> <local-cache name="local-query">
<heap-memory size="10000"/> <object-memory size="10000"/>
<expiration max-idle="100000"/> <expiration max-idle="100000"/>
</local-cache> </local-cache>
<local-cache name="timestamps"/> <local-cache name="timestamps"/>
@@ -471,7 +476,7 @@
<worker name="default"/> <worker name="default"/>
<buffer-pool name="default"/> <buffer-pool name="default"/>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:jaxrs:2.0"/> <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
<subsystem xmlns="urn:jboss:domain:jca:5.0"> <subsystem xmlns="urn:jboss:domain:jca:5.0">
<archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/> <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
<bean-validation enabled="true"/> <bean-validation enabled="true"/>
@@ -491,28 +496,22 @@
</default-workmanager> </default-workmanager>
<cached-connection-manager/> <cached-connection-manager/>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:jgroups:8.0"> <subsystem xmlns="urn:jboss:domain:jgroups:7.0">
<channels default="ee"> <channels default="ee">
<channel name="ee" stack="tcp" cluster="ejb"/> <channel name="ee" stack="tcp" cluster="ejb"/>
</channels> </channels>
<stacks> <stacks>
<stack name="tcp"> <stack name="tcp">
<transport site="${jboss.node.name}" type="TCP" socket-binding="jgroups-tcp"/> <transport site="${jboss.node.name}" type="TCP" socket-binding="jgroups-tcp"/>
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<protocol type="JDBC_PING"> <protocol type="JDBC_PING">
<property name="datasource_jndi_name">java:jboss/datasources/KeycloakDS</property> <property name="datasource_jndi_name">java:jboss/datasources/KeycloakDS</property>
<property name="initialize_sql"> <property name="initialize_sql">{{ keycloak_jdbc[keycloak_jdbc_engine].initialize_db }}</property>
CREATE TABLE IF NOT EXISTS JGROUPSPING (
own_addr varchar(200) NOT NULL,
cluster_name varchar(200) NOT NULL,
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
ping_data varbinary(5000) DEFAULT NULL,
PRIMARY KEY (own_addr, cluster_name))
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
</property>
<property name="insert_single_sql">INSERT INTO JGROUPSPING (own_addr, cluster_name, ping_data) values (?, ?, ?)</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="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> <property name="select_all_pingdata_sql">SELECT ping_data FROM JGROUPSPING WHERE cluster_name=?</property>
</protocol> </protocol>
{% endif %}
<protocol type="MERGE3"/> <protocol type="MERGE3"/>
<protocol type="FD_SOCK"/> <protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/> <protocol type="FD_ALL"/>
@@ -534,7 +533,7 @@
<remoting-connector/> <remoting-connector/>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:jpa:1.1"> <subsystem xmlns="urn:jboss:domain:jpa:1.1">
<jpa default-extended-persistence-inheritance="DEEP"/> <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1"> <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
<web-context>auth</web-context> <web-context>auth</web-context>
@@ -610,18 +609,17 @@
<default-provider>default</default-provider> <default-provider>default</default-provider>
<provider name="default" enabled="true"> <provider name="default" enabled="true">
<properties> <properties>
<property name="frontendUrl" value="${keycloak.frontendUrl:}"/> <property name="frontendUrl" value="{{ keycloak_modcluster.frontend_url }}"/>
<property name="forceBackendUrlToFrontendUrl" value="false"/> <property name="forceBackendUrlToFrontendUrl" value="true"/>
</properties> </properties>
</provider> </provider>
</spi> </spi>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:mail:4.0"> <subsystem xmlns="urn:jboss:domain:mail:3.0">
<mail-session name="default" jndi-name="java:jboss/mail/Default"> <mail-session name="default" jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/> <smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session> </mail-session>
</subsystem> </subsystem>
<subsystem xmlns="urn:wildfly:metrics:1.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:jboss}"/>
{% if keycloak_modcluster.enabled %} {% if keycloak_modcluster.enabled %}
<subsystem xmlns="urn:jboss:domain:modcluster:5.0"> <subsystem xmlns="urn:jboss:domain:modcluster:5.0">
<proxy name="default" advertise-socket="modcluster" listener="ajp" proxies="proxy1"> <proxy name="default" advertise-socket="modcluster" listener="ajp" proxies="proxy1">
@@ -677,7 +675,7 @@
</maximum-set> </maximum-set>
</deployment-permissions> </deployment-permissions>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:transactions:6.0"> <subsystem xmlns="urn:jboss:domain:transactions:5.0">
<core-environment node-identifier="{{ inventory_hostname | default('${jboss.tx.node.id:1}') }}"> <core-environment node-identifier="{{ inventory_hostname | default('${jboss.tx.node.id:1}') }}">
<process-id> <process-id>
<uuid/> <uuid/>
@@ -687,7 +685,9 @@
<coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"/> <coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<object-store path="tx-object-store" relative-to="jboss.server.data.dir"/> <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>
</subsystem> </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}}"> <subsystem xmlns="urn:jboss:domain:undertow:10.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"/> <buffer-cache name="default"/>
<server name="default-server"> <server name="default-server">
<ajp-listener name="ajp" socket-binding="ajp"/> <ajp-listener name="ajp" socket-binding="ajp"/>
@@ -712,13 +712,23 @@
</filters> </filters>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:weld:4.0"/> <subsystem xmlns="urn:jboss:domain:weld:4.0"/>
</profile> <subsystem xmlns="urn:wildfly:microprofile-config-smallrye:1.0"/>
<subsystem xmlns="urn:wildfly:microprofile-health-smallrye:2.0" security-enabled="false"
empty-liveness-checks-status="${env.MP_HEALTH_EMPTY_LIVENESS_CHECKS_STATUS:UP}"
empty-readiness-checks-status="${env.MP_HEALTH_EMPTY_READINESS_CHECKS_STATUS:UP}"/>
<subsystem xmlns="urn:wildfly:microprofile-metrics-smallrye:2.0" security-enabled="false"
exposed-subsystems="*" prefix="${wildfly.metrics.prefix:wildfly}"/>
</profile>
<interfaces> <interfaces>
<interface name="management"> <interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/> <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface> </interface>
<interface name="jgroups"> <interface name="jgroups">
{% if ansible_default_ipv4 is defined %}
<subnet-match value="{{ (ansible_default_ipv4.network + '/' + ansible_default_ipv4.netmask) | ipaddr('net') }}"/> <subnet-match value="{{ (ansible_default_ipv4.network + '/' + ansible_default_ipv4.netmask) | ipaddr('net') }}"/>
{% else %}
<any-address />
{% endif %}
</interface> </interface>
<interface name="public"> <interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/> <inet-address value="${jboss.bind.address:127.0.0.1}"/>

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<server xmlns="urn:jboss:domain:16.0"> <server xmlns="urn:jboss:domain:10.0">
<extensions> <extensions>
<extension module="org.jboss.as.clustering.infinispan"/> <extension module="org.jboss.as.clustering.infinispan"/>
<extension module="org.jboss.as.connector"/> <extension module="org.jboss.as.connector"/>
@@ -22,9 +22,10 @@
<extension module="org.wildfly.extension.bean-validation"/> <extension module="org.wildfly.extension.bean-validation"/>
<extension module="org.wildfly.extension.core-management"/> <extension module="org.wildfly.extension.core-management"/>
<extension module="org.wildfly.extension.elytron"/> <extension module="org.wildfly.extension.elytron"/>
<extension module="org.wildfly.extension.health"/>
<extension module="org.wildfly.extension.io"/> <extension module="org.wildfly.extension.io"/>
<extension module="org.wildfly.extension.metrics"/> <extension module="org.wildfly.extension.microprofile.config-smallrye"/>
<extension module="org.wildfly.extension.microprofile.health-smallrye"/>
<extension module="org.wildfly.extension.microprofile.metrics-smallrye"/>
<extension module="org.wildfly.extension.request-controller"/> <extension module="org.wildfly.extension.request-controller"/>
<extension module="org.wildfly.extension.security.manager"/> <extension module="org.wildfly.extension.security.manager"/>
<extension module="org.wildfly.extension.undertow"/> <extension module="org.wildfly.extension.undertow"/>
@@ -43,7 +44,8 @@
<security-realm name="ApplicationRealm"> <security-realm name="ApplicationRealm">
<server-identities> <server-identities>
<ssl> <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"/> <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> </ssl>
</server-identities> </server-identities>
<authentication> <authentication>
@@ -128,7 +130,7 @@
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/> <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
<subsystem xmlns="urn:jboss:domain:core-management:1.0"/> <subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
<subsystem xmlns="urn:jboss:domain:datasources:6.0"> <subsystem xmlns="urn:jboss:domain:datasources:5.0">
<datasources> <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}}"> <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> <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
@@ -156,7 +158,7 @@
<subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0"> <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}"/> <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>
<subsystem xmlns="urn:jboss:domain:ee:6.0"> <subsystem xmlns="urn:jboss:domain:ee:4.0">
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement> <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<concurrent> <concurrent>
<context-services> <context-services>
@@ -166,15 +168,17 @@
<managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/> <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
</managed-thread-factories> </managed-thread-factories>
<managed-executor-services> <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-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/>
</managed-executor-services> </managed-executor-services>
<managed-scheduled-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-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
</managed-scheduled-executor-services> </managed-scheduled-executor-services>
</concurrent> </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"/> <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>
<subsystem xmlns="urn:jboss:domain:ejb3:9.0"> <subsystem xmlns="urn:jboss:domain:ejb3:6.0">
<session-bean> <session-bean>
<stateless> <stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
@@ -201,7 +205,7 @@
<file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/> <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
</data-stores> </data-stores>
</timer-service> </timer-service>
<remote cluster="ejb" connectors="http-remoting-connector" thread-pool-name="default"> <remote connector-ref="http-remoting-connector" thread-pool-name="default">
<channel-creation-options> <channel-creation-options>
<option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/> <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
</channel-creation-options> </channel-creation-options>
@@ -217,7 +221,130 @@
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/> <statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/> <log-system-exceptions value="true"/>
</subsystem> </subsystem>
<subsystem xmlns="urn:wildfly:elytron:13.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto"> <subsystem xmlns="urn:jboss:domain:io:3.0">
<worker name="default"/>
<buffer-pool name="default"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:infinispan:9.0">
<cache-container name="keycloak">
<local-cache name="realms">
<object-memory size="10000"/>
</local-cache>
<local-cache name="users">
<object-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">
<object-memory size="10000"/>
</local-cache>
<local-cache name="keys">
<object-memory size="1000"/>
<expiration max-idle="3600000"/>
</local-cache>
<local-cache name="actionTokens">
<object-memory size="-1"/>
<expiration max-idle="-1" interval="300000"/>
</local-cache>
</cache-container>
<cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
<local-cache name="default">
<transaction mode="BATCH"/>
</local-cache>
</cache-container>
<cache-container name="web" default-cache="passivation" module="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="ejb" aliases="sfsb" default-cache="passivation" module="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="hibernate" module="org.infinispan.hibernate-cache">
<local-cache name="entity">
<object-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<object-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps"/>
</cache-container>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jaxrs:1.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-datasource="" default-extended-persistence-inheritance="DEEP"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:mail:3.0">
<mail-session name="default" jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
</subsystem>
{% if keycloak_modcluster.enabled %}
<subsystem xmlns="urn:jboss:domain:modcluster:5.0">
<proxy name="default" advertise-socket="modcluster" 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-manager:1.0">
<deployment-permissions>
<maximum-set>
<permission class="java.security.AllPermission"/>
</maximum-set>
</deployment-permissions>
</subsystem>
<subsystem xmlns="urn:wildfly:elytron:8.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
<providers> <providers>
<aggregate-providers name="combined-providers"> <aggregate-providers name="combined-providers">
<providers name="elytron"/> <providers name="elytron"/>
@@ -275,7 +402,6 @@
<permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/> <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.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 class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
</permission-set> </permission-set>
</permission-sets> </permission-sets>
<http> <http>
@@ -317,126 +443,78 @@
</mechanism-provider-filtering-sasl-server-factory> </mechanism-provider-filtering-sasl-server-factory>
<provider-sasl-server-factory name="global"/> <provider-sasl-server-factory name="global"/>
</sasl> </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>
<subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/> <subsystem xmlns="urn:jboss:domain:security:2.0">
<subsystem xmlns="urn:jboss:domain:infinispan:12.0"> <security-domains>
<cache-container name="ejb" default-cache="passivation" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan"> <security-domain name="other" cache-type="default">
<local-cache name="passivation"> <authentication>
<locking isolation="REPEATABLE_READ"/> <login-module code="Remoting" flag="optional">
<transaction mode="BATCH"/> <module-option name="password-stacking" value="useFirstPass"/>
<file-store passivation="true" purge="false"/> </login-module>
</local-cache> <login-module code="RealmDirect" flag="required">
</cache-container> <module-option name="password-stacking" value="useFirstPass"/>
<cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan"> </login-module>
<local-cache name="realms"> </authentication>
<heap-memory size="10000"/> </security-domain>
</local-cache> <security-domain name="jboss-web-policy" cache-type="default">
<local-cache name="users"> <authorization>
<heap-memory size="10000"/> <policy-module code="Delegating" flag="required"/>
</local-cache> </authorization>
<local-cache name="sessions"/> </security-domain>
<local-cache name="authenticationSessions"/> <security-domain name="jaspitest" cache-type="default">
<local-cache name="offlineSessions"/> <authentication-jaspi>
<local-cache name="clientSessions"/> <login-module-stack name="dummy">
<local-cache name="offlineClientSessions"/> <login-module code="Dummy" flag="optional"/>
<local-cache name="loginFailures"/> </login-module-stack>
<local-cache name="work"/> <auth-module code="Dummy"/>
<local-cache name="authorization"> </authentication-jaspi>
<heap-memory size="10000"/> </security-domain>
</local-cache> <security-domain name="jboss-ejb-policy" cache-type="default">
<local-cache name="keys"> <authorization>
<heap-memory size="1000"/> <policy-module code="Delegating" flag="required"/>
<expiration max-idle="3600000"/> </authorization>
</local-cache> </security-domain>
<local-cache name="actionTokens"> </security-domains>
<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>
<subsystem xmlns="urn:jboss:domain:io:3.0"> <subsystem xmlns="urn:jboss:domain:transactions:5.0">
<worker name="default"/> <core-environment node-identifier="${jboss.tx.node.id:1}">
<buffer-pool name="default"/> <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>
<subsystem xmlns="urn:jboss:domain:jaxrs:2.0"/> <subsystem xmlns="urn:jboss:domain:weld:4.0"/>
<subsystem xmlns="urn:jboss:domain:jca:5.0"> <subsystem xmlns="urn:wildfly:microprofile-config-smallrye:1.0"/>
<archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/> <subsystem xmlns="urn:wildfly:microprofile-health-smallrye:2.0" security-enabled="false"
<bean-validation enabled="true"/> empty-liveness-checks-status="${env.MP_HEALTH_EMPTY_LIVENESS_CHECKS_STATUS:UP}" empty-readiness-checks-status="${env.MP_HEALTH_EMPTY_READINESS_CHECKS_STATUS:UP}"/>
<default-workmanager> <subsystem xmlns="urn:wildfly:microprofile-metrics-smallrye:2.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:wildfly}"/>
<short-running-threads> <subsystem xmlns="urn:jboss:domain:undertow:10.0" default-server="default-server" default-virtual-host="default-host"
<core-threads count="50"/> default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
<queue-length count="50"/> <buffer-cache name="default"/>
<max-threads count="50"/> <server name="default-server">
<keepalive-time time="10" unit="seconds"/> <ajp-listener name="ajp" socket-binding="ajp"/>
</short-running-threads> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
<long-running-threads> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<core-threads count="50"/> <host name="default-host" alias="localhost">
<queue-length count="50"/> <location name="/" handler="welcome-content"/>
<max-threads count="50"/> <http-invoker security-realm="ApplicationRealm"/>
<keepalive-time time="10" unit="seconds"/> </host>
</long-running-threads> </server>
</default-workmanager> <servlet-container name="default">
<cached-connection-manager/> <jsp-config/>
</subsystem> <websockets/>
<subsystem xmlns="urn:jboss:domain:jmx:1.3"> </servlet-container>
<expose-resolved-model/> <handlers>
<expose-expression-model/> <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
<remoting-connector/> </handlers>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jpa:1.1">
<jpa default-extended-persistence-inheritance="DEEP"/>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1"> <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
<web-context>auth</web-context> <web-context>auth</web-context>
<providers> <providers>
<provider> <provider>classpath:${jboss.home.dir}/providers/*</provider>
classpath:${jboss.home.dir}/providers/*
</provider>
</providers> </providers>
<master-realm-name>master</master-realm-name> <master-realm-name>master</master-realm-name>
<scheduled-task-interval>900</scheduled-task-interval> <scheduled-task-interval>900</scheduled-task-interval>
@@ -505,103 +583,12 @@
<default-provider>default</default-provider> <default-provider>default</default-provider>
<provider name="default" enabled="true"> <provider name="default" enabled="true">
<properties> <properties>
<property name="frontendUrl" value="${keycloak.frontendUrl:}"/> <property name="frontendUrl" value="{{ keycloak_modcluster.frontend_url }}"/>
<property name="forceBackendUrlToFrontendUrl" value="false"/> <property name="forceBackendUrlToFrontendUrl" value="true"/>
</properties> </properties>
</provider> </provider>
</spi> </spi>
</subsystem> </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-socket="modcluster" 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> </profile>
<interfaces> <interfaces>
<interface name="management"> <interface name="management">
@@ -621,7 +608,7 @@
<socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/> <socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="mail-smtp"> <outbound-socket-binding name="mail-smtp">
<remote-destination host="${jboss.mail.server.host:localhost}" port="${jboss.mail.server.port:25}"/> <remote-destination host="localhost" port="25"/>
</outbound-socket-binding> </outbound-socket-binding>
{% if keycloak_modcluster.enabled %} {% if keycloak_modcluster.enabled %}
<outbound-socket-binding name="proxy1"> <outbound-socket-binding name="proxy1">

View File

@@ -1,4 +1,5 @@
#!/bin/bash -eu #!/bin/bash -eu
# {{ ansible_managed }}
set +u -o pipefail set +u -o pipefail
@@ -22,7 +23,6 @@ readonly KEYCLOAK_HTTP_PORT=${KEYCLOAK_HTTP_PORT}
readonly KEYCLOAK_HTTPS_PORT=${KEYCLOAK_HTTPS_PORT} readonly KEYCLOAK_HTTPS_PORT=${KEYCLOAK_HTTPS_PORT}
readonly KEYCLOAK_MANAGEMENT_HTTP_PORT=${KEYCLOAK_MANAGEMENT_HTTP_PORT} readonly KEYCLOAK_MANAGEMENT_HTTP_PORT=${KEYCLOAK_MANAGEMENT_HTTP_PORT}
readonly KEYCLOAK_MANAGEMENT_HTTPS_PORT=${KEYCLOAK_MANAGEMENT_HTTPS_PORT} readonly KEYCLOAK_MANAGEMENT_HTTPS_PORT=${KEYCLOAK_MANAGEMENT_HTTPS_PORT}
readonly KEYCLOAK_LOGFILE={{ keycloak_service_logfile }}
readonly KEYCLOAK_PIDFILE={{ keycloak_service_pidfile }} readonly KEYCLOAK_PIDFILE={{ keycloak_service_pidfile }}
set -u set -u
@@ -70,7 +70,6 @@ startKeycloak() {
checkEnvVar "${KEYCLOAK_HTTPS_PORT}" 'KEYCLOAK_HTTPS_PORT not provided' 5 checkEnvVar "${KEYCLOAK_HTTPS_PORT}" 'KEYCLOAK_HTTPS_PORT not provided' 5
checkEnvVar "${KEYCLOAK_MANAGEMENT_HTTP_PORT}" 'KEYCLOAK_MANAGEMENT_HTTP_PORT not provided' 6 checkEnvVar "${KEYCLOAK_MANAGEMENT_HTTP_PORT}" 'KEYCLOAK_MANAGEMENT_HTTP_PORT not provided' 6
checkEnvVar "${KEYCLOAK_MANAGEMENT_HTTPS_PORT}" 'KEYCLOAK_MANAGEMENT_HTTPS_PORT not provided' 7 checkEnvVar "${KEYCLOAK_MANAGEMENT_HTTPS_PORT}" 'KEYCLOAK_MANAGEMENT_HTTPS_PORT not provided' 7
checkEnvVar "${KEYCLOAK_LOGFILE}" 'KEYCLOAK_LOGFILE not provided' 8
if [ "$(isKeyCloakRunning)" -eq 1 ]; then if [ "$(isKeyCloakRunning)" -eq 1 ]; then
statusKeycloak statusKeycloak
@@ -82,8 +81,8 @@ startKeycloak() {
-Djboss.management.http.port=${KEYCLOAK_MANAGEMENT_HTTP_PORT} \ -Djboss.management.http.port=${KEYCLOAK_MANAGEMENT_HTTP_PORT} \
-Djboss.management.https.port=${KEYCLOAK_MANAGEMENT_HTTPS_PORT} \ -Djboss.management.https.port=${KEYCLOAK_MANAGEMENT_HTTPS_PORT} \
-Djboss.node.name={{ inventory_hostname }} \ -Djboss.node.name={{ inventory_hostname }} \
{% if ansible_facts.virtualization_type in ['docker','oci','containerd'] %}-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true {% endif %}\ {% if keycloak_prefer_ipv4 %}-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true {% endif %}\
2>&1 >> "${KEYCLOAK_LOGFILE}" & {% if keycloak_config_standalone_xml is defined %}--server-config={{ keycloak_config_standalone_xml }}{% endif %} &
while [ ! -f ${KEYCLOAK_PIDFILE} ]; do sleep 1; done while [ ! -f ${KEYCLOAK_PIDFILE} ]; do sleep 1; done
fi fi
} }

View File

@@ -1,3 +1,4 @@
# {{ ansible_managed }}
JAVA_OPTS='{{ keycloak_java_opts }}' JAVA_OPTS='{{ keycloak_java_opts }}'
JBOSS_HOME={{ keycloak_jboss_home }} JBOSS_HOME={{ keycloak_jboss_home }}
KEYCLOAK_BIND_ADDRESS={{ keycloak_bind_address }} KEYCLOAK_BIND_ADDRESS={{ keycloak_bind_address }}

View File

@@ -1,3 +1,4 @@
# {{ ansible_managed }}
[Unit] [Unit]
Description=Keycloak Server Description=Keycloak Server
After=network.target After=network.target

View File

@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<!-- {{ ansible_managed }} -->
<server xmlns="urn:jboss:domain:16.0"> <server xmlns="urn:jboss:domain:16.0">
<extensions> <extensions>
<extension module="org.jboss.as.clustering.infinispan"/> <extension module="org.jboss.as.clustering.infinispan"/>
@@ -152,15 +152,15 @@
</security> </security>
</datasource> </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}}"> <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.postgres.enabled %} {% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<connection-url>{{ keycloak_jdbc.postgres.connection_url }}</connection-url> <connection-url>{{ keycloak_jdbc[keycloak_jdbc_engine].connection_url }}</connection-url>
<driver>{{ keycloak_jdbc.postgres.driver_module_name }}</driver> <driver>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}</driver>
<pool> <pool>
<max-pool-size>20</max-pool-size> <max-pool-size>20</max-pool-size>
</pool> </pool>
<security> <security>
<user-name>{{ keycloak_jdbc.postgres.db_user }}</user-name> <user-name>{{ keycloak_jdbc[keycloak_jdbc_engine].db_user }}</user-name>
<password>{{ keycloak_jdbc.postgres.db_password }}</password> <password>{{ keycloak_jdbc[keycloak_jdbc_engine].db_password }}</password>
</security> </security>
{% else %} {% else %}
<connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url> <connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
@@ -172,10 +172,10 @@
{% endif %} {% endif %}
</datasource> </datasource>
<drivers> <drivers>
{% if keycloak_jdbc.postgres.enabled %} {% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<driver name="{{ keycloak_jdbc.postgres.driver_module_name }}" module="{{ keycloak_jdbc.postgres.driver_module_name }}"> <driver name="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}" module="{{ keycloak_jdbc[keycloak_jdbc_engine].driver_module_name }}">
<driver-class>org.postgresql.Driver</driver-class> <driver-class>{{ keycloak_jdbc[keycloak_jdbc_engine].driver_class }}</driver-class>
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class> <xa-datasource-class>{{ keycloak_jdbc[keycloak_jdbc_engine].xa_datasource_class }}</xa-datasource-class>
</driver> </driver>
{% endif %} {% endif %}
<driver name="h2" module="com.h2database.h2"> <driver name="h2" module="com.h2database.h2">
@@ -206,11 +206,11 @@
<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"/> <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>
<subsystem xmlns="urn:jboss:domain:ejb3:9.0"> <subsystem xmlns="urn:jboss:domain:ejb3:9.0">
<session-bean> <session-bean>
<stateless> <stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless> </stateless>
<stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/> <stateful default-access-timeout="5000" cache-ref="distributable" passivation-disabled-cache-ref="simple"/>
<singleton default-access-timeout="5000"/> <singleton default-access-timeout="5000"/>
</session-bean> </session-bean>
<pools> <pools>
@@ -368,12 +368,13 @@
</subsystem> </subsystem>
<subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/> <subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/>
<subsystem xmlns="urn:jboss:domain:infinispan:12.0"> <subsystem xmlns="urn:jboss:domain:infinispan:12.0">
<cache-container name="ejb" default-cache="passivation" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan"> <cache-container name="ejb" default-cache="dist" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan">
<local-cache name="passivation"> <transport lock-timeout="60000"/>
<distributed-cache name="dist">
<locking isolation="REPEATABLE_READ"/> <locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
<file-store passivation="true" purge="false"/> <file-store/>
</local-cache> </distributed-cache>
</cache-container> </cache-container>
<cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan"> <cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan">
<transport lock-timeout="60000"/> <transport lock-timeout="60000"/>
@@ -383,8 +384,7 @@
<local-cache name="users"> <local-cache name="users">
<heap-memory size="10000"/> <heap-memory size="10000"/>
</local-cache> </local-cache>
<local-cache name="authenticationSessions"/> {% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens", "authenticationSessions" ] %}
{% for cachename in [ "sessions", "offlineSessions", "clientSessions", "offlineClientSessions", "loginFailures", "actionTokens" ] %}
<distributed-cache name="{{ cachename }}"> <distributed-cache name="{{ cachename }}">
<remote-store cache="{{ cachename }}" <remote-store cache="{{ cachename }}"
remote-servers="remote-cache" remote-servers="remote-cache"
@@ -400,14 +400,15 @@
<property name="infinispan.client.hotrod.auth_password">{{ keycloak_remotecache.password }}</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_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.auth_server_name">{{ keycloak_remotecache.server_name }}</property>
<property name="infinispan.client.hotrod.sasl_mechanism">{{ keycloak_remotecache.sasl_mechanism | default('SCRAM-SHA-512') }}</property> <property name="infinispan.client.hotrod.sasl_mechanism">{{ keycloak_remotecache.sasl_mechanism }}</property>
<property name="infinispan.client.hotrod.use_ssl">false</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 | default('/etc/truststore/truststore.jks') }}</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_type">JKS</property>
<property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password | default("changeme") }}</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> </remote-store>
</distributed-cache> </distributed-cache>
{% endfor %} {% endfor %}
<replicated-cache name="work"> <replicated-cache name="work">
<remote-store cache="work" <remote-store cache="work"
remote-servers="remote-cache" remote-servers="remote-cache"
@@ -423,11 +424,12 @@
<property name="infinispan.client.hotrod.auth_password">{{ keycloak_remotecache.password }}</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_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.auth_server_name">{{ keycloak_remotecache.server_name }}</property>
<property name="infinispan.client.hotrod.sasl_mechanism">{{ keycloak_remotecache.sasl_mechanism | default('SCRAM-SHA-512') }}</property> <property name="infinispan.client.hotrod.sasl_mechanism">{{ keycloak_remotecache.sasl_mechanism }}</property>
<property name="infinispan.client.hotrod.use_ssl">false</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 | default('/etc/truststore/truststore.jks') }}</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_type">JKS</property>
<property name="infinispan.client.hotrod.trust_store_password">{{ keycloak_remotecache.trust_store_password | default("changeme") }}</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> </remote-store>
</replicated-cache> </replicated-cache>
<local-cache name="authorization"> <local-cache name="authorization">
@@ -438,33 +440,37 @@
<expiration max-idle="3600000"/> <expiration max-idle="3600000"/>
</local-cache> </local-cache>
</cache-container> </cache-container>
<cache-container name="server" default-cache="default" modules="org.wildfly.clustering.server"> <cache-container name="server" default-cache="default" aliases="singleton cluster" modules="org.wildfly.clustering.server">
<local-cache name="default"> <transport lock-timeout="60000"/>
<replicated-cache name="default">
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
</local-cache> </replicated-cache>
</cache-container> </cache-container>
<cache-container name="web" default-cache="passivation" modules="org.wildfly.clustering.web.infinispan"> <cache-container name="web" default-cache="dist" modules="org.wildfly.clustering.web.infinispan">
<local-cache name="passivation"> <transport lock-timeout="60000"/>
<replicated-cache name="sso">
<locking isolation="REPEATABLE_READ"/> <locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
<file-store passivation="true" purge="false"/> </replicated-cache>
</local-cache> <distributed-cache name="dist">
<local-cache name="sso">
<locking isolation="REPEATABLE_READ"/> <locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/> <transaction mode="BATCH"/>
</local-cache> <file-store/>
<local-cache name="routing"/> </distributed-cache>
<distributed-cache name="routing"/>
</cache-container> </cache-container>
<cache-container name="hibernate" modules="org.infinispan.hibernate-cache"> <cache-container name="hibernate" modules="org.infinispan.hibernate-cache">
<local-cache name="entity"> <transport lock-timeout="60000"/>
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query"> <local-cache name="local-query">
<heap-memory size="10000"/> <heap-memory size="10000"/>
<expiration max-idle="100000"/> <expiration max-idle="100000"/>
</local-cache> </local-cache>
<local-cache name="timestamps"/> <invalidation-cache name="entity">
<transaction mode="NON_XA"/>
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</invalidation-cache>
<replicated-cache name="timestamps"/>
</cache-container> </cache-container>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:io:3.0"> <subsystem xmlns="urn:jboss:domain:io:3.0">
@@ -498,21 +504,15 @@
<stacks> <stacks>
<stack name="tcp"> <stack name="tcp">
<transport site="${jboss.node.name}" type="TCP" socket-binding="jgroups-tcp"/> <transport site="${jboss.node.name}" type="TCP" socket-binding="jgroups-tcp"/>
{% if keycloak_jdbc[keycloak_jdbc_engine].enabled %}
<protocol type="JDBC_PING"> <protocol type="JDBC_PING">
<property name="datasource_jndi_name">java:jboss/datasources/KeycloakDS</property> <property name="datasource_jndi_name">java:jboss/datasources/KeycloakDS</property>
<property name="initialize_sql"> <property name="initialize_sql">{{ keycloak_jdbc[keycloak_jdbc_engine].initialize_db }}</property>
CREATE TABLE IF NOT EXISTS JGROUPSPING (
own_addr varchar(200) NOT NULL,
cluster_name varchar(200) NOT NULL,
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
ping_data varbinary(5000) DEFAULT NULL,
PRIMARY KEY (own_addr, cluster_name))
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
</property>
<property name="insert_single_sql">INSERT INTO JGROUPSPING (own_addr, cluster_name, ping_data) values (?, ?, ?)</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="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> <property name="select_all_pingdata_sql">SELECT ping_data FROM JGROUPSPING WHERE cluster_name=?</property>
</protocol> </protocol>
{% endif %}
<protocol type="MERGE3"/> <protocol type="MERGE3"/>
<protocol type="FD_SOCK"/> <protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/> <protocol type="FD_ALL"/>
@@ -551,6 +551,15 @@
<cacheTemplates>true</cacheTemplates> <cacheTemplates>true</cacheTemplates>
<dir>${jboss.home.dir}/themes</dir> <dir>${jboss.home.dir}/themes</dir>
</theme> </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"> <spi name="eventsStore">
<provider name="jpa" enabled="true"> <provider name="jpa" enabled="true">
<properties> <properties>
@@ -610,8 +619,8 @@
<default-provider>default</default-provider> <default-provider>default</default-provider>
<provider name="default" enabled="true"> <provider name="default" enabled="true">
<properties> <properties>
<property name="frontendUrl" value="${keycloak.frontendUrl:}"/> <property name="frontendUrl" value="{{ keycloak_modcluster.frontend_url }}"/>
<property name="forceBackendUrlToFrontendUrl" value="false"/> <property name="forceBackendUrlToFrontendUrl" value="true"/>
</properties> </properties>
</provider> </provider>
</spi> </spi>
@@ -717,20 +726,24 @@
<interface name="management"> <interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/> <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface> </interface>
<interface name="jgroups"> <interface name="jgroups">
{% if ansible_default_ipv4 is defined %}
<subnet-match value="{{ (ansible_default_ipv4.network + '/' + ansible_default_ipv4.netmask) | ipaddr('net') }}"/> <subnet-match value="{{ (ansible_default_ipv4.network + '/' + ansible_default_ipv4.netmask) | ipaddr('net') }}"/>
{% else %}
<any-address />
{% endif %}
</interface> </interface>
<interface name="public"> <interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/> <inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface> </interface>
</interfaces> </interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/> <socket-binding name="ajp" port="{{ keycloak_ajp_port }}"/>
<socket-binding name="http" port="${jboss.http.port:8080}"/> <socket-binding name="http" port="{{ keycloak_http_port }}"/>
<socket-binding name="https" port="${jboss.https.port:8443}"/> <socket-binding name="https" port="{{ keycloak_https_port }}"/>
<socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/> <socket-binding name="management-http" interface="management" port="{{ keycloak_management_http_port }}"/>
<socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/> <socket-binding name="management-https" interface="management" port="{{ keycloak_management_https_port }}"/>
<socket-binding name="jgroups-tcp" interface="jgroups" port="7600"/> <socket-binding name="jgroups-tcp" interface="jgroups" port="{{ keycloak_jgroups_port }}"/>
<socket-binding name="modcluster" multicast-address="${jboss.modcluster.multicast.address:224.0.1.105}" multicast-port="23364"/> <socket-binding name="modcluster" multicast-address="${jboss.modcluster.multicast.address:224.0.1.105}" multicast-port="23364"/>
<socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/> <socket-binding name="txn-status-manager" port="4713"/>

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<!-- {{ ansible_managed }} -->
<server xmlns="urn:jboss:domain:10.0"> <server xmlns="urn:jboss:domain:16.0">
<extensions> <extensions>
<extension module="org.jboss.as.clustering.infinispan"/> <extension module="org.jboss.as.clustering.infinispan"/>
<extension module="org.jboss.as.connector"/> <extension module="org.jboss.as.connector"/>
@@ -22,10 +22,9 @@
<extension module="org.wildfly.extension.bean-validation"/> <extension module="org.wildfly.extension.bean-validation"/>
<extension module="org.wildfly.extension.core-management"/> <extension module="org.wildfly.extension.core-management"/>
<extension module="org.wildfly.extension.elytron"/> <extension module="org.wildfly.extension.elytron"/>
<extension module="org.wildfly.extension.health"/>
<extension module="org.wildfly.extension.io"/> <extension module="org.wildfly.extension.io"/>
<extension module="org.wildfly.extension.microprofile.config-smallrye"/> <extension module="org.wildfly.extension.metrics"/>
<extension module="org.wildfly.extension.microprofile.health-smallrye"/>
<extension module="org.wildfly.extension.microprofile.metrics-smallrye"/>
<extension module="org.wildfly.extension.request-controller"/> <extension module="org.wildfly.extension.request-controller"/>
<extension module="org.wildfly.extension.security.manager"/> <extension module="org.wildfly.extension.security.manager"/>
<extension module="org.wildfly.extension.undertow"/> <extension module="org.wildfly.extension.undertow"/>
@@ -129,7 +128,7 @@
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/> <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
<subsystem xmlns="urn:jboss:domain:core-management:1.0"/> <subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
<subsystem xmlns="urn:jboss:domain:datasources:5.0"> <subsystem xmlns="urn:jboss:domain:datasources:6.0">
<datasources> <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}}"> <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> <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
@@ -140,14 +139,32 @@
</security> </security>
</datasource> </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}}"> <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> <connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
<driver>h2</driver> <driver>h2</driver>
<security> <security>
<user-name>sa</user-name> <user-name>sa</user-name>
<password>sa</password> <password>sa</password>
</security> </security>
{% endif %}
</datasource> </datasource>
<drivers> <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"> <driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class> <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver> </driver>
@@ -157,7 +174,7 @@
<subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0"> <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}"/> <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>
<subsystem xmlns="urn:jboss:domain:ee:4.0"> <subsystem xmlns="urn:jboss:domain:ee:6.0">
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement> <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<concurrent> <concurrent>
<context-services> <context-services>
@@ -167,15 +184,15 @@
<managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/> <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
</managed-thread-factories> </managed-thread-factories>
<managed-executor-services> <managed-executor-services>
<managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/> <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-executor-services>
<managed-scheduled-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-threshold="60000" keepalive-time="3000"/> <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> </managed-scheduled-executor-services>
</concurrent> </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"/> <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>
<subsystem xmlns="urn:jboss:domain:ejb3:6.0"> <subsystem xmlns="urn:jboss:domain:ejb3:9.0">
<session-bean> <session-bean>
<stateless> <stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
@@ -202,7 +219,7 @@
<file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/> <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
</data-stores> </data-stores>
</timer-service> </timer-service>
<remote connector-ref="http-remoting-connector" thread-pool-name="default"> <remote cluster="ejb" connectors="http-remoting-connector" thread-pool-name="default">
<channel-creation-options> <channel-creation-options>
<option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/> <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
</channel-creation-options> </channel-creation-options>
@@ -218,130 +235,7 @@
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/> <statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/> <log-system-exceptions value="true"/>
</subsystem> </subsystem>
<subsystem xmlns="urn:jboss:domain:io:3.0"> <subsystem xmlns="urn:wildfly:elytron:13.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
<worker name="default"/>
<buffer-pool name="default"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:infinispan:9.0">
<cache-container name="keycloak">
<local-cache name="realms">
<object-memory size="10000"/>
</local-cache>
<local-cache name="users">
<object-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">
<object-memory size="10000"/>
</local-cache>
<local-cache name="keys">
<object-memory size="1000"/>
<expiration max-idle="3600000"/>
</local-cache>
<local-cache name="actionTokens">
<object-memory size="-1"/>
<expiration max-idle="-1" interval="300000"/>
</local-cache>
</cache-container>
<cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
<local-cache name="default">
<transaction mode="BATCH"/>
</local-cache>
</cache-container>
<cache-container name="web" default-cache="passivation" module="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="ejb" aliases="sfsb" default-cache="passivation" module="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="hibernate" module="org.infinispan.hibernate-cache">
<local-cache name="entity">
<object-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<object-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps"/>
</cache-container>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jaxrs:1.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-datasource="" default-extended-persistence-inheritance="DEEP"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:mail:3.0">
<mail-session name="default" jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
</subsystem>
{% if keycloak_modcluster.enabled %}
<subsystem xmlns="urn:jboss:domain:modcluster:5.0">
<proxy name="default" advertise-socket="modcluster" 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-manager:1.0">
<deployment-permissions>
<maximum-set>
<permission class="java.security.AllPermission"/>
</maximum-set>
</deployment-permissions>
</subsystem>
<subsystem xmlns="urn:wildfly:elytron:8.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
<providers> <providers>
<aggregate-providers name="combined-providers"> <aggregate-providers name="combined-providers">
<providers name="elytron"/> <providers name="elytron"/>
@@ -399,6 +293,7 @@
<permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/> <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.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 class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
</permission-set> </permission-set>
</permission-sets> </permission-sets>
<http> <http>
@@ -440,76 +335,126 @@
</mechanism-provider-filtering-sasl-server-factory> </mechanism-provider-filtering-sasl-server-factory>
<provider-sasl-server-factory name="global"/> <provider-sasl-server-factory name="global"/>
</sasl> </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>
<subsystem xmlns="urn:jboss:domain:security:2.0"> <subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/>
<security-domains> <subsystem xmlns="urn:jboss:domain:infinispan:12.0">
<security-domain name="other" cache-type="default"> <cache-container name="ejb" default-cache="passivation" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan">
<authentication> <local-cache name="passivation">
<login-module code="Remoting" flag="optional"> <locking isolation="REPEATABLE_READ"/>
<module-option name="password-stacking" value="useFirstPass"/> <transaction mode="BATCH"/>
</login-module> <file-store passivation="true" purge="false"/>
<login-module code="RealmDirect" flag="required"> </local-cache>
<module-option name="password-stacking" value="useFirstPass"/> </cache-container>
</login-module> <cache-container name="keycloak" modules="org.keycloak.keycloak-model-infinispan">
</authentication> <local-cache name="realms">
</security-domain> <heap-memory size="10000"/>
<security-domain name="jboss-web-policy" cache-type="default"> </local-cache>
<authorization> <local-cache name="users">
<policy-module code="Delegating" flag="required"/> <heap-memory size="10000"/>
</authorization> </local-cache>
</security-domain> <local-cache name="sessions"/>
<security-domain name="jaspitest" cache-type="default"> <local-cache name="authenticationSessions"/>
<authentication-jaspi> <local-cache name="offlineSessions"/>
<login-module-stack name="dummy"> <local-cache name="clientSessions"/>
<login-module code="Dummy" flag="optional"/> <local-cache name="offlineClientSessions"/>
</login-module-stack> <local-cache name="loginFailures"/>
<auth-module code="Dummy"/> <local-cache name="work"/>
</authentication-jaspi> <local-cache name="authorization">
</security-domain> <heap-memory size="10000"/>
<security-domain name="jboss-ejb-policy" cache-type="default"> </local-cache>
<authorization> <local-cache name="keys">
<policy-module code="Delegating" flag="required"/> <heap-memory size="1000"/>
</authorization> <expiration max-idle="3600000"/>
</security-domain> </local-cache>
</security-domains> <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>
<subsystem xmlns="urn:jboss:domain:transactions:5.0"> <subsystem xmlns="urn:jboss:domain:io:3.0">
<core-environment node-identifier="${jboss.tx.node.id:1}"> <worker name="default"/>
<process-id> <buffer-pool name="default"/>
<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>
<subsystem xmlns="urn:jboss:domain:weld:4.0"/> <subsystem xmlns="urn:jboss:domain:jaxrs:2.0"/>
<subsystem xmlns="urn:wildfly:microprofile-config-smallrye:1.0"/> <subsystem xmlns="urn:jboss:domain:jca:5.0">
<subsystem xmlns="urn:wildfly:microprofile-health-smallrye:2.0" security-enabled="false" empty-liveness-checks-status="${env.MP_HEALTH_EMPTY_LIVENESS_CHECKS_STATUS:UP}" empty-readiness-checks-status="${env.MP_HEALTH_EMPTY_READINESS_CHECKS_STATUS:UP}"/> <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
<subsystem xmlns="urn:wildfly:microprofile-metrics-smallrye:2.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:wildfly}"/> <bean-validation enabled="true"/>
<subsystem xmlns="urn:jboss:domain:undertow:10.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}}"> <default-workmanager>
<buffer-cache name="default"/> <short-running-threads>
<server name="default-server"> <core-threads count="50"/>
<ajp-listener name="ajp" socket-binding="ajp"/> <queue-length count="50"/>
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> <max-threads count="50"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> <keepalive-time time="10" unit="seconds"/>
<host name="default-host" alias="localhost"> </short-running-threads>
<location name="/" handler="welcome-content"/> <long-running-threads>
<http-invoker security-realm="ApplicationRealm"/> <core-threads count="50"/>
</host> <queue-length count="50"/>
</server> <max-threads count="50"/>
<servlet-container name="default"> <keepalive-time time="10" unit="seconds"/>
<jsp-config/> </long-running-threads>
<websockets/> </default-workmanager>
</servlet-container> <cached-connection-manager/>
<handlers> </subsystem>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/> <subsystem xmlns="urn:jboss:domain:jmx:1.3">
</handlers> <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>
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1"> <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
<web-context>auth</web-context> <web-context>auth</web-context>
<providers> <providers>
<provider>classpath:${jboss.home.dir}/providers/*</provider> <provider>
classpath:${jboss.home.dir}/providers/*
</provider>
</providers> </providers>
<master-realm-name>master</master-realm-name> <master-realm-name>master</master-realm-name>
<scheduled-task-interval>900</scheduled-task-interval> <scheduled-task-interval>900</scheduled-task-interval>
@@ -519,6 +464,15 @@
<cacheTemplates>true</cacheTemplates> <cacheTemplates>true</cacheTemplates>
<dir>${jboss.home.dir}/themes</dir> <dir>${jboss.home.dir}/themes</dir>
</theme> </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"> <spi name="eventsStore">
<provider name="jpa" enabled="true"> <provider name="jpa" enabled="true">
<properties> <properties>
@@ -578,12 +532,103 @@
<default-provider>default</default-provider> <default-provider>default</default-provider>
<provider name="default" enabled="true"> <provider name="default" enabled="true">
<properties> <properties>
<property name="frontendUrl" value="${keycloak.frontendUrl:}"/> <property name="frontendUrl" value="{{ keycloak_modcluster.frontend_url }}"/>
<property name="forceBackendUrlToFrontendUrl" value="false"/> <property name="forceBackendUrlToFrontendUrl" value="true"/>
</properties> </properties>
</provider> </provider>
</spi> </spi>
</subsystem> </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-socket="modcluster" 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> </profile>
<interfaces> <interfaces>
<interface name="management"> <interface name="management">
@@ -594,16 +639,16 @@
</interface> </interface>
</interfaces> </interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/> <socket-binding name="ajp" port="{{ keycloak_ajp_port }}"/>
<socket-binding name="http" port="${jboss.http.port:8080}"/> <socket-binding name="http" port="{{ keycloak_http_port }}"/>
<socket-binding name="https" port="${jboss.https.port:8443}"/> <socket-binding name="https" port="{{ keycloak_https_port }}"/>
<socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/> <socket-binding name="management-http" interface="management" port="{{ keycloak_management_http_port }}"/>
<socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/> <socket-binding name="management-https" interface="management" port="{{ keycloak_management_https_port }}"/>
<socket-binding name="modcluster" multicast-address="${jboss.modcluster.multicast.address:224.0.1.105}" multicast-port="23364"/> <socket-binding name="modcluster" multicast-address="${jboss.modcluster.multicast.address:224.0.1.105}" multicast-port="23364"/>
<socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/> <socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="mail-smtp"> <outbound-socket-binding name="mail-smtp">
<remote-destination host="localhost" port="25"/> <remote-destination host="${jboss.mail.server.host:localhost}" port="${jboss.mail.server.port:25}"/>
</outbound-socket-binding> </outbound-socket-binding>
{% if keycloak_modcluster.enabled %} {% if keycloak_modcluster.enabled %}
<outbound-socket-binding name="proxy1"> <outbound-socket-binding name="proxy1">

View File

@@ -1,44 +1,72 @@
--- ---
# vars file for keycloak # required variables for keycloak
# administrator console password
# administrator console password, this is a required variable
keycloak_admin_password: keycloak_admin_password:
# internal variables below
rhsso_rhn_ids:
'7.5.0': '101971'
'7.5.1': '103836'
# locations # locations
keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}" keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}" keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
keycloak:
home: "{{ keycloak_jboss_home }}"
config_dir: "{{ keycloak_config_dir }}"
bundle: "{{ keycloak_rhsso_archive if keycloak_rhsso_enable else keycloak_archive }}"
service_name: "{{ 'rhsso' if keycloak_rhsso_enable else 'keycloak' }}"
health_url: "{{ keycloak_management_url }}/health"
# database # database
keycloak_jdbc: keycloak_jdbc:
postgres: postgres:
enabled: "{{ keycloak_ha_enabled and keycloak_jdbc_engine == 'postgres' }}" enabled: "{{ (keycloak_ha_enabled or keycloak_db_enabled) and keycloak_jdbc_engine == 'postgres' }}"
driver_class: org.postgresql.Driver driver_class: org.postgresql.Driver
xa_datasource_class: org.postgresql.xa.PGXADataSource xa_datasource_class: org.postgresql.xa.PGXADataSource
driver_module_name: "org.postgresql" driver_module_name: "org.postgresql"
driver_module_dir: "{{ keycloak_jboss_home }}/modules/org/postgresql/main" driver_module_dir: "{{ keycloak_jboss_home }}/modules/org/postgresql/main"
driver_version: 9.4.1212 driver_version: "{{ keycloak_jdbc_driver_version }}"
driver_jar_filename: "postgresql-9.4.1212.jar" driver_jar_filename: "postgresql-{{ keycloak_jdbc_driver_version }}.jar"
driver_jar_url: "https://repo.maven.apache.org/maven2/org/postgresql/postgresql/9.4.1212/postgresql-9.4.1212.jar" driver_jar_url: "https://repo.maven.apache.org/maven2/org/postgresql/postgresql/{{ keycloak_jdbc_driver_version }}/postgresql-{{ keycloak_jdbc_driver_version }}.jar"
connection_url: "{{ postgres_jdbc_url }}" connection_url: "{{ keycloak_jdbc_url }}"
db_user: "{{ postgres_db_user }}" db_user: "{{ keycloak_db_user }}"
db_password: "{{ postgres_db_pass }}" db_password: "{{ keycloak_db_pass }}"
initialize_db: >
CREATE TABLE IF NOT EXISTS JGROUPSPING (
own_addr varchar(200) NOT NULL,
cluster_name varchar(200) NOT NULL,
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ping_data BYTEA,
constraint PK_JGROUPSPING PRIMARY KEY (own_addr, cluster_name))
mariadb: mariadb:
enabled: "{{ keycloak_ha_enabled and keycloak_jdbc_engine == 'mariadb' }}" enabled: "{{ (keycloak_ha_enabled or keycloak_db_enabled) and keycloak_jdbc_engine == 'mariadb' }}"
driver_class: org.mariadb.jdbc.Driver driver_class: org.mariadb.jdbc.Driver
xa_datasource_class: org.mariadb.jdbc.MySQLDataSource xa_datasource_class: org.mariadb.jdbc.MySQLDataSource
driver_module_name: "org.mariadb" driver_module_name: "org.mariadb"
driver_module_dir: "{{ keycloak_jboss_home }}/modules/org/mariadb/main" driver_module_dir: "{{ keycloak_jboss_home }}/modules/org/mariadb/main"
driver_version: 2.7.4 driver_version: "{{ keycloak_jdbc_driver_version }}"
driver_jar_filename: "mariadb-java-client-2.7.4.jar" 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/2.7.4/mariadb-java-client-2.7.4.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: "{{ mariadb_jdbc_url }}" connection_url: "{{ keycloak_jdbc_url }}"
db_user: "{{ mariadb_db_user }}" db_user: "{{ keycloak_db_user }}"
db_password: "{{ mariadb_db_pass }}" db_password: "{{ keycloak_db_pass }}"
initialize_db: >
CREATE TABLE IF NOT EXISTS JGROUPSPING (
own_addr varchar(200) NOT NULL,
cluster_name varchar(200) NOT NULL,
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
ping_data varbinary(5000) DEFAULT NULL,
PRIMARY KEY (own_addr, cluster_name))
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
# reverse proxy mod_cluster # reverse proxy mod_cluster
keycloak_modcluster: keycloak_modcluster:
enabled: "{{ keycloak_ha_enabled }}" enabled: "{{ keycloak_ha_enabled }}"
reverse_proxy_url: "{{ keycloak_modcluster_url }}" reverse_proxy_url: "{{ keycloak_modcluster_url }}"
frontend_url: "{{ keycloak_frontend_url }}"
# infinispan # infinispan
keycloak_remotecache: keycloak_remotecache:
@@ -46,6 +74,8 @@ keycloak_remotecache:
username: "{{ infinispan_user }}" username: "{{ infinispan_user }}"
password: "{{ infinispan_pass }}" password: "{{ infinispan_pass }}"
realm: default realm: default
sasl_mechanism: "{{ infinispan_sasl_mechanism }}"
server_name: "{{ infinispan_url }}" server_name: "{{ infinispan_url }}"
trust_store_path: /path/to/jks/keystore use_ssl: "{{ infinispan_use_ssl }}"
trust_store_password: changeme trust_store_path: "{{ infinispan_trust_store_path }}"
trust_store_password: "{{ infinispan_trust_store_password }}"

View File

@@ -9,11 +9,18 @@ Role Defaults
| Variable | Description | Default | | Variable | Description | Default |
|:---------|:------------|:---------| |:---------|:------------|:---------|
|`keycloak_admin_user` | Administration console user account | `admin` | |`keycloak_admin_user`| Administration console user account | `admin` |
|`keycloak_host` | hostname | `localhost` | |`keycloak_host`| hostname | `localhost` |
|`keycloak_http_port` | HTTP port | `8080` | |`keycloak_http_port`| HTTP port | `8080` |
|`keycloak_https_port` | TLS HTTP port | `8443` | |`keycloak_https_port`| TLS HTTP port | `8443` |
|`keycloak_auth_realm` | Name of the main authentication realm | `master` | |`keycloak_auth_realm`| Name of the main authentication realm | `master` |
|`keycloak_rhsso_enable`| Define service is an upstream(Keycloak) or RHSSO | `master` |
|`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` |
|`keycloak_client_web_origins`| Web origins for realm client | `+` |
|`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 }}` |
Role Variables Role Variables
@@ -36,9 +43,30 @@ The following variables are available for creating clients:
|`keycloak_client_users` | List of user/role mappings for a client | `[]` | |`keycloak_client_users` | List of user/role mappings for a client | `[]` |
The following variable are available for creating user federation:
| Variable | Description | Default |
|:---------|:------------|:---------|
|`keycloak_user_federation` | List of _keycloak_user_federation_ for the realm | `[]` |
Variable formats Variable formats
---------------- ----------------
* `keycloak_user_federation`, a list of:
```yaml
- realm: <name of the realm in which user federation should be configured, required>
name: <name of the user federation provider, required>
provider_id: <type of the user federation provider, required>
provider_type: <Provider Type, default is set to org.keycloak.storage.UserStorageProvider>
config: <dictionary of supported configuration values, required>
mappers: <list of supported configuration values, required>
```
Refer to [docs](https://docs.ansible.com/ansible/latest/collections/community/general/keycloak_user_federation_module.html) for information on supported variables.
* `keycloak_clients`, a list of: * `keycloak_clients`, a list of:
```yaml ```yaml
@@ -69,7 +97,7 @@ Variable formats
realm: <name of the realm> realm: <name of the realm>
``` ```
For a comprehensive example, refer to the [playbook](playbooks/keycloak.yml). For a comprehensive example, refer to the [playbook](../../playbooks/keycloak_realm.yml).
Example Playbook Example Playbook

View File

@@ -3,29 +3,35 @@
keycloak_host: localhost keycloak_host: localhost
keycloak_http_port: 8080 keycloak_http_port: 8080
keycloak_https_port: 8443 keycloak_https_port: 8443
keycloak_management_http_port: 9990
keycloak_rhsso_enable: False
### Keycloak administration console user ### Keycloak administration console user
keycloak_admin_user: admin keycloak_admin_user: admin
keycloak_auth_realm: master keycloak_auth_realm: master
keycloak_auth_client: admin-cli keycloak_auth_client: admin-cli
### Keycloak realm client defaults
### Keycloak realms, clients, roles, federation
# list of clients to create in the realm # list of clients to create in the realm
# #
# Refer to the playbook for a comprehensive example. # Refer to the playbook for a comprehensive example.
# Also refer to meta/argument_specs.yml for specifications.
# #
# Each client has the form: # Each client has the form:
# { name: '', roles: [], realm: '', public_client: bool, web_origins: '', users: [] } # { name: '', roles: [], realm: '', public_client: bool, web_origins: '', users: [] }
# where roles is a list of default role names for the client # where roles is a list of default role names for the client
# and users is a list of account, see below for the format definition # and users is a list of account, see below for the format definition
# an empty name will skip the creation of the client # an empty name will skip the creation of the client
keycloak_clients: #
- name: '' #keycloak_clients:
roles: "{{ keycloak_client_default_roles }}" # - name: ''
realm: "{{ keycloak_realm }}" # roles: "{{ keycloak_client_default_roles }}"
public_client: "{{ keycloak_client_public }}" # realm: "{{ keycloak_realm }}"
web_origins: "{{ keycloak_client_web_origins }}" # public_client: "{{ keycloak_client_public }}"
users: "{{ keycloak_client_users }}" # web_origins: "{{ keycloak_client_web_origins }}"
# users: "{{ keycloak_client_users }}"
keycloak_clients: []
# list of roles to create in the client # list of roles to create in the client
keycloak_client_default_roles: [] keycloak_client_default_roles: []
@@ -42,3 +48,6 @@ keycloak_client_web_origins: '+'
# where each client_role has the form: # where each client_role has the form:
# { client: '', role: '', realm: '' } # { client: '', role: '', realm: '' }
keycloak_client_users: [] keycloak_client_users: []
### List of Keycloak User Federation
keycloak_user_federation: []

View File

@@ -0,0 +1,93 @@
argument_specs:
main:
options:
keycloak_host:
# line 3 of keycloak_realm/defaults/main.yml
default: "localhost"
description: "hostname for rest calls"
type: "str"
keycloak_http_port:
# line 4 of keycloak_realm/defaults/main.yml
default: 8080
description: "HTTP port"
type: "int"
keycloak_https_port:
# line 5 of keycloak_realm/defaults/main.yml
default: 8443
description: "HTTPS port"
type: "int"
keycloak_management_http_port:
# line 6 of keycloak_realm/defaults/main.yml
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"
description: "Administration console user account"
type: "str"
keycloak_auth_realm:
# line 11 of keycloak_realm/defaults/main.yml
default: "master"
description: "Name of the main authentication realm"
type: "str"
keycloak_auth_client:
# line 12 of keycloak_realm/defaults/main.yml
default: "admin-cli"
description: "Authentication client for configuration REST calls"
type: "str"
keycloak_client_default_roles:
# line 36 of keycloak_realm/defaults/main.yml
default: "[]"
description: "List of roles to configure as client default"
type: "list"
keycloak_client_public:
# line 39 of keycloak_realm/defaults/main.yml
default: true
description: "Configure a public realm client"
type: "bool"
keycloak_client_web_origins:
# line 42 of keycloak_realm/defaults/main.yml
default: "+"
description: "Web origins for realm client"
type: "str"
keycloak_client_users:
# line 49 of keycloak_realm/defaults/main.yml
default: "[]"
description: "List of users to configure in the realm client"
type: "list"
keycloak_user_federation:
# line 52 of keycloak_realm/defaults/main.yml
default: "[]"
description: "List of user federations to configure in the realm"
type: "list"
keycloak_admin_password:
# line 5 of keycloak_realm/vars/main.yml
required: true
description: "Password for the administration console user account"
type: "str"
keycloak_realm:
# line 8 of keycloak_realm/vars/main.yml
required: true
description: "Name of the realm to be configured"
type: "str"
keycloak_clients:
# line 11 of keycloak_realm/vars/main.yml
default: "[]"
description: "List of client declarations for the realm"
type: "list"
keycloak_url:
# line 14 of keycloak_realm/vars/main.yml
default: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
description: "URL for configuration rest calls"
type: "str"
keycloak_management_url:
# line 15 of keycloak_realm/vars/main.yml
default: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
description: "URL for management console rest calls"
type: "str"

View File

@@ -1 +1,23 @@
--- ---
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
company: Red Hat, Inc.
license: Apache License 2.0
min_ansible_version: "2.9"
platforms:
- name: EL
versions:
- 8
galaxy_tags:
- keycloak
- redhat
- rhel
- rhn
- sso

View File

@@ -1,17 +1,18 @@
--- ---
- name: Generate keycloak auth token - name: Generate keycloak auth token
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token" url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
method: POST method: POST
body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password" body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password"
validate_certs: no validate_certs: no
no_log: True
register: keycloak_auth_response register: keycloak_auth_response
until: keycloak_auth_response.status == 200 until: keycloak_auth_response.status == 200
retries: 5 retries: 5
delay: 2 delay: 2
- name: "Determine if realm exists" - name: "Determine if realm exists"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}" url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}"
method: GET method: GET
status_code: status_code:
@@ -23,7 +24,7 @@
register: keycloak_realm_exists register: keycloak_realm_exists
- name: Create Realm - name: Create Realm
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms" url: "{{ keycloak_url }}/auth/admin/realms"
method: POST method: POST
body: "{{ lookup('template','realm.json.j2') }}" body: "{{ lookup('template','realm.json.j2') }}"
@@ -34,34 +35,66 @@
status_code: 201 status_code: 201
when: keycloak_realm_exists.status == 404 when: keycloak_realm_exists.status == 404
- name: Create Client - name: Create user federation
community.general.keycloak_user_federation:
auth_keycloak_url: "{{ keycloak_url }}/auth"
auth_realm: "{{ keycloak_auth_realm }}"
auth_username: "{{ keycloak_admin_user }}"
auth_password: "{{ keycloak_admin_password }}"
realm: "{{ item.realm }}"
name: "{{ item.name }}"
state: present
provider_id: "{{ item.provider_id }}"
provider_type: "{{ item.provider_type | default(org.keycloak.storage.UserStorageProvider) }}"
config: "{{ item.config }}"
mappers: "{{ item.mappers | default(omit) }}"
no_log: True
register: create_user_federation_result
loop: "{{ keycloak_user_federation | flatten }}"
when: keycloak_user_federation is defined
- name: Create or update a Keycloak client
community.general.keycloak_client: community.general.keycloak_client:
auth_client_id: "{{ keycloak_auth_client }}" auth_client_id: "{{ keycloak_auth_client }}"
auth_keycloak_url: "{{ keycloak_url }}/auth" auth_keycloak_url: "{{ keycloak_url }}/auth"
auth_realm: "{{ keycloak_auth_realm }}" auth_realm: "{{ keycloak_auth_realm }}"
auth_username: "{{ keycloak_admin_user }}" auth_username: "{{ keycloak_admin_user }}"
auth_password: "{{ keycloak_admin_password }}" auth_password: "{{ keycloak_admin_password }}"
client_id: "{{ item.name }}"
realm: "{{ item.realm }}" realm: "{{ item.realm }}"
default_roles: "{{ item.roles | default(omit) }}" default_roles: "{{ item.roles | default(omit) }}"
client_id: "{{ item.client_id | default(omit) }}"
id: "{{ item.id | default(omit) }}"
name: "{{ item.name | default(omit) }}"
description: "{{ item.description | default(omit) }}"
root_url: "{{ item.root_url | default('') }}" root_url: "{{ item.root_url | default('') }}"
redirect_uris: "{{ demo_app_redirect_uris | default([]) }}" admin_url: "{{ item.admin_url | default('') }}"
public_client: "{{ item.public_client | default(False) }}" base_url: "{{ item.base_url | default('') }}"
enabled: "{{ item.enabled | default(True) }}"
redirect_uris: "{{ item.redirect_uris | default(omit) }}"
web_origins: "{{ item.web_origins | default('+') }}" web_origins: "{{ item.web_origins | default('+') }}"
bearer_only: "{{ item.bearer_only | default(omit) }}"
standard_flow_enabled: "{{ item.standard_flow_enabled | default(omit) }}"
implicit_flow_enabled: "{{ item.implicit_flow_enabled | default(omit) }}"
direct_access_grants_enabled: "{{ item.direct_access_grants_enabled | default(omit) }}"
service_accounts_enabled: "{{ item.service_accounts_enabled | default(omit) }}"
public_client: "{{ item.public_client | default(False) }}"
protocol: "{{ item.protocol | default(omit) }}"
state: present state: present
no_log: True
register: create_client_result register: create_client_result
loop: "{{ keycloak_clients | flatten }}" loop: "{{ keycloak_clients | flatten }}"
when: item.name|length > 0 when: (item.name is defined and item.client_id is defined) or (item.name is defined and item.id is defined)
- name: Create client roles - name: Create client roles
include_tasks: manage_client_roles.yml ansible.builtin.include_tasks: manage_client_roles.yml
when: keycloak_rhsso_enable
loop: "{{ keycloak_clients | flatten }}" loop: "{{ keycloak_clients | flatten }}"
loop_control: loop_control:
loop_var: client loop_var: client
when: "'roles' in client"
- name: Create client users - name: Create client users
include_tasks: manage_client_users.yml ansible.builtin.include_tasks: manage_client_users.yml
loop: "{{ keycloak_clients | flatten }}" loop: "{{ keycloak_clients | flatten }}"
loop_control: loop_control:
loop_var: client loop_var: client
when: "'users' in client"

View File

@@ -10,3 +10,4 @@
auth_password: "{{ keycloak_admin_password }}" auth_password: "{{ keycloak_admin_password }}"
state: present state: present
loop: "{{ client.roles | flatten }}" loop: "{{ client.roles | flatten }}"
no_log: True

View File

@@ -1,12 +1,12 @@
--- ---
- name: Manage Users - name: Manage Users
include_tasks: manage_user.yml ansible.builtin.include_tasks: manage_user.yml
loop: "{{ client.users | flatten }}" loop: "{{ client.users | flatten }}"
loop_control: loop_control:
loop_var: user loop_var: user
- name: Manage User Roles - name: Manage User Roles
include_tasks: manage_user_roles.yml ansible.builtin.include_tasks: manage_user_roles.yml
loop: "{{ client.users | flatten }}" loop: "{{ client.users | flatten }}"
loop_control: loop_control:
loop_var: user loop_var: user

View File

@@ -1,6 +1,6 @@
--- ---
- name: "Check if User Already Exists" - name: "Check if User Already Exists"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}" url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
validate_certs: no validate_certs: no
headers: headers:
@@ -8,7 +8,7 @@
register: keycloak_user_search_result register: keycloak_user_search_result
- name: "Create User" - name: "Create User"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users" url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users"
method: POST method: POST
body: body:
@@ -26,7 +26,7 @@
when: keycloak_user_search_result.json | length == 0 when: keycloak_user_search_result.json | length == 0
- name: "Get User" - name: "Get User"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}" url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
validate_certs: no validate_certs: no
headers: headers:
@@ -34,7 +34,7 @@
register: keycloak_user register: keycloak_user
- name: "Update User Password" - name: "Update User Password"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users/{{ (keycloak_user.json | first).id }}/reset-password" url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users/{{ (keycloak_user.json | first).id }}/reset-password"
method: PUT method: PUT
body: body:

View File

@@ -1,6 +1,6 @@
--- ---
- name: "Get Realm for role" - name: "Get Realm for role"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ client_role.realm }}" url: "{{ keycloak_url }}/auth/admin/realms/{{ client_role.realm }}"
method: GET method: GET
status_code: status_code:
@@ -11,7 +11,7 @@
register: client_role_realm register: client_role_realm
- name: Check if Mapping is available - name: Check if Mapping is available
uri: 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 }}/auth/admin/realms/{{ client_role.realm }}/users/{{ (keycloak_user.json | first).id }}/role-mappings/clients/{{ (create_client_result.results | selectattr('end_state.clientId', 'equalto', client_role.client) | list | first).end_state.id }}/available"
method: GET method: GET
status_code: status_code:
@@ -22,7 +22,7 @@
register: client_role_user_available register: client_role_user_available
- name: "Create Role Mapping" - name: "Create Role Mapping"
uri: 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 }}/auth/admin/realms/{{ client_role.realm }}/users/{{ (keycloak_user.json | first).id }}/role-mappings/clients/{{ (create_client_result.results | selectattr('end_state.clientId', 'equalto', client_role.client) | list | first).end_state.id }}"
method: POST method: POST
body: body:

View File

@@ -1,7 +1,6 @@
--- ---
- name: "Get User {{ user.username }}" - name: "Get User {{ user.username }}"
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}" url: "{{ keycloak_url }}/auth/admin/realms/{{ keycloak_realm }}/users?username={{ user.username }}"
headers: headers:
validate_certs: no validate_certs: no
@@ -9,18 +8,19 @@
register: keycloak_user register: keycloak_user
- name: Refresh keycloak auth token - name: Refresh keycloak auth token
uri: ansible.builtin.uri:
url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token" url: "{{ keycloak_url }}/auth/realms/master/protocol/openid-connect/token"
method: POST method: POST
body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password" body: "client_id={{ keycloak_auth_client }}&username={{ keycloak_admin_user }}&password={{ keycloak_admin_password }}&grant_type=password"
validate_certs: no validate_certs: no
register: keycloak_auth_response register: keycloak_auth_response
no_log: True
until: keycloak_auth_response.status == 200 until: keycloak_auth_response.status == 200
retries: 5 retries: 5
delay: 2 delay: 2
- name: "Manage Client Role Mapping for {{ user.username }}" - name: "Manage Client Role Mapping for {{ user.username }}"
include_tasks: manage_user_client_roles.yml ansible.builtin.include_tasks: manage_user_client_roles.yml
loop: "{{ user.client_roles | flatten }}" loop: "{{ user.client_roles | flatten }}"
loop_control: loop_control:
loop_var: client_role loop_var: client_role

View File

@@ -7,10 +7,6 @@ keycloak_admin_password:
# name of the realm to create, this is a required variable # name of the realm to create, this is a required variable
keycloak_realm: keycloak_realm:
# keycloak realm clients, this is a required variable
keycloak_clients:
# other settings # other settings
keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}" keycloak_url: "http://{{ keycloak_host }}:{{ keycloak_http_port }}"
keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}" keycloak_management_url: "http://{{ keycloak_host }}:{{ keycloak_management_http_port }}"
keycloak_rhsso_enable: "{{ True if rhsso_rhn_id is defined else False }}"