Compare commits

..

1 Commits

Author SHA1 Message Date
516e2430d8 feat(oidc_user_backend): add ansible role 2024-09-29 12:52:45 +02:00
13 changed files with 148 additions and 267 deletions

View File

@ -15,8 +15,6 @@ and managing nextcloud installations
server instance. Can install, remove, enable/disable and update apps. server instance. Can install, remove, enable/disable and update apps.
- [`ldap_user_backend`](roles/ldap_user_backend/README.md): - [`ldap_user_backend`](roles/ldap_user_backend/README.md):
Manages LDAP authentication sources in installed nextcloud instances. Manages LDAP authentication sources in installed nextcloud instances.
- [`oidc_user_backend`](roles/oidc_user_backend/README.md):
Manage OIDC authentication sources in installed nextcloud instances.
- [`nginx_fpm_proxy`](roles/nginx_fpm_proxy/README.md): - [`nginx_fpm_proxy`](roles/nginx_fpm_proxy/README.md):
Reverse proxy role which connects to nextcloud using FPM Reverse proxy role which connects to nextcloud using FPM
and serves static content. and serves static content.

View File

@ -1,6 +1,6 @@
namespace: finallycoffee namespace: finallycoffee
name: nextcloud name: nextcloud
version: 0.7.0 version: 0.6.1
readme: README.md readme: README.md
authors: authors:
- transcaffeine <transcaffeine@finally.coffee> - transcaffeine <transcaffeine@finally.coffee>

View File

@ -4,23 +4,26 @@ Configure OIDC user backends in nextcloud using this ansible role.
This role can be run multiple times with different arguments in order to This role can be run multiple times with different arguments in order to
configure multiple oidc-based user backends. configure multiple oidc-based user backends.
> [!WARNING]
> This role is not production ready or finished
## Configuration ## Configuration
Set `oidc_user_backend_provider_identifier` to a unique identifier. Set `oidc_user_occ_user_oidc_provider_identifier` to a unique identifier.
Populate your provider information in the `oidc_user_backend_config_provider_provider_(settings_)` Populate your provider information in the `oidc_user_config_(settings_)`
like this: like this:
```yaml ```yaml
oidc_user_backend_config_provider_identifier: my_provider oidc_user_config_identifier: my_provider
oidc_user_backend_config_provider_discovery_endpoint: https://idp.example.com/ oidc_user_config_discovery_endpoint: https://idp.example.com/
oidc_user_backend_config_provider_client_id: my-client-id oidc_user_config_client_id: my-client-id
oidc_user_backend_config_provider_client_secret: my-client-secret oidc_user_config_client_secret: my-client-secret
# All options to the occ command are avaible in the # All options to the occ command are avaible in the
# `oidc_user_backend_config_provider_settings_` namespace # `oidc_user_config_settings_` namespace
oidc_user_backend_config_provider_settings_unique_id: true oidc_user_config_settings_unique_id: true
oidc_user_backend_config_provider_settings_send_id_token_hint: true oidc_user_config_settings_send_id_token_hint: true
oidc_user_backend_config_provider_settings_mapping_display_name: name oidc_user_config_settings_mapping_display_name: name
oidc_user_backend_config_provider_settings_mapping_uid: preferred_username oidc_user_config_settings_mapping_uid: preferred_username
oidc_user_backend_config_provider_settings_mapping_email: email oidc_user_config_settings_mapping_email: email
``` ```

View File

