From 11d1a026aac5788a1bed7ce98437ace2a076ebc1 Mon Sep 17 00:00:00 2001 From: psy Date: Tue, 21 Dec 2021 09:00:44 +0100 Subject: [PATCH] add module for ldap configuration --- README.md | 72 +++++++++++++++++++++++++++++ library/nextcloud_ldap.py | 96 +++++++++++++++++++++++++++++++++++++++ tasks/main.yml | 8 ++++ 3 files changed, 176 insertions(+) create mode 100644 library/nextcloud_ldap.py diff --git a/README.md b/README.md index 5618a6c..6b34f1f 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,75 @@ nextcloud: ``` All configured groups have full edit rights in the group folder. + +LDAP connection is configured as follows: + +```yaml +nextcloud: + ldap: + config_id: 's01' # use existing or next free configuration + config: + "hasMemberOfFilterSupport": 1 + "homeFolderNamingRule": "" + "lastJpegPhotoLookup": 0 + "ldapAgentName": "cn=nextcloud,ou=system,dc=example,dc=com" + "ldapAgentPassword": "" + "ldapAttributesForGroupSearch": "" + "ldapAttributesForUserSearch": "" + "ldapBackupHost": "" + "ldapBackupPort": "" + "ldapBase": + - "ou=users,dc=example,dc=com" + "ldapBaseGroups": + - "ou=groups,dc=example,dc=com" + "ldapBaseUsers": + - "ou=users,dc=example,dc=com" + "ldapCacheTTL": 600 + "ldapDefaultPPolicyDN": "" + "ldapDynamicGroupMemberURL": "" + "ldapEmailAttribute": "mail" + "ldapExperiencedAdmin": 0 + "ldapExpertUUIDGroupAttr": "" + "ldapExpertUUIDUserAttr": "uid" + "ldapExpertUsernameAttr": "uid" + "ldapExtStorageHomeAttribute": "" + "ldapGidNumber": "gidNumber" + "ldapGroupDisplayName": "cn" + "ldapGroupFilter": "(&(|(objectclass=groupOfUniqueNames))(|(cn=service_nextcloud_admin)(!(cn=service_*))))" + "ldapGroupFilterGroups": + - "service_gitlab_access" + "ldapGroupFilterMode": 0 + "ldapGroupFilterObjectclass": + - "top" + "ldapGroupMemberAssocAttr": "uniqueMember" + "ldapHost": "ldaps://sso.example.com" + "ldapIgnoreNamingRules": false + "ldapLoginFilter": "(&(objectClass=posixAccount)(memberOf=cn=service_nextcloud_access,ou=groups,dc=example,dc=com)(uid=%uid))" + "ldapLoginFilterAttributes": "" + "ldapLoginFilterEmail": 0 + "ldapLoginFilterMode": 1 + "ldapLoginFilterUsername": 1 + "ldapMatchingRuleInChainState": "unknown" + "ldapNestedGroups": 0 + "ldapOverrideMainServer": "" + "ldapPagingSize": 500 + "ldapPort": 636 + "ldapQuotaAttribute": "" + "ldapQuotaDefault": "" + "ldapTLS": 0 + "ldapUserAvatarRule": "default" + "ldapUserDisplayName": "displayname" + "ldapUserDisplayName2": "" + "ldapUserFilter": "(&(objectClass=posixAccount)(memberOf=cn=service_nextcloud_access,ou=groups,dc=example,dc=com))" + "ldapUserFilterGroups": + - "service_nextcloud_access" + "ldapUserFilterMode": 1 + "ldapUserFilterObjectclass": + - "posixAccount" + "ldapUuidGroupAttribute": "auto" + "ldapUuidUserAttribute": "auto" + "turnOffCertCheck": 1 + "turnOnPasswordChange": 0 + "useMemberOfToDetectMembership": 1 +``` + diff --git a/library/nextcloud_ldap.py b/library/nextcloud_ldap.py new file mode 100644 index 0000000..ba310f8 --- /dev/null +++ b/library/nextcloud_ldap.py @@ -0,0 +1,96 @@ +from ansible.module_utils.basic import AnsibleModule + +import os +import json + + +def run_module(): + module_args = { + 'nextcloud_path': {'type': 'str', 'default': '/var/www/nextcloud'}, + 'config': {'type': 'dict', 'default': {}} + } + + result = { + 'changed': False, + # 'message': '', + 'diff': {'before': {}, 'after': {}} + } + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True + ) + + if 'config_id' not in module.params: + module.params['config_id'] = 's01' + + os.chdir(module.params['nextcloud_path']) + + rc, stdout, stderr = module.run_command(['/usr/bin/php', 'occ', 'ldap:show-config', '--show-password', '--output', 'json'], check_rc=True, + cwd=module.params['nextcloud_path']) + + try: + current_configs = json.loads(stdout) + except Exception as e: + module.fail_json(msg=str(e), **result) + + if module.params['config']['config_id'] not in current_configs.keys(): + new_config_id_calculated = f"s{len(current_configs.keys())+1:02d}" + + if new_config_id_calculated != module.params['config']['config_id']: + module.fail_json(msg=f"Config ID ({module.params['config']['config_id']}) does not match next free config ID ({new_config_id})!", **result) + + if not module.check_mode: + rc, stdout, stderr = module.run_command(['/usr/bin/php', 'occ', 'ldap:create-empty-config', '--only-print-prefix'], check_rc=True, + cwd=module.params['nextcloud_path']) + new_config_id = stdout.strip() + + if new_config_id != new_config_id_calculated: + module.fail_json(msg=f"New config id ({new_config_id}) is not the same as calculated id ({new_config_id_calculated})!", **result) + + rc, stdout, stderr = module.run_command(['/usr/bin/php', 'occ', 'ldap:show-config', '--show-password', '--output', 'json'], check_rc=True, + cwd=module.params['nextcloud_path']) + + try: + current_configs = json.loads(stdout) + except Exception as e: + module.fail_json(msg=str(e), **result) + + result['changed'] = True + + if module.check_mode: + module.exit_json(**result) + + current_config = current_configs[module.params['config']['config_id']] + new_config = module.params['config']['config'] + + for key in current_config.keys(): + if key in new_config and str(current_config[key]) != str(new_config[key]): + result['diff']['before'][key] = current_config[key] + result['diff']['after'][key] = new_config[key] + + result['changed'] = True + + if not module.check_mode: + try: + rc, stdout, stderr = module.run_command(['/usr/bin/php', 'occ', 'ldap:set-config', module.params['config']['config_id'], key, + ';'.join(new_config[key]) if isinstance(new_config[key], list) else str(new_config[key])], + check_rc=True, cwd=module.params['nextcloud_path']) + except Exception as e: + module.fail_json(msg="Error on key " + key + " : " + str(e), **result) + + rc, stdout, stderr = module.run_command(['/usr/bin/php', 'occ', 'ldap:test-config', module.params['config']['config_id']], check_rc=True, + cwd=module.params['nextcloud_path']) + + if stdout.strip() != 'The configuration is valid and the connection could be established!': + module.fail_json(msg=f"LDAP connection test failed: {stdout}", **result) + + if not module.check_mode: + rc, stdout, stderr = module.run_command(['/usr/bin/php', 'occ', 'ldap:set-config', module.params['config']['config_id'], 'ldapConfigurationActive', + '1'], check_rc=True, cwd=module.params['nextcloud_path']) + + module.exit_json(**result) + + +if __name__ == '__main__': + run_module() diff --git a/tasks/main.yml b/tasks/main.yml index e09e339..15cdbee 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,5 +1,13 @@ - import_tasks: base.yml +- name: configure ldap app + become: true + become_user: www-data + nextcloud_ldap: + config: "{{ nextcloud.ldap }}" + when: + - nextcloud.ldap.config + - include_tasks: groupfolders.yml when: - nextcloud.groupfolders