diff --git a/plugins/modules/acl.ps1 b/plugins/modules/acl.ps1 new file mode 100644 index 0000000..37934d2 --- /dev/null +++ b/plugins/modules/acl.ps1 @@ -0,0 +1,144 @@ +#!powershell + +# Copyright: (c) 2023, Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#AnsibleRequires -CSharpUtil Ansible.Basic +#Requires -Module Ansible.ModuleUtils.Legacy +#Requires -Module Ansible.ModuleUtils.SID + +$spec = @{ + options = @{ + object = @{ type = "str"; required = $true; aliases = "path" } + principal = @{ type = "str"; required = $true; aliases = "user" } + rights = @{ type = "str"; required = $true } + object_type = @{ type = "str"; aliases = "rights_attr" } + type = @{ type = "str"; required = $true; choices = "allow", "deny" } + inherit = @{ type = "str"; default = "None" } + inherited_object_type = @{ type = "str" } + state = @{ type = "str"; default = "present"; choices = "absent", "present" } + } +} + +$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) +$module.Result.changed = $false + +Try { + Import-Module ActiveDirectory +} +Catch { + $module.FailJson("Error importing module ActiveDirectory") +} + +$object = $module.Params.object +$principal = $module.Params.principal +$state = $module.Params.state +$type = $module.Params.type +$rights = $module.Params.rights +$object_type = $module.Params.object_type +$inherit = $module.Params.inherit +$inherited_object_type = $module.Params.inherited_object_type + +$user_sid = Convert-ToSID -account_name $principal + +$guidmap = @{} +Get-ADObject -SearchBase ((Get-ADRootDSE).SchemaNamingContext) -LDAPFilter "(schemaidguid=*)" -Properties lDAPDisplayName, schemaIDGUID | + ForEach-Object { $guidmap[$_.lDAPDisplayName] = [System.GUID]$_.schemaIDGUID } + +if ($rights_attr) { + if ($guidmap.Contains($object_type)) { + $objGUID = $guidmap[$object_type] + } + Else { + $module.FailJson("LDAP attribute $rights_attr does not exist") + } +} +Else { + $objGUID = [guid]::empty +} + +if ($inherited_object_type) { + if ($guidmap.Contains($inherited_object_type)) { + $inheritGUID = $guidmap[$inherited_object_type] + } + Else { + $module.FailJson("LDAP attribute $inherited_object_type does not exist") + } +} +Else { + $inheritGUID = [guid]::empty +} + +Try { + $objRights = [System.DirectoryServices.ActiveDirectoryRights]$rights + $InheritanceFlag = [System.DirectoryServices.ActiveDirectorySecurityInheritance]$inherit + + If ($type -eq "allow") { + $objType = [System.Security.AccessControl.AccessControlType]::Allow + } + Else { + $objType = [System.Security.AccessControl.AccessControlType]::Deny + } + + $objUser = New-Object System.Security.Principal.SecurityIdentifier($user_sid) + $objACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($objUser, $objRights, $objType, $objGUID, $InheritanceFlag, $inheritGUID) + $objACL = Get-ACL -Path "AD:\$($object)" + + $match = $false + ForEach ($rule in $objACL.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])) { + If ( + ($rule.ActiveDirectoryRights -eq $objACE.ActiveDirectoryRights) -And + ($rule.InheritanceType -eq $objACE.InheritanceType) -And + ($rule.ObjectType -eq $objACE.ObjectType) -And + ($rule.InheritedObjectType -eq $objACE.InheritedObjectType) -And + ($rule.ObjectFlags -eq $objACE.ObjectFlags) -And + ($rule.AccessControlType -eq $objACE.AccessControlType) -And + ($rule.IdentityReference -eq $objACE.IdentityReference) -And + ($rule.IsInherited -eq $objACE.IsInherited) -And + ($rule.InheritanceFlags -eq $objACE.InheritanceFlags) -And + ($rule.PropagationFlags -eq $objACE.PropagationFlags) + ) { + $match = $true + Break + } + } + + If ($state -eq "present" -And $match -eq $false) { + Try { + $objACL.AddAccessRule($objACE) + Set-ACL -Path "AD:\$($object)" -AclObject $objACL + $module.Result.changed = $true + } + Catch { + $module.FailJson("an exception occurred when adding the specified rule - $($_.Exception.Message)") + } + } + ElseIf ($state -eq "absent" -And $match -eq $true) { + Try { + $objACL.RemoveAccessRule($objACE) + Set-ACL -Path "AD:\$($object)" -AclObject $objACL + $module.Result.changed = $true + } + Catch { + $module.FailJson("an exception occurred when removing the specified rule - $($_.Exception.Message)") + } + } + Else { + # A rule was attempting to be added but already exists + If ($match -eq $true) { + $module.Result.msg = "the specified rule already exists" + $module.ExitJson() + } + # A rule didn't exist that was trying to be removed + Else { + $module.Result.msg = "the specified rule does not exist" + $module.ExitJson() + } + } + +} +Catch { + $module.FailJson("an error occurred when attempting to $type $rights permission(s) on $object for $principal - $($_.Exception.Message)") +} + +$module.ExitJson() diff --git a/plugins/modules/acl.py b/plugins/modules/acl.py new file mode 100644 index 0000000..f9d91d7 --- /dev/null +++ b/plugins/modules/acl.py @@ -0,0 +1,86 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r''' +--- +module: acl +short_description: Used to set ACL's on objects in an Active Directory. +description: + - Used to set ACL's on objects in an Active Directory. +options: + object: + description: The Distinguished Name of object to modify. + type: str + required: yes + aliases: [ path ] + principal: + description: User or Group to add specified rights on the object. + type: str + required: yes + aliases: [ user ] + rights: + description: + - The rights/permissions that are to be allowed/denied for the object. + - The rights can be any right under Microsoft Learn ActiveDirectoryRights + U(https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryrights). + type: str + required: yes + object_type: + description: + - The attribute or object type that the rights are to be allowd/denied for. + - This can be any LDAP attribute or object type. + type: str + aliases: [ rights_attr ] + type: + description: Specify whether to allow or deny the rights specified. + type: str + choices: [ allow, deny ] + required: yes + inherit: + description: + - Inherit flags on the ACL rules. + - For more information on the choices see Microsoft Learn ActiveDirectorySecurityInheritance + U(https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectorysecurityinheritance). + type: str + default: None + inherited_object_type: + description: The inherited attribute or object type the access rule applies on + type: str + state: + description: Specify whether to add C(present) or remove C(absent) the specified access rule. + type: str + choices: [ absent, present ] + default: present +author: + - Mikael Olofsson (@quiphius) +''' + +EXAMPLES = r''' +- name: Let System Adminstrators create/delete users in the MyAdmins OU + microsoft.ad.acl: + path: "OU=MyAdmins,DC=domain,DC=test" + user: System Administrators + rights: CreateChild,DeleteChild + rights_attr: user + type: allow + +- name: Let System Adminstrators manage users in the MyAdmins OU + microsoft.ad.acl: + path: "CN=System Administrators,OU=MyAdmins,DC=domain,DC=test" + user: System Administrators + rights: GenericAll + inherited_object_type: user + inherit: Children + type: allow + +- name: Set the C(Manager can update membership list) in the C(Managed By) tab + microsoft.ad.acl: + object: "CN=System Administrators,OU=MyAdmins,DC=domain,DC=test" + principal: System Administrators + rights: WriteProperty + rights_attr: member + type: allow +'''