@ -0,0 +1,47 @@
---
oidc_user_deployment_method: host
oidc_user_deployment_become_user: ~
oidc_user_deployment_method_docker_container_name: nextcloud
oidc_user_deployment_method_podman_container_name: nextcloud
oidc_user_occ_command: "php occ"
oidc_user_occ_user_oidc_provider_identifier: ~
oidc_user_config_identifier: ~
oidc_user_config_client_id: ~
oidc_user_config_client_secret: ~
oidc_user_config_discovery_endpoint: ~
oidc_user_config_end_session_endpoint: ~
oidc_user_config_scopes:
- openid
- email
- profile
oidc_user_config_settings_unique_id: true
oidc_user_config_settings_check_bearer: true
oidc_user_config_settings_send_id_token_hint: true
oidc_user_config_settings_bearer_provisioning: false
oidc_user_config_settings_extra_claims: []
oidc_user_config_settings_provider_based_id: false
oidc_user_config_settings_group_provisioning: false
oidc_user_config_settings_mapping_display_name: name
oidc_user_config_settings_mapping_email: email
oidc_user_config_settings_mapping_quota: ~
oidc_user_config_settings_mapping_uid: sub
oidc_user_config_settings_mapping_groups: ~
oidc_user_config_settings_mapping_address: ~
oidc_user_config_settings_mapping_street_address: ~
oidc_user_config_settings_mapping_postal_code: ~
oidc_user_config_settings_mapping_locality: ~
oidc_user_config_settings_mapping_region: ~
oidc_user_config_settings_mapping_country: ~
oidc_user_config_settings_mapping_website: ~
oidc_user_config_settings_mapping_avatar: ~
oidc_user_config_settings_mapping_twitter: ~
oidc_user_config_settings_mapping_fediverse: ~
oidc_user_config_settings_mapping_organisation: ~
oidc_user_config_settings_mapping_role: ~
oidc_user_config_settings_mapping_headline: ~
oidc_user_config_settings_mapping_biography: ~
oidc_user_config_settings_mapping_phone: ~
oidc_user_config_settings_mapping_gender: ~

View File

@ -1,40 +0,0 @@
---
oidc_user_backend_config_provider_identifier: ~
oidc_user_backend_config_provider_client_id: ~
oidc_user_backend_config_provider_client_secret: ~
oidc_user_backend_config_provider_discovery_endpoint: ~
oidc_user_backend_config_provider_end_session_endpoint: ~
oidc_user_backend_config_provider_scopes:
- openid
- email
- profile
oidc_user_backend_config_provider_settings_unique_uid: true
oidc_user_backend_config_provider_settings_check_bearer: true
oidc_user_backend_config_provider_settings_send_id_token_hint: true
oidc_user_backend_config_provider_settings_bearer_provisioning: false
oidc_user_backend_config_provider_settings_extra_claims: []
oidc_user_backend_config_provider_settings_provider_based_id: false
oidc_user_backend_config_provider_settings_group_provisioning: false
oidc_user_backend_config_provider_settings_mapping_display_name: name
oidc_user_backend_config_provider_settings_mapping_email: email
oidc_user_backend_config_provider_settings_mapping_quota: ~
oidc_user_backend_config_provider_settings_mapping_uid: sub
oidc_user_backend_config_provider_settings_mapping_groups: ~
oidc_user_backend_config_provider_settings_mapping_address: ~
oidc_user_backend_config_provider_settings_mapping_street_address: ~
oidc_user_backend_config_provider_settings_mapping_postal_code: ~
oidc_user_backend_config_provider_settings_mapping_locality: ~
oidc_user_backend_config_provider_settings_mapping_region: ~
oidc_user_backend_config_provider_settings_mapping_country: ~
oidc_user_backend_config_provider_settings_mapping_website: ~
oidc_user_backend_config_provider_settings_mapping_avatar: ~
oidc_user_backend_config_provider_settings_mapping_twitter: ~
oidc_user_backend_config_provider_settings_mapping_fediverse: ~
oidc_user_backend_config_provider_settings_mapping_organisation: ~
oidc_user_backend_config_provider_settings_mapping_role: ~
oidc_user_backend_config_provider_settings_mapping_headline: ~
oidc_user_backend_config_provider_settings_mapping_biography: ~
oidc_user_backend_config_provider_settings_mapping_phone: ~
oidc_user_backend_config_provider_settings_mapping_gender: ~

View File

@ -1,5 +0,0 @@
---
oidc_user_backend_deployment_method: host
oidc_user_backend_deployment_become_user: ~
oidc_user_backend_deployment_method_docker_container_name: nextcloud
oidc_user_backend_deployment_method_podman_container_name: nextcloud

View File

@ -1,15 +0,0 @@
---
oidc_user_backend_occ_command: "php occ"
oidc_user_backend_occ_user_oidc_provider_identifier: >-2
{{ oidc_user_backend_config_provider_identifier }}
oidc_user_backend_force_update: false
oidc_user_backend_occ_user_oidc_provider_set_command: >-2
{{ oidc_user_backend_occ_command }} user_oidc:provider
{{ oidc_user_backend_occ_user_oidc_provider_options }}
{{ oidc_user_backend_occ_user_oidc_provider_identifier }}
oidc_user_backend_occ_user_oidc_provider_list_command: >-2
{{ oidc_user_backend_occ_command }} user_oidc:provider --output=json
oidc_user_backend_occ_user_oidc_provider_get_command: >-2
{{ oidc_user_backend_occ_command }} user_oidc:provider --output=json
{{ oidc_user_backend_occ_user_oidc_provider_identifier }}

