From 99f633d222c20e0063a24c4b26835c7bc917465e Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Fri, 21 Mar 2025 22:50:48 +0100 Subject: [PATCH] Optimized nextcloud keycloak ldap implementation --- group_vars/all/07_applications.yml | 26 ++++++------ .../templates/import/realm.json.j2 | 22 +++++++++- roles/docker-nextcloud/Applications.md | 6 +++ roles/docker-nextcloud/IAM.md | 40 +++++++++++++++++++ roles/docker-nextcloud/OCC.md | 18 ++++++++- .../templates/config/oidc.config.php.j2 | 4 +- .../docker-portfolio/templates/config.yaml.j2 | 8 ++-- 7 files changed, 103 insertions(+), 21 deletions(-) diff --git a/group_vars/all/07_applications.yml b/group_vars/all/07_applications.yml index 27822adc..61a8d795 100644 --- a/group_vars/all/07_applications.yml +++ b/group_vars/all/07_applications.yml @@ -338,33 +338,33 @@ defaults_applications: ## Nextcloud nextcloud: - version: "production" # @see https://nextcloud.com/blog/nextcloud-release-channels-and-how-to-track-them/ + version: "production" # @see https://nextcloud.com/blog/nextcloud-release-channels-and-how-to-track-them/ ldap: - enabled: True # Enables LDAP by default + enabled: True # Enables LDAP by default oidc: - enabled: "{{ _applications_nextcloud_oidc_enabled }}" # Activate OIDC for Nextcloud + enabled: "{{ _applications_nextcloud_oidc_enabled }}" # Activate OIDC for Nextcloud # floavor decides which OICD plugin should be used. # Available options: oidc_login, sociallogin # @see https://apps.nextcloud.com/apps/oidc_login # @see https://apps.nextcloud.com/apps/sociallogin - flavor: "oidc_login" # Keeping on sociallogin because the other option is not implemented yet + flavor: "oidc_login" # Keeping on sociallogin because the other option is not implemented yet matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style - landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe + landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe database: - central_storage: True # Activate Central Database Storage + central_storage: True # Activate Central Database Storage credentials: -# database_password: Null # Needs to be set in inventory file +# database_password: Null # Needs to be set in inventory file users: administrator: - username: "{{users.administrator.username}}" - initial_password: "{{users.administrator.initial_password}}" # Keep in mind to change the password fast after creation and activate 2FA - default_quota: '1000000000' # Quota to assign if no quota is specified in the OIDC response (bytes) + username: "{{users.administrator.username}}" + initial_password: "{{users.administrator.initial_password}}" # Keep in mind to change the password fast after creation and activate 2FA + default_quota: '1000000000' # Quota to assign if no quota is specified in the OIDC response (bytes) legacy_login_mask: - enabled: False # If true, then legacy login mask is shown. Otherwise just SSO + enabled: False # If true, then legacy login mask is shown. Otherwise just SSO container: - application: "nextcloud-application" # Nextcloud application container name - proxy: "nextcloud-web" # Nextcloud Proxy Container Name + application: "nextcloud-application" # Nextcloud application container name + proxy: "nextcloud-web" # Nextcloud Proxy Container Name performance: php: memory_limit: "{{ ((ansible_memtotal_mb | int) / 30)|int }}M" # Dynamic set memory limit diff --git a/roles/docker-keycloak/templates/import/realm.json.j2 b/roles/docker-keycloak/templates/import/realm.json.j2 index be46d773..adcff45c 100644 --- a/roles/docker-keycloak/templates/import/realm.json.j2 +++ b/roles/docker-keycloak/templates/import/realm.json.j2 @@ -885,6 +885,7 @@ "email" ], "optionalClientScopes": [ + "nextcloud", "address", "phone", "organization", @@ -1195,7 +1196,7 @@ { "id": "15dd4961-5b4f-4635-a3f1-a21e1fa7bf3a", "name": "nextcloud", - "description": "", + "description": "Optimized mappers for nextcloud oidc_login with ldap.", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "false", @@ -1222,6 +1223,25 @@ "claim.name": "nextcloudQuota", "jsonType.label": "int" } + }, + { + "id": "018c63c6-3fea-43fe-abbf-2c17e3f2353f", + "name": "UID Mapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "introspection.token.claim": "true", + "multivalued": "false", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "{{ldap.attributes.user_id}}", + "jsonType.label": "String" + } } ] }, diff --git a/roles/docker-nextcloud/Applications.md b/roles/docker-nextcloud/Applications.md index 7298efa0..322e5972 100644 --- a/roles/docker-nextcloud/Applications.md +++ b/roles/docker-nextcloud/Applications.md @@ -2,6 +2,12 @@ Details on specific apps like Cospend, including related SQL queries and debugging tips. +## Recieve Plugin Information +To recieve the relevant configuration options for a plugin type: +```bash +docker compose exec -u www-data application php occ config:list oidc_login +``` + ## App Relevant Tables 🗃️ - `oc_appconfig` diff --git a/roles/docker-nextcloud/IAM.md b/roles/docker-nextcloud/IAM.md index 5633578f..cabc07d4 100644 --- a/roles/docker-nextcloud/IAM.md +++ b/roles/docker-nextcloud/IAM.md @@ -15,6 +15,12 @@ docker compose exec -u www-data application /var/www/html/occ config:app:get soc More information: https://docs.nextcloud.com/server/latest/admin_manual/configuration_user/user_auth_ldap.html +## Get LDAP Configuration + +```bash +docker compose exec -u www-data application php occ ldap:show-config +``` + ## Get all relevant entries except password ```sql @@ -27,6 +33,40 @@ SELECT * FROM `oc_appconfig` WHERE appid LIKE "%ldap%" and configkey != "s01ldap docker compose exec -it -u www-data application php occ ldap:check-user --update {{username}} ``` +## Update LDAP Sync + +```bash +docker compose exec -u www-data application php occ user:sync-account-data +``` + +### Update Each User +If you want to update **every LDAP user**, run: + +```bash +for user in $(docker compose exec -u www-data application php occ user:list --output=json | jq -r 'keys[]'); do + docker compose exec -u www-data application php occ ldap:check-user --update "$user" +done +``` + +### Unlink All +```bash +for user in $(docker compose exec -u www-data application php occ ldap:show-remnants | tail -n +3 | awk -F '|' '{print $2}' | tr -d ' ' | grep -v '^$'); do + echo "Unlinking user from LDAP: $user" + echo "y" | docker compose exec -T -u www-data application php occ ldap:reset-user "$user" +done +``` + +### Reset LDAP Links for Orphaned Users +Run this **corrected script**: + +```bash +for user in $(docker compose exec -u www-data application php occ ldap:show-remnants | tail -n +3 | awk -F '|' '{print $2}' | tr -d ' ' | grep -v '^$'); do + echo "Resetting LDAP link for user: $user" + echo "y" | docker compose exec -T -u www-data application php occ ldap:reset-user "$user" +done +``` + + ## Federation If users are just created via Keycloak and not via LDAP, they have a different username. Due to this reaso concider to use LDAP to guaranty that the username is valid. diff --git a/roles/docker-nextcloud/OCC.md b/roles/docker-nextcloud/OCC.md index 67faa949..cd21ee23 100644 --- a/roles/docker-nextcloud/OCC.md +++ b/roles/docker-nextcloud/OCC.md @@ -16,6 +16,11 @@ docker-compose exec -it -u www-data application /var/www/html/occ docker compose exec -it -u www-data application php occ user:list ``` +### Get User Info +```bash +docker compose exec -u www-data application php occ user:info {{username}} +``` + ### Sync Users ```bash docker compose exec -it -u www-data application php occ user:sync @@ -35,7 +40,18 @@ docker compose exec -it -u www-data application php occ group:adduser admin {{us ```bash docker compose exec -it -u www-data application php occ user:delete {{username}} ``` ---- + +### Delete all User (if no ldap is used) +```bash +for user in $(docker compose exec -u www-data application php occ user:list --output=json | jq -r 'keys[]'); do + docker compose exec -u www-data application php occ user:delete "$user" +done +``` + +### Identify users which exist still in nextcloud but not in LDAP anymore +```bash +occ ldap:show-remnants +``` ## App Administration ```bash diff --git a/roles/docker-nextcloud/templates/config/oidc.config.php.j2 b/roles/docker-nextcloud/templates/config/oidc.config.php.j2 index f54e9170..093f6e3c 100644 --- a/roles/docker-nextcloud/templates/config/oidc.config.php.j2 +++ b/roles/docker-nextcloud/templates/config/oidc.config.php.j2 @@ -97,10 +97,10 @@ return array ( // note: on Keycloak, OIDC name claim = "${given_name} ${family_name}" or one of them if any is missing // 'oidc_login_attributes' => array ( - 'id' => 'username', + 'id' => '{{ldap.attributes.user_id}}', 'name' => 'name', 'mail' => 'email', - # 'quota' => 'nextcloudQuota', # Not implemented yet + 'quota' => 'nextcloudQuota', # 'home' => 'homeDirectory', # Not implemented yet 'ldap_uid' => 'preferred_username', # 'groups' => 'ownCloudGroups', # Not implemented yet diff --git a/roles/docker-portfolio/templates/config.yaml.j2 b/roles/docker-portfolio/templates/config.yaml.j2 index ecb1cb44..65737811 100644 --- a/roles/docker-portfolio/templates/config.yaml.j2 +++ b/roles/docker-portfolio/templates/config.yaml.j2 @@ -210,7 +210,7 @@ cards: - icon: class: "fa-solid fa-envelope" - title: "Mailu Mail Server" + title: "Mail Server" text: "Revolutionize your email communications with Mailu, a secure and flexible mail server solution that integrates seamlessly into your workflow. Experience enhanced reliability, robust security, and an energetic approach to managing your digital correspondence." url: https://{{domains.mailu}} link_text: "Elevate Your Email Now!" @@ -682,19 +682,19 @@ navigation: class: fas fa-user-shield iframe: {{ applications | get_landingpage_iframe_enabled('keycloak') }} children: - - name: Keycloak Master Admin + - name: Administration description: Access the central admin console icon: class: fa-solid fa-shield-halved url: https://{{domains.keycloak}}/admin iframe: {{ applications | get_landingpage_iframe_enabled('keycloak') }} - - name: Manage Your Profile + - name: Profile description: Update your personal admin settings icon: class: fa-solid fa-user-gear url: https://{{ domains.keycloak }}/realms/{{oidc.client.id}}/account iframe: {{ applications | get_landingpage_iframe_enabled('keycloak') }} - - name: Log Out of Keycloak + - name: Logout description: End your admin session securely icon: class: fa-solid fa-right-from-bracket