#!/usr/bin/python # Copyright (c) 2016, Adfinis SyGroup AG # Tobias Rueetschi # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import annotations DOCUMENTATION = r""" module: udm_share author: - Tobias Rüetschi (@keachi) short_description: Manage samba shares on a univention corporate server description: - This module allows to manage samba shares on a univention corporate server (UCS). It uses the Python API of the UCS to create a new object or edit it. extends_documentation_fragment: - community.general.attributes attributes: check_mode: support: full diff_mode: support: partial options: state: default: "present" choices: [present, absent] description: - Whether the share is present or not. type: str name: required: true description: - Name. type: str host: description: - Host FQDN (server which provides the share), for example V({{ ansible_fqdn }}). Required if O(state=present). type: str path: description: - Directory on the providing server, for example V(/home). Required if O(state=present). type: path sambaName: description: - Windows name. Required if O(state=present). type: str aliases: [samba_name] ou: required: true description: - Organisational unit, inside the LDAP Base DN. type: str owner: default: '0' description: - Directory owner of the share's root directory. type: str group: default: '0' description: - Directory owner group of the share's root directory. type: str directorymode: default: '00755' description: - Permissions for the share's root directory. type: str root_squash: default: true description: - Modify user ID for root user (root squashing). type: bool subtree_checking: default: true description: - Subtree checking. type: bool sync: default: 'sync' description: - NFS synchronisation. type: str writeable: default: true description: - NFS write access. type: bool sambaBlockSize: description: - Blocking size. type: str aliases: [samba_block_size] sambaBlockingLocks: default: true description: - Blocking locks. type: bool aliases: [samba_blocking_locks] sambaBrowseable: description: - Show in Windows network environment. type: bool default: true aliases: [samba_browsable] sambaCreateMode: default: '0744' description: - File mode. type: str aliases: [samba_create_mode] sambaCscPolicy: default: 'manual' description: - Client-side caching policy. type: str aliases: [samba_csc_policy] sambaCustomSettings: default: [] description: - Option name in C(smb.conf) and its value. type: list elements: dict aliases: [samba_custom_settings] sambaDirectoryMode: default: '0755' description: - Directory mode. type: str aliases: [samba_directory_mode] sambaDirectorySecurityMode: default: '0777' description: - Directory security mode. type: str aliases: [samba_directory_security_mode] sambaDosFilemode: default: false description: - Users with write access may modify permissions. type: bool aliases: [samba_dos_filemode] sambaFakeOplocks: default: false description: - Fake oplocks. type: bool aliases: [samba_fake_oplocks] sambaForceCreateMode: default: false description: - Force file mode. type: bool aliases: [samba_force_create_mode] sambaForceDirectoryMode: default: false description: - Force directory mode. type: bool aliases: [samba_force_directory_mode] sambaForceDirectorySecurityMode: default: false description: - Force directory security mode. type: bool aliases: [samba_force_directory_security_mode] sambaForceGroup: description: - Force group. type: str aliases: [samba_force_group] sambaForceSecurityMode: default: false description: - Force security mode. type: bool aliases: [samba_force_security_mode] sambaForceUser: description: - Force user. type: str aliases: [samba_force_user] sambaHideFiles: description: - Hide files. type: str aliases: [samba_hide_files] sambaHideUnreadable: default: false description: - Hide unreadable files/directories. type: bool aliases: [samba_hide_unreadable] sambaHostsAllow: default: [] description: - Allowed host/network. type: list elements: str aliases: [samba_hosts_allow] sambaHostsDeny: default: [] description: - Denied host/network. type: list elements: str aliases: [samba_hosts_deny] sambaInheritAcls: default: true description: - Inherit ACLs. type: bool aliases: [samba_inherit_acls] sambaInheritOwner: default: false description: - Create files/directories with the owner of the parent directory. type: bool aliases: [samba_inherit_owner] sambaInheritPermissions: default: false description: - Create files/directories with permissions of the parent directory. type: bool aliases: [samba_inherit_permissions] sambaInvalidUsers: description: - Invalid users or groups. type: str aliases: [samba_invalid_users] sambaLevel2Oplocks: default: true description: - Level 2 oplocks. type: bool aliases: [samba_level_2_oplocks] sambaLocking: default: true description: - Locking. type: bool aliases: [samba_locking] sambaMSDFSRoot: default: false description: - MSDFS root. type: bool aliases: [samba_msdfs_root] sambaNtAclSupport: default: true description: - NT ACL support. type: bool aliases: [samba_nt_acl_support] sambaOplocks: default: true description: - Oplocks. type: bool aliases: [samba_oplocks] sambaPostexec: description: - Postexec script. type: str aliases: [samba_postexec] sambaPreexec: description: - Preexec script. type: str aliases: [samba_preexec] sambaPublic: default: false description: - Allow anonymous read-only access with a guest user. type: bool aliases: [samba_public] sambaSecurityMode: default: '0777' description: - Security mode. type: str aliases: [samba_security_mode] sambaStrictLocking: default: 'Auto' description: - Strict locking. type: str aliases: [samba_strict_locking] sambaVFSObjects: description: - VFS objects. type: str aliases: [samba_vfs_objects] sambaValidUsers: description: - Valid users or groups. type: str aliases: [samba_valid_users] sambaWriteList: description: - Restrict write access to these users/groups. type: str aliases: [samba_write_list] sambaWriteable: default: true description: - Samba write access. type: bool aliases: [samba_writeable] nfs_hosts: default: [] description: - Only allow access for this host, IP address or network. type: list elements: str nfsCustomSettings: default: [] description: - Option name in exports file. type: list elements: str aliases: [nfs_custom_settings] """ EXAMPLES = r""" - name: Create a share named home on the server ucs.example.com with the path /home community.general.udm_share: name: home path: /home host: ucs.example.com sambaName: Home """ RETURN = """#""" from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.general.plugins.module_utils.univention_umc import ( umc_module_for_add, umc_module_for_edit, ldap_search, base_dn, ) def main(): module = AnsibleModule( argument_spec=dict( name=dict(required=True, type="str"), ou=dict(required=True, type="str"), owner=dict(type="str", default="0"), group=dict(type="str", default="0"), path=dict(type="path"), directorymode=dict(type="str", default="00755"), host=dict(type="str"), root_squash=dict(type="bool", default=True), subtree_checking=dict(type="bool", default=True), sync=dict(type="str", default="sync"), writeable=dict(type="bool", default=True), sambaBlockSize=dict(type="str", aliases=["samba_block_size"]), sambaBlockingLocks=dict(type="bool", aliases=["samba_blocking_locks"], default=True), sambaBrowseable=dict(type="bool", aliases=["samba_browsable"], default=True), sambaCreateMode=dict(type="str", aliases=["samba_create_mode"], default="0744"), sambaCscPolicy=dict(type="str", aliases=["samba_csc_policy"], default="manual"), sambaCustomSettings=dict(type="list", elements="dict", aliases=["samba_custom_settings"], default=[]), sambaDirectoryMode=dict(type="str", aliases=["samba_directory_mode"], default="0755"), sambaDirectorySecurityMode=dict(type="str", aliases=["samba_directory_security_mode"], default="0777"), sambaDosFilemode=dict(type="bool", aliases=["samba_dos_filemode"], default=False), sambaFakeOplocks=dict(type="bool", aliases=["samba_fake_oplocks"], default=False), sambaForceCreateMode=dict(type="bool", aliases=["samba_force_create_mode"], default=False), sambaForceDirectoryMode=dict(type="bool", aliases=["samba_force_directory_mode"], default=False), sambaForceDirectorySecurityMode=dict( type="bool", aliases=["samba_force_directory_security_mode"], default=False ), sambaForceGroup=dict(type="str", aliases=["samba_force_group"]), sambaForceSecurityMode=dict(type="bool", aliases=["samba_force_security_mode"], default=False), sambaForceUser=dict(type="str", aliases=["samba_force_user"]), sambaHideFiles=dict(type="str", aliases=["samba_hide_files"]), sambaHideUnreadable=dict(type="bool", aliases=["samba_hide_unreadable"], default=False), sambaHostsAllow=dict(type="list", elements="str", aliases=["samba_hosts_allow"], default=[]), sambaHostsDeny=dict(type="list", elements="str", aliases=["samba_hosts_deny"], default=[]), sambaInheritAcls=dict(type="bool", aliases=["samba_inherit_acls"], default=True), sambaInheritOwner=dict(type="bool", aliases=["samba_inherit_owner"], default=False), sambaInheritPermissions=dict(type="bool", aliases=["samba_inherit_permissions"], default=False), sambaInvalidUsers=dict(type="str", aliases=["samba_invalid_users"]), sambaLevel2Oplocks=dict(type="bool", aliases=["samba_level_2_oplocks"], default=True), sambaLocking=dict(type="bool", aliases=["samba_locking"], default=True), sambaMSDFSRoot=dict(type="bool", aliases=["samba_msdfs_root"], default=False), sambaName=dict(type="str", aliases=["samba_name"]), sambaNtAclSupport=dict(type="bool", aliases=["samba_nt_acl_support"], default=True), sambaOplocks=dict(type="bool", aliases=["samba_oplocks"], default=True), sambaPostexec=dict(type="str", aliases=["samba_postexec"]), sambaPreexec=dict(type="str", aliases=["samba_preexec"]), sambaPublic=dict(type="bool", aliases=["samba_public"], default=False), sambaSecurityMode=dict(type="str", aliases=["samba_security_mode"], default="0777"), sambaStrictLocking=dict(type="str", aliases=["samba_strict_locking"], default="Auto"), sambaVFSObjects=dict(type="str", aliases=["samba_vfs_objects"]), sambaValidUsers=dict(type="str", aliases=["samba_valid_users"]), sambaWriteList=dict(type="str", aliases=["samba_write_list"]), sambaWriteable=dict(type="bool", aliases=["samba_writeable"], default=True), nfs_hosts=dict(type="list", elements="str", default=[]), nfsCustomSettings=dict(type="list", elements="str", aliases=["nfs_custom_settings"], default=[]), state=dict(default="present", choices=["present", "absent"], type="str"), ), supports_check_mode=True, required_if=([("state", "present", ["path", "host", "sambaName"])]), ) name = module.params["name"] state = module.params["state"] changed = False diff = None obj = list(ldap_search(f"(&(objectClass=univentionShare)(cn={name}))", attr=["cn"])) exists = bool(len(obj)) container = f"cn=shares,ou={module.params['ou']},{base_dn()}" dn = f"cn={name},{container}" if state == "present": try: if not exists: obj = umc_module_for_add("shares/share", container) else: obj = umc_module_for_edit("shares/share", dn) module.params["printablename"] = f"{name} ({module.params['host']})" for k in obj.keys(): if module.params[k] is True: module.params[k] = "1" elif module.params[k] is False: module.params[k] = "0" obj[k] = module.params[k] diff = obj.diff() if exists: for k in obj.keys(): if obj.hasChanged(k): changed = True else: changed = True if not module.check_mode: if not exists: obj.create() elif changed: obj.modify() except Exception as err: module.fail_json(msg=f"Creating/editing share {name} in {container} failed: {err}") if state == "absent" and exists: try: obj = umc_module_for_edit("shares/share", dn) if not module.check_mode: obj.remove() changed = True except Exception as err: module.fail_json(msg=f"Removing share {name} in {container} failed: {err}") module.exit_json(changed=changed, name=name, diff=diff, container=container) if __name__ == "__main__": main()