View File

@ -1,41 +0,0 @@
---
- name: Execute OCC command (host)
ansible.builtin.command:
cmd: "{{ oidc_user_backend_occ_command_to_exec }}"
become_user: "{{ oidc_user_backend_occ_user_to_become }}"
register: oidc_user_backend_occ_command_result_host
when: oidc_user_backend_deployment_method == 'host'
- name: Execute OCC command (docker)
community.docker.docker_container_exec:
container: >-2
{{ oidc_user_backend_deployment_method_docker_container_name }}
command: "{{ oidc_user_backend_occ_command_to_exec }}"
user: "{{ oidc_user_backend_occ_user_to_become | default(omit, true) }}"
register: oidc_user_backend_occ_command_result_docker
when: oidc_user_backend_deployment_method == 'docker'
- name: Execute OCC command (podman)
containers.podman.podman_container_exec:
name: >-2
{{ oidc_user_backend_deployment_method_podman_container_name }}
command: "{{ oidc_user_backend_occ_command_to_exec }}"
user: "{{ oidc_user_backend_occ_user_to_become | default(omit, true) }}"
register: oidc_user_backend_occ_command_result_podman
when: oidc_user_backend_deployment_method == 'podman'
- name: Register result into variable
ansible.builtin.set_fact: {
"{{ oidc_user_backend_occ_command_result_var }}" : "{{
oidc_user_backend_occ_command_result.stdout | string | from_json
}}"
}
vars:
oidc_user_backend_occ_result_map:
host: "{{ oidc_user_backend_occ_command_result_host }}"
docker: "{{ oidc_user_backend_occ_command_result_docker }}"
podman: "{{ oidc_user_backend_occ_command_result_podman }}"
oidc_user_backend_occ_command_result: >-2
{{ oidc_user_backend_occ_result_map[oidc_user_backend_deployment_method]
| default(false, true) }}
when: oidc_user_backend_occ_command_result_var | default(false, true)

View File

@ -1,52 +1,29 @@
--- ---
- name: Check if deployment method is supported - name: Check if deployment method is supported
ansible.builtin.fail: ansible.builtin.fail:
msg: >-2 msg: >-2
Deployment method '{{ oidc_user_backend_deployment_method }}' is not supported! Deployment method '{{ oidc_user_deployment_method }}' is not supported!
Supported are: {{ oidc_user_backend_deployment_methods | join(', ') }} Supported are: {{ oidc_user_deployment_methods | join(', ') }}
when: oidc_user_backend_deployment_method not in oidc_user_backend_deployment_methods when: oidc_user_deployment_method not in oidc_user_deployment_methods
- name: Lookup become user info - name: Configure OIDC provider
ansible.builtin.user: ansible.builtin.command:
name: "{{ oidc_user_backend_deployment_become_user }}" cmd: "{{ oidc_user_occ_user_oidc_provider_set_command }}"
state: present become_user: "{{ oidc_user_deployment_become_user }}"
check_mode: true become: "{{ oidc_user_deployment_become_user | default(false, true) }}"
register: oidc_user_backend_deployment_become_user_info when: oidc_user_deployment_method == 'host'
when: oidc_user_backend_deployment_become_user | default(false, true)
- name: Retrieve configured providers - name: Configure OIDC provider (docker)
ansible.builtin.include_tasks: community.docker.docker_container_exec:
file: execute-occ.yml container: "{{ oidc_user_deployment_method_docker_container_name }}"
vars: command: "{{ oidc_user_occ_user_oidc_provider_set_command }}"
oidc_user_backend_occ_command_to_exec: >- user: "{{ oidc_user_deployment_become_user | default(omit, true) }}"
{{ oidc_user_backend_occ_user_oidc_provider_get_command }} when: oidc_user_deployment_method == 'docker'
oidc_user_backend_occ_user_to_become: "{{ oidc_user_backend_deployment_become_user_info.uid }}"
oidc_user_backend_occ_command_result_var: "oidc_user_backend_occ_user_oidc_provider"
- name: Check if provider information should be updated - name: Configure OIDC provider (podman)
set_fact: containers.podman.podman_container_exec:
oidc_user_backend_backend_force_update: true name: "{{ oidc_user_deployment_method_podman_container_name }}"
loop: "{{ lookup('ansible.utils.to_paths', oidc_user_backend_occ_user_oidc_provider) | dict2items }}" command: "{{ oidc_user_occ_user_oidc_provider_set_command }}"
loop_control: user: "{{ oidc_user_deployment_become_user | default(omit, true) }}"
label: "{{ item.key }}" when: oidc_user_deployment_method == 'podman'
vars:
target_config: >-2
{{ lookup('ansible.utils.to_paths', oidc_user_backend_occ_user_oidc_config_provider_dict) }}
when:
- item.key not in oidc_user_backend_occ_user_oidc_provider_ignored_settings
- (item.value != None) and (target_config[item.key] != None)
- >-2
(target_config[item.key] != None) | ternary(
(item.value != target_config[item.key]),
(item.value | string | length > 0)
)
- name: Update configuration for provider '{{ oidc_user_backend_config_provider_identifier }}'
ansible.builtin.include_tasks:
file: execute-occ.yml
vars:
oidc_user_backend_occ_command_to_exec: >-
{{ oidc_user_backend_occ_user_oidc_provider_set_command }}
oidc_user_backend_occ_user_to_become: "{{ oidc_user_backend_deployment_become_user_info.uid }}"
oidc_user_backend_occ_command_result_var: ~
when: oidc_user_backend_backend_force_update | default(false, true)

