diff --git a/group_vars/all/00_general.yml b/group_vars/all/00_general.yml index 60f7e800..ca598ad7 100644 --- a/group_vars/all/00_general.yml +++ b/group_vars/all/00_general.yml @@ -90,4 +90,11 @@ _applications_nextcloud_oidc_flavor: >- # Systemctl SYS_TIMER_SUFFIX: ".{{ SOFTWARE_NAME | lower }}.timer" -SYS_SERVICE_SUFFIX: ".{{ SOFTWARE_NAME | lower }}.service" \ No newline at end of file +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 \ No newline at end of file diff --git a/group_vars/all/12_oidc.yml b/group_vars/all/12_oidc.yml index ef75dbe8..59dbdd24 100644 --- a/group_vars/all/12_oidc.yml +++ b/group_vars/all/12_oidc.yml @@ -39,6 +39,4 @@ defaults_oidc: USERNAME: "preferred_username" GIVEN_NAME: "givenName" FAMILY_NAME: "surname" - EMAIL: "email" - CLAIMS: - GROUPS: "groups" + EMAIL: "email" \ No newline at end of file diff --git a/roles/web-app-bigbluebutton/tasks/main.yml b/roles/web-app-bigbluebutton/tasks/main.yml index 85a40424..cf5cfda5 100644 --- a/roles/web-app-bigbluebutton/tasks/main.yml +++ b/roles/web-app-bigbluebutton/tasks/main.yml @@ -13,7 +13,7 @@ include_role: name: cmp-docker-proxy vars: - docker_compose_flush_handlers: false + docker_compose_flush_handlers: false - 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" diff --git a/roles/web-app-keycloak/config/main.yml b/roles/web-app-keycloak/config/main.yml index da69fd3f..d03508b2 100644 --- a/roles/web-app-keycloak/config/main.yml +++ b/roles/web-app-keycloak/config/main.yml @@ -32,7 +32,6 @@ server: scopes: nextcloud: nextcloud -rbac_groups: "/rbac" docker: services: keycloak: @@ -44,5 +43,5 @@ docker: credentials: recaptcha: - website_key: "YOUR_RECAPTCHA_WEBSITE_KEY" # Required if you enabled recaptcha: - secret_key: "YOUR_RECAPTCHA_SECRET_KEY" # Required if you enabled recaptcha: \ No newline at end of file + website_key: "" # Required if you enabled recaptcha: + secret_key: "" # Required if you enabled recaptcha: \ No newline at end of file diff --git a/roles/web-app-keycloak/tasks/01_meta.yml b/roles/web-app-keycloak/tasks/01_meta.yml new file mode 100644 index 00000000..ae4caa73 --- /dev/null +++ b/roles/web-app-keycloak/tasks/01_meta.yml @@ -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" \ No newline at end of file diff --git a/roles/web-app-keycloak/tasks/01_cleanup.yml b/roles/web-app-keycloak/tasks/02_cleanup.yml similarity index 100% rename from roles/web-app-keycloak/tasks/01_cleanup.yml rename to roles/web-app-keycloak/tasks/02_cleanup.yml diff --git a/roles/web-app-keycloak/tasks/02_initialize.yml b/roles/web-app-keycloak/tasks/03_init.yml similarity index 100% rename from roles/web-app-keycloak/tasks/02_initialize.yml rename to roles/web-app-keycloak/tasks/03_init.yml diff --git a/roles/web-app-keycloak/tasks/03_load_dependencies.yml b/roles/web-app-keycloak/tasks/03_load_dependencies.yml deleted file mode 100644 index 18a4e632..00000000 --- a/roles/web-app-keycloak/tasks/03_load_dependencies.yml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/roles/web-app-keycloak/tasks/04_dependencies.yml b/roles/web-app-keycloak/tasks/04_dependencies.yml new file mode 100644 index 00000000..2ec67abd --- /dev/null +++ b/roles/web-app-keycloak/tasks/04_dependencies.yml @@ -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 diff --git a/roles/web-app-keycloak/tasks/04_rbac_client_scope.yml b/roles/web-app-keycloak/tasks/05_rbac_client_scope.yml similarity index 94% rename from roles/web-app-keycloak/tasks/04_rbac_client_scope.yml rename to roles/web-app-keycloak/tasks/05_rbac_client_scope.yml index cfb2e955..7af26882 100644 --- a/roles/web-app-keycloak/tasks/04_rbac_client_scope.yml +++ b/roles/web-app-keycloak/tasks/05_rbac_client_scope.yml @@ -5,7 +5,7 @@ {{ ( KEYCLOAK_DICTIONARY_REALM.clientScopes - | selectattr('name','equalto', KEYCLOAK_OIDC_RBAC_SCOPE_NAME) + | selectattr('name','equalto', KEYCLOAK_RBAC_GROUP_CLAIME) | list | first ) | to_json }} @@ -27,7 +27,7 @@ scope_id_rbac: >- {{ ( all_scopes.stdout | from_json - | selectattr('name','equalto', KEYCLOAK_OIDC_RBAC_SCOPE_NAME) + | selectattr('name','equalto', KEYCLOAK_RBAC_GROUP_CLAIME) | list | first | default({}) ).id | default('') }} diff --git a/roles/web-app-keycloak/tasks/05_ldap.yml b/roles/web-app-keycloak/tasks/06_ldap.yml similarity index 98% rename from roles/web-app-keycloak/tasks/05_ldap.yml rename to roles/web-app-keycloak/tasks/06_ldap.yml index d7d49737..0a461457 100644 --- a/roles/web-app-keycloak/tasks/05_ldap.yml +++ b/roles/web-app-keycloak/tasks/06_ldap.yml @@ -1,5 +1,5 @@ - name: "Update REALM settings (merge LDAP component .config)" - include_tasks: 03_update.yml + include_tasks: _update.yml vars: kc_object_kind: "component" kc_lookup_value: "{{ KEYCLOAK_LDAP_CMP_NAME }}" @@ -141,4 +141,4 @@ }, recursive=True) }} kc_merge_path: "config" - include_tasks: 03_update.yml + include_tasks: _update.yml diff --git a/roles/web-app-keycloak/tasks/03_update.yml b/roles/web-app-keycloak/tasks/_update.yml similarity index 100% rename from roles/web-app-keycloak/tasks/03_update.yml rename to roles/web-app-keycloak/tasks/_update.yml diff --git a/roles/web-app-keycloak/tasks/main.yml b/roles/web-app-keycloak/tasks/main.yml index ccde926d..bb98d3d5 100644 --- a/roles/web-app-keycloak/tasks/main.yml +++ b/roles/web-app-keycloak/tasks/main.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 }}'" - include_tasks: 01_cleanup.yml + include_tasks: 02_cleanup.yml - 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 }}'" - include_tasks: 03_load_dependencies.yml + include_tasks: 04_dependencies.yml + when: KEYCLOAK_LOAD_DEPENDENCIES | bool - name: "Wait until '{{ KEYCLOAK_CONTAINER }}' container is healthy" community.docker.docker_container_info: @@ -50,9 +56,9 @@ | list | first | default({}) ).attributes | default({}) ) | 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 diff --git a/roles/web-app-keycloak/templates/import/clients/default.json.j2 b/roles/web-app-keycloak/templates/import/clients/default.json.j2 index 57dee708..46331e8b 100644 --- a/roles/web-app-keycloak/templates/import/clients/default.json.j2 +++ b/roles/web-app-keycloak/templates/import/clients/default.json.j2 @@ -54,7 +54,7 @@ "organization", "offline_access", "microprofile-jwt", - "{{ KEYCLOAK_OIDC_RBAC_SCOPE_NAME }}", + "{{ KEYCLOAK_RBAC_GROUP_CLAIME }}", "{{ applications | get_app_conf(application_id, 'scopes.nextcloud', True) }}" ] } diff --git a/roles/web-app-keycloak/templates/import/components/org.keycloak.storage.UserStorageProvider.json.j2 b/roles/web-app-keycloak/templates/import/components/org.keycloak.storage.UserStorageProvider.json.j2 index 0935e107..882b16e8 100644 --- a/roles/web-app-keycloak/templates/import/components/org.keycloak.storage.UserStorageProvider.json.j2 +++ b/roles/web-app-keycloak/templates/import/components/org.keycloak.storage.UserStorageProvider.json.j2 @@ -156,7 +156,7 @@ "group.object.classes": [ "groupOfNames" ], "memberof.ldap.attribute": [ "memberOf" ], "drop.non.existing.groups.during.sync": [ "false" ], - "groups.path": [ "{{ applications | get_app_conf(application_id, 'rbac_groups', True) }}" ] + "groups.path": [ "{{ KEYCLOAK_RBAC_GROUP_NAME }}" ] } }, { diff --git a/roles/web-app-keycloak/templates/import/realm.json.j2 b/roles/web-app-keycloak/templates/import/realm.json.j2 index e8131479..fcd47bb1 100644 --- a/roles/web-app-keycloak/templates/import/realm.json.j2 +++ b/roles/web-app-keycloak/templates/import/realm.json.j2 @@ -1430,7 +1430,7 @@ "phone", "microprofile-jwt", "organization", - "{{ KEYCLOAK_OIDC_RBAC_SCOPE_NAME }}", + "{{ KEYCLOAK_RBAC_GROUP_CLAIME }}", "{{ applications | get_app_conf(application_id, 'scopes.nextcloud', True) }}" ], "browserSecurityHeaders": { diff --git a/roles/web-app-keycloak/templates/import/scopes/rbac.json.j2 b/roles/web-app-keycloak/templates/import/scopes/rbac.json.j2 index 2fefc3e9..2e070908 100644 --- a/roles/web-app-keycloak/templates/import/scopes/rbac.json.j2 +++ b/roles/web-app-keycloak/templates/import/scopes/rbac.json.j2 @@ -1,5 +1,5 @@ { - "name": "{{ KEYCLOAK_OIDC_RBAC_SCOPE_NAME }}", + "name": "{{ KEYCLOAK_RBAC_GROUP_CLAIME }}", "description": "RBAC Groups", "protocol": "openid-connect", "attributes": { @@ -22,7 +22,7 @@ "id.token.claim": "true", "lightweight.claim": "false", "access.token.claim": "true", - "claim.name": "{{ OIDC.CLAIMS.GROUPS }}" + "claim.name": "{{ KEYCLOAK_RBAC_GROUP_CLAIME }}" } } ] diff --git a/roles/web-app-keycloak/vars/main.yml b/roles/web-app-keycloak/vars/main.yml index d9b0992e..83690293 100644 --- a/roles/web-app-keycloak/vars/main.yml +++ b/roles/web-app-keycloak/vars/main.yml @@ -11,9 +11,12 @@ KEYCLOAK_REALM_URL: "{{ WEB_PROTOCOL }}://{{ KEYCLOAK_REALM }}" KEYCLOAK_DEBUG_ENABLED: "{{ MODE_DEBUG }}" KEYCLOAK_CLIENT_ID: "{{ OIDC.CLIENT.ID }}" 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') }}" +# RBAC +KEYCLOAK_RBAC_GROUP_CLAIME: "{{ RBAC.GROUP.CLAIM }}" +KEYCLOAK_RBAC_GROUP_NAME: "{{ RBAC.GROUP.NAME }}" + ## Health KEYCLOAK_HEALTH_ENABLED: true diff --git a/roles/web-app-lam/config/main.yml b/roles/web-app-lam/config/main.yml index 409f360e..1efaca9a 100644 --- a/roles/web-app-lam/config/main.yml +++ b/roles/web-app-lam/config/main.yml @@ -7,7 +7,7 @@ oauth2_proxy: application: application port: 80 allowed_groups: - - "/roles/web-app-lam-administrator" + - "{{ [RBAC.GROUP.NAME, 'web-app-lam-administrator'] | path_join }}" features: matomo: true css: true diff --git a/roles/web-app-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 b/roles/web-app-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 index be00a741..419f5f5d 100644 --- a/roles/web-app-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 +++ b/roles/web-app-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 @@ -15,8 +15,8 @@ provider_display_name = "{{ OIDC.BUTTON_TEXT }}" {% if applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.allowed_groups', False) %} {# role based restrictions #} -scope = "openid email profile {{ OIDC.CLAIMS.GROUPS }}" -oidc_groups_claim = "{{ OIDC.CLAIMS.GROUPS }}" +scope = "openid email profile {{ RBAC.GROUP.CLAIM }}" +oidc_groups_claim = "{{ RBAC.GROUP.CLAIM }}" allowed_groups = {{ applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.allowed_groups', True) | tojson }} email_domains = ["*"] {% else %} diff --git a/roles/web-app-pgadmin/config/main.yml b/roles/web-app-pgadmin/config/main.yml index abe2eb6c..a397318c 100644 --- a/roles/web-app-pgadmin/config/main.yml +++ b/roles/web-app-pgadmin/config/main.yml @@ -5,14 +5,14 @@ oauth2_proxy: application: "application" port: "80" allowed_groups: - - "/roles/web-app-pgadmin-administrator" + - "{{ [RBAC.GROUP.NAME, 'web-app-pgadmin-administrator'] | path_join }}" features: matomo: true css: true - desktop: true + desktop: true central_database: true oauth2: true - logout: true + logout: true server: csp: flags: diff --git a/roles/web-app-phpldapadmin/config/main.yml b/roles/web-app-phpldapadmin/config/main.yml index 147018e5..1745ae68 100644 --- a/roles/web-app-phpldapadmin/config/main.yml +++ b/roles/web-app-phpldapadmin/config/main.yml @@ -3,7 +3,7 @@ oauth2_proxy: application: application # Needs to be the same as webinterface port: 8080 # application port allowed_groups: - - "/roles/web-app-phpldapadmin-administrator" + - "{{ [RBAC.GROUP.NAME, 'web-app-phpldapadmin-administrator'] | path_join }}" features: matomo: true css: true diff --git a/roles/web-app-phpmyadmin/config/main.yml b/roles/web-app-phpmyadmin/config/main.yml index 31befecb..a17e61c8 100644 --- a/roles/web-app-phpmyadmin/config/main.yml +++ b/roles/web-app-phpmyadmin/config/main.yml @@ -3,7 +3,7 @@ oauth2_proxy: port: "80" application: "application" allowed_groups: - - "/roles/web-app-phpmyadmin-administrator" + - "{{ [RBAC.GROUP.NAME, 'web-app-phpmyadmin-administrator'] | path_join }}" features: matomo: true css: false diff --git a/roles/web-app-yourls/config/main.yml b/roles/web-app-yourls/config/main.yml index 1c1c8bf3..ef6f99c6 100644 --- a/roles/web-app-yourls/config/main.yml +++ b/roles/web-app-yourls/config/main.yml @@ -2,7 +2,7 @@ oauth2_proxy: application: "application" port: "80" allowed_groups: - - "/roles/web-app-yourls-administrator" + - "{{ [RBAC.GROUP.NAME, 'web-app-yourls-administrator'] | path_join }}" acl: blacklist: - "<< defaults_applications[web-app-yourls].server.locations.admin >>" # Protects the admin area