mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-20 10:45:01 +02:00
Fix RBAC groups handling and refactor Keycloak role
- Fixed incorrect handling of RBAC group configuration (moved from OIDC claims into dedicated RBAC variable set). - Unified RBAC group usage across applications (LAM, pgAdmin, phpLDAPadmin, phpMyAdmin, YOURLS). - Replaced old 'KEYCLOAK_OIDC_RBAC_SCOPE_NAME' with dedicated 'KEYCLOAK_RBAC_GROUP_*' variables. - Updated OAuth2 Proxy configuration to use 'RBAC.GROUP.CLAIM'. - Refactored Keycloak role task structure: * Renamed and reorganized task files for clarity ('_update.yml', '02_cleanup.yml', etc.). * Introduced meta and dependency handling separation. - Cleaned up Keycloak config defaults and recaptcha placeholders.
This commit is contained in:
commit
d1cd87c843
@ -90,4 +90,11 @@ _applications_nextcloud_oidc_flavor: >-
|
|||||||
|
|
||||||
# Systemctl
|
# Systemctl
|
||||||
SYS_TIMER_SUFFIX: ".{{ SOFTWARE_NAME | lower }}.timer"
|
SYS_TIMER_SUFFIX: ".{{ SOFTWARE_NAME | lower }}.timer"
|
||||||
SYS_SERVICE_SUFFIX: ".{{ SOFTWARE_NAME | lower }}.service"
|
SYS_SERVICE_SUFFIX: ".{{ SOFTWARE_NAME | lower }}.service"
|
||||||
|
|
||||||
|
# Role-based access control
|
||||||
|
# @See https://en.wikipedia.org/wiki/Role-based_access_control
|
||||||
|
RBAC:
|
||||||
|
GROUP:
|
||||||
|
NAME: "/roles" # Name of the group which holds the RBAC roles
|
||||||
|
CLAIM: "groups" # Name of the claim containing the RBAC groups
|
@ -39,6 +39,4 @@ defaults_oidc:
|
|||||||
USERNAME: "preferred_username"
|
USERNAME: "preferred_username"
|
||||||
GIVEN_NAME: "givenName"
|
GIVEN_NAME: "givenName"
|
||||||
FAMILY_NAME: "surname"
|
FAMILY_NAME: "surname"
|
||||||
EMAIL: "email"
|
EMAIL: "email"
|
||||||
CLAIMS:
|
|
||||||
GROUPS: "groups"
|
|
@ -13,7 +13,7 @@
|
|||||||
include_role:
|
include_role:
|
||||||
name: cmp-docker-proxy
|
name: cmp-docker-proxy
|
||||||
vars:
|
vars:
|
||||||
docker_compose_flush_handlers: false
|
docker_compose_flush_handlers: false
|
||||||
- name: "include 04_seed-database-to-backup.yml"
|
- name: "include 04_seed-database-to-backup.yml"
|
||||||
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/04_seed-database-to-backup.yml"
|
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/04_seed-database-to-backup.yml"
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ server:
|
|||||||
scopes:
|
scopes:
|
||||||
nextcloud: nextcloud
|
nextcloud: nextcloud
|
||||||
|
|
||||||
rbac_groups: "/rbac"
|
|
||||||
docker:
|
docker:
|
||||||
services:
|
services:
|
||||||
keycloak:
|
keycloak:
|
||||||
@ -44,5 +43,5 @@ docker:
|
|||||||
|
|
||||||
credentials:
|
credentials:
|
||||||
recaptcha:
|
recaptcha:
|
||||||
website_key: "YOUR_RECAPTCHA_WEBSITE_KEY" # Required if you enabled recaptcha:
|
website_key: "" # Required if you enabled recaptcha:
|
||||||
secret_key: "YOUR_RECAPTCHA_SECRET_KEY" # Required if you enabled recaptcha:
|
secret_key: "" # Required if you enabled recaptcha:
|
8
roles/web-app-keycloak/tasks/01_meta.yml
Normal file
8
roles/web-app-keycloak/tasks/01_meta.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
- include_tasks: "{{ playbook_dir }}/tasks/utils/load_handlers.yml"
|
||||||
|
vars:
|
||||||
|
handler_role_name: "docker-compose"
|
||||||
|
- ansible.builtin.include_vars:
|
||||||
|
file: "{{ item }}"
|
||||||
|
loop:
|
||||||
|
- "{{ playbook_dir }}/roles/docker-compose/vars/docker-compose.yml"
|
||||||
|
- "{{ playbook_dir }}/roles/cmp-rdbms/vars/database.yml"
|
@ -1,25 +0,0 @@
|
|||||||
- name: Load the '{{ application_id }}' role dependencies
|
|
||||||
block:
|
|
||||||
- name: "load required 'web-svc-logout' for {{ application_id }}"
|
|
||||||
include_role:
|
|
||||||
name: web-svc-logout
|
|
||||||
when: run_once_web_svc_logout is not defined
|
|
||||||
|
|
||||||
- name: "load docker, db and proxy for {{ application_id }}"
|
|
||||||
include_role:
|
|
||||||
name: cmp-db-docker-proxy
|
|
||||||
vars:
|
|
||||||
docker_compose_flush_handlers: true
|
|
||||||
when: KEYCLOAK_LOAD_DEPENDENCIES | bool
|
|
||||||
|
|
||||||
- name: "Load database & docker-compose variables if role dependencies aren't loaded"
|
|
||||||
block:
|
|
||||||
- include_tasks: "{{ playbook_dir }}/tasks/utils/load_handlers.yml"
|
|
||||||
vars:
|
|
||||||
handler_role_name: "docker-compose"
|
|
||||||
- ansible.builtin.include_vars:
|
|
||||||
file: "{{ item }}"
|
|
||||||
loop:
|
|
||||||
- "{{ playbook_dir }}/roles/docker-compose/vars/docker-compose.yml"
|
|
||||||
- "{{ playbook_dir }}/roles/cmp-rdbms/vars/database.yml"
|
|
||||||
when: not KEYCLOAK_LOAD_DEPENDENCIES | bool
|
|
12
roles/web-app-keycloak/tasks/04_dependencies.yml
Normal file
12
roles/web-app-keycloak/tasks/04_dependencies.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
- block:
|
||||||
|
- name: "load required 'web-svc-logout' for {{ application_id }}"
|
||||||
|
include_role:
|
||||||
|
name: web-svc-logout
|
||||||
|
public: false
|
||||||
|
when: run_once_web_svc_logout is not defined
|
||||||
|
|
||||||
|
- name: "load docker, db and proxy for {{ application_id }}"
|
||||||
|
include_role:
|
||||||
|
name: cmp-db-docker-proxy
|
||||||
|
vars:
|
||||||
|
docker_compose_flush_handlers: true
|
@ -5,7 +5,7 @@
|
|||||||
{{
|
{{
|
||||||
(
|
(
|
||||||
KEYCLOAK_DICTIONARY_REALM.clientScopes
|
KEYCLOAK_DICTIONARY_REALM.clientScopes
|
||||||
| selectattr('name','equalto', KEYCLOAK_OIDC_RBAC_SCOPE_NAME)
|
| selectattr('name','equalto', KEYCLOAK_RBAC_GROUP_CLAIME)
|
||||||
| list | first
|
| list | first
|
||||||
) | to_json
|
) | to_json
|
||||||
}}
|
}}
|
||||||
@ -27,7 +27,7 @@
|
|||||||
scope_id_rbac: >-
|
scope_id_rbac: >-
|
||||||
{{ (
|
{{ (
|
||||||
all_scopes.stdout | from_json
|
all_scopes.stdout | from_json
|
||||||
| selectattr('name','equalto', KEYCLOAK_OIDC_RBAC_SCOPE_NAME)
|
| selectattr('name','equalto', KEYCLOAK_RBAC_GROUP_CLAIME)
|
||||||
| list | first | default({})
|
| list | first | default({})
|
||||||
).id | default('') }}
|
).id | default('') }}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
- name: "Update REALM settings (merge LDAP component .config)"
|
- name: "Update REALM settings (merge LDAP component .config)"
|
||||||
include_tasks: 03_update.yml
|
include_tasks: _update.yml
|
||||||
vars:
|
vars:
|
||||||
kc_object_kind: "component"
|
kc_object_kind: "component"
|
||||||
kc_lookup_value: "{{ KEYCLOAK_LDAP_CMP_NAME }}"
|
kc_lookup_value: "{{ KEYCLOAK_LDAP_CMP_NAME }}"
|
||||||
@ -141,4 +141,4 @@
|
|||||||
}, recursive=True)
|
}, recursive=True)
|
||||||
}}
|
}}
|
||||||
kc_merge_path: "config"
|
kc_merge_path: "config"
|
||||||
include_tasks: 03_update.yml
|
include_tasks: _update.yml
|
@ -1,12 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
- name: "Load meta"
|
||||||
|
include_tasks: 01_meta.yml
|
||||||
|
when: not KEYCLOAK_LOAD_DEPENDENCIES | bool
|
||||||
|
|
||||||
|
|
||||||
- name: "Load cleanup routine for '{{ application_id }}'"
|
- name: "Load cleanup routine for '{{ application_id }}'"
|
||||||
include_tasks: 01_cleanup.yml
|
include_tasks: 02_cleanup.yml
|
||||||
|
|
||||||
- name: "Load init routine for '{{ application_id }}'"
|
- name: "Load init routine for '{{ application_id }}'"
|
||||||
include_tasks: 02_initialize.yml
|
include_tasks: 03_init.yml
|
||||||
|
|
||||||
- name: "Load the depdendencies required by '{{ application_id }}'"
|
- name: "Load the depdendencies required by '{{ application_id }}'"
|
||||||
include_tasks: 03_load_dependencies.yml
|
include_tasks: 04_dependencies.yml
|
||||||
|
when: KEYCLOAK_LOAD_DEPENDENCIES | bool
|
||||||
|
|
||||||
- name: "Wait until '{{ KEYCLOAK_CONTAINER }}' container is healthy"
|
- name: "Wait until '{{ KEYCLOAK_CONTAINER }}' container is healthy"
|
||||||
community.docker.docker_container_info:
|
community.docker.docker_container_info:
|
||||||
@ -50,9 +56,9 @@
|
|||||||
| list | first | default({}) ).attributes | default({}) )
|
| list | first | default({}) ).attributes | default({}) )
|
||||||
| combine({'frontchannel.logout.url': KEYCLOAK_FRONTCHANNEL_LOGOUT_URL}, recursive=True)
|
| combine({'frontchannel.logout.url': KEYCLOAK_FRONTCHANNEL_LOGOUT_URL}, recursive=True)
|
||||||
}}
|
}}
|
||||||
include_tasks: 03_update.yml
|
include_tasks: _update.yml
|
||||||
|
|
||||||
- include_tasks: 04_rbac_client_scope.yml
|
- include_tasks: 05_rbac_client_scope.yml
|
||||||
|
|
||||||
- include_tasks: 05_ldap.yml
|
- include_tasks: 06_ldap.yml
|
||||||
when: KEYCLOAK_LDAP_ENABLED | bool
|
when: KEYCLOAK_LDAP_ENABLED | bool
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"organization",
|
"organization",
|
||||||
"offline_access",
|
"offline_access",
|
||||||
"microprofile-jwt",
|
"microprofile-jwt",
|
||||||
"{{ KEYCLOAK_OIDC_RBAC_SCOPE_NAME }}",
|
"{{ KEYCLOAK_RBAC_GROUP_CLAIME }}",
|
||||||
"{{ applications | get_app_conf(application_id, 'scopes.nextcloud', True) }}"
|
"{{ applications | get_app_conf(application_id, 'scopes.nextcloud', True) }}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@
|
|||||||
"group.object.classes": [ "groupOfNames" ],
|
"group.object.classes": [ "groupOfNames" ],
|
||||||
"memberof.ldap.attribute": [ "memberOf" ],
|
"memberof.ldap.attribute": [ "memberOf" ],
|
||||||
"drop.non.existing.groups.during.sync": [ "false" ],
|
"drop.non.existing.groups.during.sync": [ "false" ],
|
||||||
"groups.path": [ "{{ applications | get_app_conf(application_id, 'rbac_groups', True) }}" ]
|
"groups.path": [ "{{ KEYCLOAK_RBAC_GROUP_NAME }}" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1430,7 +1430,7 @@
|
|||||||
"phone",
|
"phone",
|
||||||
"microprofile-jwt",
|
"microprofile-jwt",
|
||||||
"organization",
|
"organization",
|
||||||
"{{ KEYCLOAK_OIDC_RBAC_SCOPE_NAME }}",
|
"{{ KEYCLOAK_RBAC_GROUP_CLAIME }}",
|
||||||
"{{ applications | get_app_conf(application_id, 'scopes.nextcloud', True) }}"
|
"{{ applications | get_app_conf(application_id, 'scopes.nextcloud', True) }}"
|
||||||
],
|
],
|
||||||
"browserSecurityHeaders": {
|
"browserSecurityHeaders": {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "{{ KEYCLOAK_OIDC_RBAC_SCOPE_NAME }}",
|
"name": "{{ KEYCLOAK_RBAC_GROUP_CLAIME }}",
|
||||||
"description": "RBAC Groups",
|
"description": "RBAC Groups",
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
@ -22,7 +22,7 @@
|
|||||||
"id.token.claim": "true",
|
"id.token.claim": "true",
|
||||||
"lightweight.claim": "false",
|
"lightweight.claim": "false",
|
||||||
"access.token.claim": "true",
|
"access.token.claim": "true",
|
||||||
"claim.name": "{{ OIDC.CLAIMS.GROUPS }}"
|
"claim.name": "{{ KEYCLOAK_RBAC_GROUP_CLAIME }}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -11,9 +11,12 @@ KEYCLOAK_REALM_URL: "{{ WEB_PROTOCOL }}://{{ KEYCLOAK_REALM }}"
|
|||||||
KEYCLOAK_DEBUG_ENABLED: "{{ MODE_DEBUG }}"
|
KEYCLOAK_DEBUG_ENABLED: "{{ MODE_DEBUG }}"
|
||||||
KEYCLOAK_CLIENT_ID: "{{ OIDC.CLIENT.ID }}"
|
KEYCLOAK_CLIENT_ID: "{{ OIDC.CLIENT.ID }}"
|
||||||
KEYCLOAK_SERVER_INTERNAL_URL: "http://127.0.0.1:8080"
|
KEYCLOAK_SERVER_INTERNAL_URL: "http://127.0.0.1:8080"
|
||||||
KEYCLOAK_OIDC_RBAC_SCOPE_NAME: "{{ OIDC.CLAIMS.GROUPS }}"
|
|
||||||
KEYCLOAK_LOAD_DEPENDENCIES: "{{ applications | get_app_conf(application_id, 'load_dependencies') }}"
|
KEYCLOAK_LOAD_DEPENDENCIES: "{{ applications | get_app_conf(application_id, 'load_dependencies') }}"
|
||||||
|
|
||||||
|
# RBAC
|
||||||
|
KEYCLOAK_RBAC_GROUP_CLAIME: "{{ RBAC.GROUP.CLAIM }}"
|
||||||
|
KEYCLOAK_RBAC_GROUP_NAME: "{{ RBAC.GROUP.NAME }}"
|
||||||
|
|
||||||
## Health
|
## Health
|
||||||
KEYCLOAK_HEALTH_ENABLED: true
|
KEYCLOAK_HEALTH_ENABLED: true
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ oauth2_proxy:
|
|||||||
application: application
|
application: application
|
||||||
port: 80
|
port: 80
|
||||||
allowed_groups:
|
allowed_groups:
|
||||||
- "/roles/web-app-lam-administrator"
|
- "{{ [RBAC.GROUP.NAME, 'web-app-lam-administrator'] | path_join }}"
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
|
@ -15,8 +15,8 @@ provider_display_name = "{{ OIDC.BUTTON_TEXT }}"
|
|||||||
|
|
||||||
{% if applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.allowed_groups', False) %}
|
{% if applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.allowed_groups', False) %}
|
||||||
{# role based restrictions #}
|
{# role based restrictions #}
|
||||||
scope = "openid email profile {{ OIDC.CLAIMS.GROUPS }}"
|
scope = "openid email profile {{ RBAC.GROUP.CLAIM }}"
|
||||||
oidc_groups_claim = "{{ OIDC.CLAIMS.GROUPS }}"
|
oidc_groups_claim = "{{ RBAC.GROUP.CLAIM }}"
|
||||||
allowed_groups = {{ applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.allowed_groups', True) | tojson }}
|
allowed_groups = {{ applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.allowed_groups', True) | tojson }}
|
||||||
email_domains = ["*"]
|
email_domains = ["*"]
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -5,14 +5,14 @@ oauth2_proxy:
|
|||||||
application: "application"
|
application: "application"
|
||||||
port: "80"
|
port: "80"
|
||||||
allowed_groups:
|
allowed_groups:
|
||||||
- "/roles/web-app-pgadmin-administrator"
|
- "{{ [RBAC.GROUP.NAME, 'web-app-pgadmin-administrator'] | path_join }}"
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
desktop: true
|
desktop: true
|
||||||
central_database: true
|
central_database: true
|
||||||
oauth2: true
|
oauth2: true
|
||||||
logout: true
|
logout: true
|
||||||
server:
|
server:
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
|
@ -3,7 +3,7 @@ oauth2_proxy:
|
|||||||
application: application # Needs to be the same as webinterface
|
application: application # Needs to be the same as webinterface
|
||||||
port: 8080 # application port
|
port: 8080 # application port
|
||||||
allowed_groups:
|
allowed_groups:
|
||||||
- "/roles/web-app-phpldapadmin-administrator"
|
- "{{ [RBAC.GROUP.NAME, 'web-app-phpldapadmin-administrator'] | path_join }}"
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
|
@ -3,7 +3,7 @@ oauth2_proxy:
|
|||||||
port: "80"
|
port: "80"
|
||||||
application: "application"
|
application: "application"
|
||||||
allowed_groups:
|
allowed_groups:
|
||||||
- "/roles/web-app-phpmyadmin-administrator"
|
- "{{ [RBAC.GROUP.NAME, 'web-app-phpmyadmin-administrator'] | path_join }}"
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: false
|
css: false
|
||||||
|
@ -2,7 +2,7 @@ oauth2_proxy:
|
|||||||
application: "application"
|
application: "application"
|
||||||
port: "80"
|
port: "80"
|
||||||
allowed_groups:
|
allowed_groups:
|
||||||
- "/roles/web-app-yourls-administrator"
|
- "{{ [RBAC.GROUP.NAME, 'web-app-yourls-administrator'] | path_join }}"
|
||||||
acl:
|
acl:
|
||||||
blacklist:
|
blacklist:
|
||||||
- "<< defaults_applications[web-app-yourls].server.locations.admin >>" # Protects the admin area
|
- "<< defaults_applications[web-app-yourls].server.locations.admin >>" # Protects the admin area
|
||||||
|
Loading…
x
Reference in New Issue
Block a user