View File

@ -0,0 +1,63 @@
---
oidc_user_deployment_methods:
- host
- docker
- podman
oidc_user_occ_user_oidc_options_dict:
clientid: "{{ oidc_user_config_client_id }}"
clientsecret: "{{ oidc_user_config_client_secret }}"
discoveryuri: "{{ oidc_user_config_discovery_endpoint }}"
endsessionendpointuri: "{{ oidc_user_config_end_session_endpoint }}"
scope: "'{{ oidc_user_config_scopes | default([], true) | join(' ') }}'"
"unique-uid": >-2
{{ oidc_user_config_settings_unique_id | bool | ternary(1, 0) }}
"check-bearer": >-2
{{ oidc_user_config_settings_check_bearer | bool | ternary(1, 0) }}
"send-id-token-hint": >-2
{{ oidc_user_config_settings_send_id_token_hint | bool | ternary(1, 0) }}
"group-provisioning": >-2
{{ oidc_user_config_settings_group_provisioning | bool | ternary(1, 0) }}
"extra-claims": >-2
{{ (oidc_user_config_settings_extra_claims | default([]) | length > 0)
| ternary(oidc_user_config_settings_extra_claims | join(' ') | quote, '') }}
oidc_user_occ_user_oidc_mapping_options_dict:
"display-name": "{{ oidc_user_config_settings_mapping_display_name }}"
email: "{{ oidc_user_config_settings_mapping_email }}"
quota: "{{ oidc_user_config_settings_mapping_quota }}"
uid: "{{ oidc_user_config_settings_mapping_uid }}"
groups: "{{ oidc_user_config_settings_mapping_groups }}"
website: "{{ oidc_user_config_settings_mapping_website }}"
avatar: "{{ oidc_user_config_settings_mapping_avatar }}"
twitter: "{{ oidc_user_config_settings_mapping_twitter }}"
fediverse: "{{ oidc_user_config_settings_mapping_fediverse }}"
organisation: "{{ oidc_user_config_settings_mapping_organisation }}"
role: "{{ oidc_user_config_settings_mapping_role }}"
headline: "{{ oidc_user_config_settings_mapping_headline }}"
biography: "{{ oidc_user_config_settings_mapping_biography }}"
phone: "{{ oidc_user_config_settings_mapping_phone }}"
gender: "{{ oidc_user_config_settings_mapping_gender }}"
address: "{{ oidc_user_config_settings_mapping_address }}"
street_address: "{{ oidc_user_config_settings_mapping_street_address }}"
postal_code: "{{ oidc_user_config_settings_mapping_postal_code }}"
locality: "{{ oidc_user_config_settings_mapping_locality }}"
region: "{{ oidc_user_config_settings_mapping_region }}"
country: "{{ oidc_user_config_settings_mapping_country }}"
oidc_user_occ_user_oidc_provider_options: >-2
{% for tuple in oidc_user_occ_user_oidc_options_dict | dict2items %}
{% if tuple.value | default(false, true) %}
--{{ tuple.key }}={{ tuple.value }}
{% endif %}
{% endfor %}
{% for tuple in oidc_user_occ_user_oidc_mapping_options_dict | dict2items %}
{% if tuple.value | default(false, true) %}
--mapping-{{ tuple.key }}={{ tuple.value }}
{% endif %}
{% endfor %}
oidc_user_occ_user_oidc_provider_set_command: >-2
{{ oidc_user_occ_command }} user_oidc:provider
{{ oidc_user_occ_user_oidc_provider_options }}
{{ oidc_user_occ_user_oidc_provider_identifier }}

