mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 15:06:26 +02:00
Huge role refactoring/cleanup. Other commits will propably follow. Because some bugs will exist. Still important for longrun and also for auto docs/help/slideshow generation
This commit is contained in:
33
roles/web-app-keycloak/README.md
Normal file
33
roles/web-app-keycloak/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Keycloak
|
||||
|
||||
## Description
|
||||
|
||||
Step into a secure future with Keycloak! This open‐source identity and access management solution offers powerful single sign-on (SSO), multi-factor authentication, and user federation capabilities. With support for industry standards such as SAML and OpenID Connect, Keycloak helps you protect and streamline access to your applications.
|
||||
|
||||
## Overview
|
||||
|
||||
This role deploys Keycloak in a Docker environment, integrating it with a PostgreSQL database and enabling operation behind a reverse proxy such as NGINX. It manages container orchestration and configuration via Docker Compose and environment variable templates, ensuring a secure and scalable identity management solution.
|
||||
|
||||
## Features
|
||||
|
||||
- **Comprehensive Identity Management:** Manage users, roles, and permissions across your applications with robust SSO and user federation.
|
||||
- **Advanced Security Options:** Benefit from multi-factor authentication, configurable password policies, and secure session management.
|
||||
- **Standards Support:** Seamlessly integrate with SAML, OpenID Connect, and OAuth2 to support various authentication flows.
|
||||
- **Scalable and Customizable:** Easily tailor settings and scale your Keycloak instance to meet growing demands.
|
||||
|
||||
## Further Resources
|
||||
|
||||
- [Keycloak Official Website](https://www.keycloak.org/)
|
||||
- [Official Keycloak Documentation](https://www.keycloak.org/documentation.html)
|
||||
- [Keycloak GitHub Repository](https://github.com/keycloak/keycloak)
|
||||
- [Setting up Keycloak behind a Reverse Proxy](https://www.keycloak.org/server/reverseproxy)
|
||||
- [Wikipedia](https://en.wikipedia.org/wiki/Keycloak)
|
||||
- [Youtube Tutorial](https://www.youtube.com/watch?v=fvxQ8bW0vO8)
|
||||
|
||||
## Credits
|
||||
|
||||
Developed and maintained by **Kevin Veen-Birkenbach**.
|
||||
Learn more at [veen.world](https://www.veen.world).
|
||||
|
||||
Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais)
|
||||
Licensed under [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl).
|
24
roles/web-app-keycloak/meta/main.yml
Normal file
24
roles/web-app-keycloak/meta/main.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: "Kevin Veen-Birkenbach"
|
||||
description: "Step into a secure future with Keycloak! Our dynamic identity and access management solution offers streamlined SSO capabilities, robust security measures, and an intuitive user experience that propels your applications to unprecedented heights of performance and reliability."
|
||||
license: "CyMaIS NonCommercial License (CNCL)"
|
||||
license_url: "https://s.veen.world/cncl"
|
||||
company: |
|
||||
Kevin Veen-Birkenbach
|
||||
Consulting & Coaching Solutions
|
||||
https://www.veen.world
|
||||
galaxy_tags:
|
||||
- keycloak
|
||||
- docker
|
||||
- identity management
|
||||
- sso
|
||||
- self-hosted
|
||||
repository: https://s.veen.world/cymais
|
||||
issue_tracker_url: https://s.veen.world/cymaisissues
|
||||
documentation: https://s.veen.world/cymais
|
||||
logo:
|
||||
class: "fa-solid fa-lock"
|
||||
run_after:
|
||||
- web-app-matomo
|
||||
- service-openldap
|
5
roles/web-app-keycloak/meta/schema.yml
Normal file
5
roles/web-app-keycloak/meta/schema.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
credentials:
|
||||
administrator_password:
|
||||
description: "Password for the Keycloak administrator user (used in bootstrap and CLI access)"
|
||||
algorithm: "sha256"
|
||||
validation: "^[a-f0-9]{64}$"
|
3
roles/web-app-keycloak/meta/users.yml
Normal file
3
roles/web-app-keycloak/meta/users.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
users:
|
||||
administrator:
|
||||
username: "administrator"
|
82
roles/web-app-keycloak/tasks/attributes/ssh_public_key.yml
Normal file
82
roles/web-app-keycloak/tasks/attributes/ssh_public_key.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
- name: "Wait until Keycloak is reachable at {{ keycloak_server_host_url }}"
|
||||
uri:
|
||||
url: "{{ keycloak_server_host_url }}/realms/master"
|
||||
method: GET
|
||||
status_code: 200
|
||||
validate_certs: false
|
||||
register: keycloak_check
|
||||
retries: 30
|
||||
delay: 5
|
||||
until: keycloak_check.status == 200
|
||||
|
||||
# Configure Credentials
|
||||
- name: Ensure Keycloak CLI credentials are configured
|
||||
shell: |
|
||||
{{ keycloak_kcadm_path }} config credentials \
|
||||
--server {{ keycloak_server_internal_url }} \
|
||||
--realm master \
|
||||
--user {{ keycloak_administrator_username }} \
|
||||
--password {{ keycloak_administrator_password }}
|
||||
|
||||
# LDAP Source
|
||||
- name: Get ID of LDAP storage provider
|
||||
shell: |
|
||||
{{ keycloak_kcadm_path }} get components \
|
||||
-r {{ keycloak_realm }} \
|
||||
--query 'providerId=ldap' \
|
||||
--fields id,name \
|
||||
--format json
|
||||
register: ldap_components
|
||||
|
||||
- name: Extract LDAP component ID
|
||||
set_fact:
|
||||
ldap_component_id: "{{ (ldap_components.stdout | from_json)[0].id }}"
|
||||
|
||||
- name: Ensure {{ ldap.user.attributes.ssh_public_key }} LDAP Mapper exists
|
||||
shell: |
|
||||
docker exec -i keycloak_application bash -c '
|
||||
/opt/keycloak/bin/kcadm.sh get components -r {{ keycloak_realm }} \
|
||||
| grep -q "\"name\" : \"{{ ldap.user.attributes.ssh_public_key }}\"" \
|
||||
|| printf "%s\n" "{
|
||||
\"name\": \"{{ ldap.user.attributes.ssh_public_key }}\",
|
||||
\"parentId\": \"{{ ldap_component_id }}\",
|
||||
\"providerId\": \"user-attribute-ldap-mapper\",
|
||||
\"providerType\": \"org.keycloak.storage.ldap.mappers.LDAPStorageMapper\",
|
||||
\"config\": {
|
||||
\"user.model.attribute\": [\"{{ ldap.user.attributes.ssh_public_key }}\"],
|
||||
\"ldap.attribute\": [\"{{ ldap.user.attributes.ssh_public_key }}\"],
|
||||
\"read.only\": [\"false\"],
|
||||
\"write.only\": [\"true\"],
|
||||
\"always.read.value.from.ldap\": [\"false\"],
|
||||
\"multivalued\": [\"true\"]
|
||||
}
|
||||
}" | /opt/keycloak/bin/kcadm.sh create components -r {{ keycloak_realm }} -f -'
|
||||
register: mapper_create
|
||||
changed_when: mapper_create.rc == 0 and mapper_create.stdout != ""
|
||||
|
||||
# GUI
|
||||
|
||||
- name: Enable user profile in realm
|
||||
shell: >
|
||||
{{ keycloak_kcadm_path }} update realms/{{ keycloak_realm }}
|
||||
-s 'attributes.userProfileEnabled=true'
|
||||
|
||||
- name: Re-authenticate to Keycloak after enabling user profile
|
||||
shell: |
|
||||
{{ keycloak_kcadm_path }} config credentials \
|
||||
--server {{ keycloak_server_internal_url }} \
|
||||
--realm master \
|
||||
--user {{ keycloak_administrator_username }} \
|
||||
--password {{ keycloak_administrator_password }}
|
||||
|
||||
- name: Render user-profile JSON for SSH key
|
||||
template:
|
||||
src: import/user-profile.json.j2
|
||||
dest: "{{ import_directory_host }}/user-profile.json"
|
||||
mode: '0644'
|
||||
notify: docker compose up
|
||||
|
||||
- name: Apply SSH Public Key to user-profile via kcadm
|
||||
shell: |
|
||||
docker exec -i {{ container_name }} \
|
||||
/opt/keycloak/bin/kcadm.sh update realms/{{ keycloak_realm }} -f {{ import_directory_docker }}user-profile.json
|
29
roles/web-app-keycloak/tasks/main.yml
Normal file
29
roles/web-app-keycloak/tasks/main.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
- name: "include service-rdbms-central"
|
||||
include_role:
|
||||
name: service-rdbms-central
|
||||
|
||||
- name: "include role webserver-proxy-domain for {{application_id}}"
|
||||
include_role:
|
||||
name: webserver-proxy-domain
|
||||
vars:
|
||||
domain: "{{ domains | get_domain(application_id) }}"
|
||||
http_port: "{{ ports.localhost.http[application_id] }}"
|
||||
|
||||
- name: "create directory {{import_directory_host}}"
|
||||
file:
|
||||
path: "{{import_directory_host}}"
|
||||
state: directory
|
||||
mode: 0755
|
||||
|
||||
- name: "Copy import files to {{ import_directory_host }}"
|
||||
template:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ import_directory_host }}/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
mode: '770'
|
||||
loop: "{{ lookup('fileglob', '{{ role_path }}/templates/import/*.j2', wantlist=True) }}"
|
||||
notify: docker compose up
|
||||
|
||||
# Deactivated temporary. Import now via realm.yml
|
||||
#- name: Implement SSH Public Key Attribut
|
||||
# include_tasks: attributes/ssh_public_key.yml
|
18
roles/web-app-keycloak/templates/docker-compose.yml.j2
Normal file
18
roles/web-app-keycloak/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,18 @@
|
||||
{% include 'roles/docker-compose/templates/base.yml.j2' %}
|
||||
|
||||
application:
|
||||
image: "{{ applications[application_id].images.keycloak }}"
|
||||
container_name: {{container_name}}
|
||||
command: start {% if applications[application_id].import_realm | bool %}--import-realm{% endif %}
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
ports:
|
||||
- "{{ keycloak_server_host }}:8080"
|
||||
volumes:
|
||||
- "{{import_directory_host}}:{{import_directory_docker}}"
|
||||
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
{% set container_port = 9000 %}
|
||||
{% set container_healthcheck = 'health/live' %}
|
||||
{% include 'roles/docker-container/templates/healthcheck/tcp.yml.j2' %}
|
||||
|
||||
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
25
roles/web-app-keycloak/templates/env.j2
Normal file
25
roles/web-app-keycloak/templates/env.j2
Normal file
@@ -0,0 +1,25 @@
|
||||
# Environment File for Keycloak
|
||||
# Documentation can be found here:
|
||||
# @see https://www.keycloak.org/server/containers
|
||||
|
||||
KC_HOSTNAME= https://{{domains | get_domain(application_id)}}
|
||||
KC_HTTP_ENABLED= true
|
||||
|
||||
# Health Checks
|
||||
# @see https://quarkus.io/guides/smallrye-health
|
||||
KC_HEALTH_ENABLED= true
|
||||
KC_METRICS_ENABLED= true
|
||||
|
||||
# Administrator
|
||||
KEYCLOAK_ADMIN= "{{applications[application_id].users.administrator.username}}"
|
||||
KEYCLOAK_ADMIN_PASSWORD= "{{applications[application_id].credentials.administrator_password}}"
|
||||
|
||||
# Database
|
||||
KC_DB= postgres
|
||||
KC_DB_URL= {{database_url_jdbc}}
|
||||
KC_DB_USERNAME= {{database_username}}
|
||||
KC_DB_PASSWORD= {{database_password}}
|
||||
|
||||
# If the initial administrator already exists and the environment variables are still present at startup, an error message stating the failed creation of the initial administrator is shown in the logs. Keycloak ignores the values and starts up correctly.
|
||||
KC_BOOTSTRAP_ADMIN_USERNAME= "{{applications[application_id].users.administrator.username}}"
|
||||
KC_BOOTSTRAP_ADMIN_PASSWORD= "{{applications[application_id].credentials.administrator_password}}"
|
3078
roles/web-app-keycloak/templates/import/realm.json.j2
Normal file
3078
roles/web-app-keycloak/templates/import/realm.json.j2
Normal file
File diff suppressed because it is too large
Load Diff
30
roles/web-app-keycloak/vars/configuration.yml
Normal file
30
roles/web-app-keycloak/vars/configuration.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
images:
|
||||
keycloak: "quay.io/keycloak/keycloak:latest"
|
||||
import_realm: True # If True realm will be imported. If false skip.
|
||||
features:
|
||||
matomo: true
|
||||
css: false
|
||||
portfolio_iframe: true
|
||||
ldap: true
|
||||
central_database: true
|
||||
recaptcha: true
|
||||
csp:
|
||||
flags:
|
||||
script-src-elem:
|
||||
unsafe-inline: true
|
||||
script-src:
|
||||
unsafe-inline: true
|
||||
style-src:
|
||||
unsafe-inline: true
|
||||
domains:
|
||||
canonical:
|
||||
- "auth.{{ primary_domain }}"
|
||||
scopes:
|
||||
rbac_roles: rbac_roles
|
||||
nextcloud: nextcloud
|
||||
|
||||
rbac_groups: "/rbac"
|
||||
docker:
|
||||
services:
|
||||
database:
|
||||
enabled: true
|
14
roles/web-app-keycloak/vars/main.yml
Normal file
14
roles/web-app-keycloak/vars/main.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
application_id: "keycloak"
|
||||
database_type: "postgres"
|
||||
container_name: "{{application_id}}_application"
|
||||
import_directory_host: "{{docker_compose.directories.volumes}}import/" # Directory in which keycloack import files are placed on the host
|
||||
import_directory_docker: "/opt/keycloak/data/import/" # Directory in which keycloack import files are placed in the running docker container
|
||||
keycloak_realm: "{{ primary_domain}}" # This is the name of the default realm which is used by the applications
|
||||
keycloak_administrator: "{{ applications[application_id].users.administrator }}" # Master Administrator
|
||||
keycloak_administrator_username: "{{ keycloak_administrator.username}}" # Master Administrator Username
|
||||
keycloak_administrator_password: "{{ keycloak_administrator.password}}" # Master Administrator Password
|
||||
keycloak_kcadm_path: "docker exec -i {{ container_name }} /opt/keycloak/bin/kcadm.sh"
|
||||
keycloak_server_internal_url: "http://127.0.0.1:8080"
|
||||
keycloak_server_host: "127.0.0.1:{{ports.localhost.http[application_id]}}"
|
||||
keycloak_server_host_url: "http://{{ keycloak_server_host }}"
|
||||
|
Reference in New Issue
Block a user