Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround for user_saml-application to return lower-case realm when configured through environment-variable. #273

Merged
merged 6 commits into from
May 30, 2023
Merged
14 changes: 13 additions & 1 deletion roles/install_nextcloud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,18 @@ The name may not be canon some times. (like **appName-x.y.z** instead of **appNa
Changing a parameter, then running the role again while the app is already enabled will **not** update its configuration.
- this post_install process is tagged and can be called directly using the `--tags install_apps` option.

#### Patch **user_saml** Application

If you centrally administer your users and configure nextcloud to include users via LDAP as user-backend through e.g. `user_ldap` module and want to provide Single-sign-on, you may configure the `user_saml` application using the environment-variable `REMOTE_USER`. In this case, the returned principal contains an upper-case realm. This is undesirable when the user backend stores the principals with realm in lower-case, which is the case for `user_ldap`, because the case-sensitive lookup by `user_saml` module for the existing user would not find the existing user. A typical use-case is, when you run a Samba Domain Controller and manage your users centrally in the Domain and want to provide Single-Sign-On in Nextcloud.
This patch adds a workaround to `SAMLController.php`, which converts the realm to lower-case. To activate this patch, you also need to define `user_saml` application in `nextcloud_apps`.
```yaml
nextcloud_apps:
user_saml:
nextcloud_patch_user_saml_app: true
```
This patch is a modified version of the workaround proposed [here](https://github.com/nextcloud/user_saml/issues/118).
Note: When `user_saml` application is updated, this patch will be overwritten. In this case you may re-apply the patch by calling directly using the `--tags patch_user_saml_app` option. The patch is implemented in a way, that it shall work even when `user_saml`-app (including the patched-file `SAMLController.php`) changes, i.e. it shall be robust against changes of the `user_saml`-app. By an educated guess it will work for future versions of `user_saml`, but in any case it would not change anything if the change to `SAMLController.php` would touch the sensitive code therein.

## Example Playbook
### Case 1: Installing a quick Nextcloud demo
In some case, you may want to deploy quickly many instances of Nextcloud on multiple hosts for testing/demo purpose and don't want to tune the role's variables for each hosts: Just run the playbook without any additional variable (all default) !
Expand Down Expand Up @@ -592,7 +604,7 @@ You can choose the version channel to download a specific version of nextcloud.
### Case 2: Using letsencrypt with this role.
This role is not designed to manage letsencrypt certificates. However you can still use your certificates with nextcloud.

You must create first your certificates using a letsencrypt ACME client or an Ansible role like [this one] (https://github.com/jaywink/ansible-letsencrypt)
You must create first your certificates using a letsencrypt ACME client or an Ansible role like [this one](https://github.com/jaywink/ansible-letsencrypt)

then call _install_nextcloud_ by setting `nextcloud_tls_cert_method: "installed"`

Expand Down
1 change: 1 addition & 0 deletions roles/install_nextcloud/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ nextcloud_tls_session_cache_size: 50m # in Byte or human readable size notation
# [APPS]
nextcloud_apps: {}
nextcloud_disable_apps: []
nextcloud_patch_user_saml_app: false # Apply Workaround to lower-case REALM for REMOTE_USER environment-variable.

# [SYSTEM]
# nextcloud_mysql_root_pwd: "secret"
Expand Down
3 changes: 3 additions & 0 deletions roles/install_nextcloud/files/SAMLController.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (isset($_SERVER['REMOTE_USER'])) {
$_SERVER['REMOTE_USER'] = strtolower($_SERVER['REMOTE_USER']);
}
26 changes: 26 additions & 0 deletions roles/install_nextcloud/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
- nextcloud_apps is mapping
tags:
- install_apps
- patch_user_saml_app
block:
- name: "[NC apps] - lists the number of apps available in the instance."
ansible.builtin.command: php occ app:list --output=json_pretty --no-warnings
Expand All @@ -110,8 +111,10 @@
# do if the app is not enabled and ( (archive path is not "") or (app is disabled) )
when:
- item.key not in nc_available_apps.enabled
- ansible_run_tags is not search('patch_user_saml_app')
with_dict: "{{ nextcloud_apps }}"


- name: Add indices
ansible.builtin.command: php occ db:add-missing-indices
args:
Expand All @@ -122,3 +125,26 @@
register: nc_indices_cmd
changed_when: '"Done" not in nc_indices_cmd.stdout'
when: nextcloud_install_db

- name: "[Main] - Patch from the app 'user_saml' the file SAMLController.php."
when:
- nextcloud_patch_user_saml_app
- nc_available_apps.enabled['user_saml'] is defined or nc_available_apps.disabled['user_saml'] is defined
tags:
- patch_user_saml_app
vars:
pattern: '.*\$this->session->set\(.user_saml\.samlUserData.,\s+\$_SERVER\);.*'
file2patch: "{{ nextcloud_webroot + 'apps/user_saml/lib/Controller/SAMLController.php' }}"
block:
- name: "[Main] - Check if SAMLController.php can be patched."
marioqxx marked this conversation as resolved.
Show resolved Hide resolved
ansible.builtin.slurp:
src: "{{ file2patch }}"
register: df_file

- name: "[Main] - Patch file SAMController.php."
ansible.builtin.blockinfile:
block: "{{ lookup('ansible.builtin.file', 'files/SAMLController.patch') }}"
path: "{{ file2patch }}"
insertbefore: "{{ pattern }}"
marker: " /** {mark} ANSIBLE MANAGED BLOCK */"
when: df_file.content | b64decode | regex_search(pattern)