View File

@ -1,9 +0,0 @@
---
oidc_user_backend_deployment_methods:
- host
- docker
- podman
oidc_user_backend_occ_user_oidc_provider_ignored_settings:
- 'id'
- 'settings.bearerProvisioning'

View File

@ -1,43 +0,0 @@
---
# JSON structure of the `occ` response with `--output=json`
oidc_user_backend_occ_user_oidc_config_provider_dict:
identifier: "{{ oidc_user_backend_config_provider_identifier }}"
clientId: "{{ oidc_user_backend_config_provider_client_id }}"
clientSecret: "{{ oidc_user_backend_config_provider_client_secret }}"
discoveryEndpoint: "{{ oidc_user_backend_config_provider_discovery_endpoint }}"
endSessionEndpoint: "{{ oidc_user_backend_config_provider_end_session_endpoint }}"
scope: "{{ oidc_user_backend_config_provider_scopes | default([], true) | join(' ') }}"
settings:
uniqueUid: >-2
{{ oidc_user_backend_config_provider_settings_unique_uid | bool }}
providerBasedId: >-2
{{ oidc_user_backend_config_provider_settings_provider_based_id | bool }}
checkBearer: >-2
{{ oidc_user_backend_config_provider_settings_check_bearer | bool }}
sendIdTokenHint: >-2
{{ oidc_user_backend_config_provider_settings_send_id_token_hint | bool }}
groupProvisioning: >-2
{{ oidc_user_backend_config_provider_settings_group_provisioning | bool }}
extraClaims: >-2
{{ oidc_user_backend_config_provider_settings_extra_claims | default([]) | join(' ') }}
mappingDisplayName: "{{ oidc_user_backend_config_provider_settings_mapping_display_name }}"
mappingEmail: "{{ oidc_user_backend_config_provider_settings_mapping_email }}"
mappingQuota: "{{ oidc_user_backend_config_provider_settings_mapping_quota }}"
mappingUid: "{{ oidc_user_backend_config_provider_settings_mapping_uid }}"
mappingGroups: "{{ oidc_user_backend_config_provider_settings_mapping_groups }}"
mappingWebsite: "{{ oidc_user_backend_config_provider_settings_mapping_website }}"
mappingAvatar: "{{ oidc_user_backend_config_provider_settings_mapping_avatar }}"
mappingTwitter: "{{ oidc_user_backend_config_provider_settings_mapping_twitter }}"
mappingFediverse: "{{ oidc_user_backend_config_provider_settings_mapping_fediverse }}"
mappingOrganisation: "{{ oidc_user_backend_config_provider_settings_mapping_organisation }}"
mappingRole: "{{ oidc_user_backend_config_provider_settings_mapping_role }}"
mappingHeadline: "{{ oidc_user_backend_config_provider_settings_mapping_headline }}"
mappingBiography: "{{ oidc_user_backend_config_provider_settings_mapping_biography }}"
mappingPhonenumber: "{{ oidc_user_backend_config_provider_settings_mapping_phone }}"
mappingGender: "{{ oidc_user_backend_config_provider_settings_mapping_gender }}"
mappingAddress: "{{ oidc_user_backend_config_provider_settings_mapping_address }}"
mappingStreetaddress: "{{ oidc_user_backend_config_provider_settings_mapping_street_address }}"
mappingPostalcode: "{{ oidc_user_backend_config_provider_settings_mapping_postal_code }}"
mappingLocality: "{{ oidc_user_backend_config_provider_settings_mapping_locality }}"
mappingRegion: "{{ oidc_user_backend_config_provider_settings_mapping_region }}"
mappingCountry: "{{ oidc_user_backend_config_provider_settings_mapping_country }}"

View File

@ -1,54 +0,0 @@
---
# Structure how `occ user_oidc:provider [options] [<identifier>]` expects them
oidc_user_backend_occ_user_oidc_provider_options_dict:
clientid: "{{ oidc_user_backend_config_provider_client_id }}"
clientsecret: "{{ oidc_user_backend_config_provider_client_secret }}"
discoveryuri: "{{ oidc_user_backend_config_provider_discovery_endpoint }}"
endsessionendpointuri: "{{ oidc_user_backend_config_provider_end_session_endpoint }}"
scope: "'{{ oidc_user_backend_config_provider_scopes | default([], true) | join(' ') }}'"
"unique-uid": >-2
{{ oidc_user_backend_config_provider_settings_unique_uid | bool | ternary(1, 0) }}
"check-bearer": >-2
{{ oidc_user_backend_config_provider_settings_check_bearer | bool | ternary(1, 0) }}
"send-id-token-hint": >-2
{{ oidc_user_backend_config_provider_settings_send_id_token_hint | bool | ternary(1, 0) }}
"group-provisioning": >-2
{{ oidc_user_backend_config_provider_settings_group_provisioning | bool | ternary(1, 0) }}
"extra-claims": >-2
{{ (oidc_user_backend_config_provider_settings_extra_claims | default([]) | length > 0)
| ternary(oidc_user_backend_config_provider_settings_extra_claims | join(' ') | quote, '') }}
oidc_user_backend_occ_user_oidc_provider_mapping_options_dict:
"display-name": "{{ oidc_user_backend_config_provider_settings_mapping_display_name }}"
email: "{{ oidc_user_backend_config_provider_settings_mapping_email }}"
quota: "{{ oidc_user_backend_config_provider_settings_mapping_quota }}"
uid: "{{ oidc_user_backend_config_provider_settings_mapping_uid }}"
groups: "{{ oidc_user_backend_config_provider_settings_mapping_groups }}"
website: "{{ oidc_user_backend_config_provider_settings_mapping_website }}"
avatar: "{{ oidc_user_backend_config_provider_settings_mapping_avatar }}"
twitter: "{{ oidc_user_backend_config_provider_settings_mapping_twitter }}"
fediverse: "{{ oidc_user_backend_config_provider_settings_mapping_fediverse }}"
organisation: "{{ oidc_user_backend_config_provider_settings_mapping_organisation }}"
role: "{{ oidc_user_backend_config_provider_settings_mapping_role }}"
headline: "{{ oidc_user_backend_config_provider_settings_mapping_headline }}"
biography: "{{ oidc_user_backend_config_provider_settings_mapping_biography }}"
phone: "{{ oidc_user_backend_config_provider_settings_mapping_phone }}"
gender: "{{ oidc_user_backend_config_provider_settings_mapping_gender }}"
address: "{{ oidc_user_backend_config_provider_settings_mapping_address }}"
street_address: "{{ oidc_user_backend_config_provider_settings_mapping_street_address }}"
postal_code: "{{ oidc_user_backend_config_provider_settings_mapping_postal_code }}"
locality: "{{ oidc_user_backend_config_provider_settings_mapping_locality }}"
region: "{{ oidc_user_backend_config_provider_settings_mapping_region }}"
country: "{{ oidc_user_backend_config_provider_settings_mapping_country }}"
oidc_user_backend_occ_user_oidc_provider_options: >-2
{% for tuple in oidc_user_backend_occ_user_oidc_provider_options_dict | dict2items %}
{% if tuple.value | default(false, true) %}
--{{ tuple.key }}={{ tuple.value }}
{% endif %}
{% endfor %}
{% for tuple in oidc_user_backend_occ_user_oidc_provider_mapping_options_dict | dict2items %}
{% if tuple.value | default(false, true) %}
--mapping-{{ tuple.key }}={{ tuple.value }}
{% endif %}
{% endfor %}