summaryrefslogtreecommitdiffstats
path: root/ansible_collections/microsoft/ad/plugins/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-26 06:22:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-26 06:22:20 +0000
commit18bd2207b6c1977e99a93673a7be099e23f0f547 (patch)
tree40fd9e5913462a88be6ba24be6953383c5b39874 /ansible_collections/microsoft/ad/plugins/modules
parentReleasing progress-linux version 10.0.1+dfsg-1~progress7.99u1. (diff)
downloadansible-18bd2207b6c1977e99a93673a7be099e23f0f547.tar.xz
ansible-18bd2207b6c1977e99a93673a7be099e23f0f547.zip
Merging upstream version 10.1.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/microsoft/ad/plugins/modules')
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/computer.ps174
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/computer.py59
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/domain.py1
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/domain_child.ps1242
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/domain_child.yml184
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/domain_controller.py5
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/group.ps1135
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/group.py57
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/membership.ps12
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/object.py8
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/object_info.py4
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/ou.ps11
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/ou.py15
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/user.ps1108
-rw-r--r--ansible_collections/microsoft/ad/plugins/modules/user.py78
15 files changed, 666 insertions, 307 deletions
diff --git a/ansible_collections/microsoft/ad/plugins/modules/computer.ps1 b/ansible_collections/microsoft/ad/plugins/modules/computer.ps1
index b97bb1062..9010c103d 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/computer.ps1
+++ b/ansible_collections/microsoft/ad/plugins/modules/computer.ps1
@@ -12,15 +12,10 @@ $setParams = @{
Name = 'delegates'
Option = @{
aliases = 'principals_allowed_to_delegate'
- type = 'dict'
- options = @{
- add = @{ type = 'list'; elements = 'str' }
- remove = @{ type = 'list'; elements = 'str' }
- set = @{ type = 'list'; elements = 'str' }
- }
+ type = 'add_remove_set'
}
Attribute = 'PrincipalsAllowedToDelegateToAccount'
- CaseInsensitive = $true
+ DNLookup = $true
}
[PSCustomObject]@{
Name = 'dns_hostname'
@@ -35,24 +30,8 @@ $setParams = @{
[PSCustomObject]@{
Name = 'kerberos_encryption_types'
Option = @{
- type = 'dict'
- options = @{
- add = @{
- choices = 'aes128', 'aes256', 'des', 'rc4'
- type = 'list'
- elements = 'str'
- }
- remove = @{
- choices = 'aes128', 'aes256', 'des', 'rc4'
- type = 'list'
- elements = 'str'
- }
- set = @{
- choices = 'aes128', 'aes256', 'des', 'rc4'
- type = 'list'
- elements = 'str'
- }
- }
+ type = 'add_remove_set'
+ choices = 'aes128', 'aes256', 'des', 'rc4'
}
Attribute = 'KerberosEncryptionType'
CaseInsensitive = $true
@@ -107,8 +86,9 @@ $setParams = @{
}
[PSCustomObject]@{
Name = 'managed_by'
- Option = @{ type = 'str' }
+ Option = @{ type = 'raw' }
Attribute = 'ManagedBy'
+ DNLookup = $true
}
[PSCustomObject]@{
Name = 'sam_account_name'
@@ -119,45 +99,11 @@ $setParams = @{
Name = 'spn'
Option = @{
aliases = 'spns'
- type = 'dict'
- options = @{
- add = @{ type = 'list'; elements = 'str' }
- remove = @{ type = 'list'; elements = 'str' }
- set = @{ type = 'list'; elements = 'str' }
- }
- }
- Attribute = 'ServicePrincipalNames'
- New = {
- param($Module, $ADParams, $NewParams)
-
- $spns = @(
- $Module.Params.spn.add
- $Module.Params.spn.set
- ) | Select-Object -Unique
-
- $NewParams.ServicePrincipalNames = $spns
- $Module.Diff.after.spn = $spns
- }
- Set = {
- param($Module, $ADParams, $SetParams, $ADObject)
-
- $desired = $Module.Params.spn
- $compareParams = @{
- Existing = $ADObject.ServicePrincipalNames
- CaseInsensitive = $true
- }
- $res = Compare-AnsibleADIdempotentList @compareParams @desired
- if ($res.Changed) {
- $SetParams.ServicePrincipalNames = @{}
- if ($res.ToAdd) {
- $SetParams.ServicePrincipalNames.Add = $res.ToAdd
- }
- if ($res.ToRemove) {
- $SetParams.ServicePrincipalNames.Remove = $res.ToRemove
- }
- }
- $module.Diff.after.kerberos_encryption_types = @($res.Value | Sort-Object)
+ type = 'add_remove_set'
}
+ Attribute = 'servicePrincipalName'
+ CaseInsensitive = $true
+ IsRawAttribute = $true
}
[PSCustomObject]@{
Name = 'trusted_for_delegation'
diff --git a/ansible_collections/microsoft/ad/plugins/modules/computer.py b/ansible_collections/microsoft/ad/plugins/modules/computer.py
index ab336d6b4..cf160256a 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/computer.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/computer.py
@@ -15,14 +15,19 @@ options:
description:
- The principal objects that the current AD object can trust for
delegation to either add, remove or set.
- - The values for each sub option must be specified as a distinguished name
- C(CN=shenetworks,CN=Users,DC=ansible,DC=test)
+ - Each subkey value is a list of values in the form of a
+ C(distinguishedName), C(objectGUID), C(objectSid), C(sAMAccountName),
+ or C(userPrincipalName) string or a dictionary with the I(name) and
+ optional I(server) key.
- This is the value set on the C(msDS-AllowedToActOnBehalfOfOtherIdentity)
LDAP attribute.
- This is a highly sensitive attribute as it allows the principals
specified to impersonate any account when authenticating with the AD
computer object being managed.
- To clear all principals, use I(set) with an empty list.
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information on how DN lookups work.
- See R(Setting list option values,ansible_collections.microsoft.ad.docsite.guide_list_values)
for more information on how to add/remove/set list options.
aliases:
@@ -31,29 +36,35 @@ options:
suboptions:
add:
description:
- - The AD objects by their C(DistinguishedName) to add as a principal
- allowed to delegate.
+ - Adds the principals specified as principals allowed to delegate to.
- Any existing principals not specified by I(add) will be untouched
unless specified by I(remove) or not in I(set).
type: list
- elements: str
+ elements: raw
+ lookup_failure_action:
+ description:
+ - Control the action to take when the lookup fails to find the DN.
+ - C(fail) will cause the task to fail.
+ - C(ignore) will ignore the value and continue.
+ - C(warn) will ignore the value and display a warning.
+ choices: ['fail', 'ignore', 'warn']
+ default: fail
+ type: str
remove:
description:
- - The AD objects by their C(DistinguishedName) to remove as a principal
- allowed to delegate.
+ - Removes the principals specified as principals allowed to delegate to.
- Any existing pricipals not specified by I(remove) will be untouched
unless I(set) is defined.
type: list
- elements: str
+ elements: raw
set:
description:
- - The AD objects by their C(DistinguishedName) to set as the only
- principals allowed to delegate.
+ - Sets the principals specified as principals allowed to delegate to.
- This will remove any existing principals if not specified in this
list.
- Specify an empty list to remove all principals allowed to delegate.
type: list
- elements: str
+ elements: raw
dns_hostname:
description:
- Specifies the fully qualified domain name (FQDN) of the computer.
@@ -124,9 +135,13 @@ options:
description:
- The user or group that manages the object.
- The value can be in the form of a C(distinguishedName), C(objectGUID),
- C(objectSid), or sAMAccountName).
+ C(objectSid), C(sAMAccountName), or C(userPrincipalName) string or a
+ dictionary with the I(name) and optional I(server) key.
- This is the value set on the C(managedBy) LDAP attribute.
- type: str
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information on how DN lookups work.
+ type: raw
sam_account_name:
description:
- The C(sAMAccountName) value to set for the group.
@@ -220,7 +235,7 @@ EXAMPLES = r"""
dns_hostname: one_linux_server.my_org.local
path: OU=servers,DC=my_org,DC=local
description: Example of linux server
- enabled: yes
+ enabled: true
state: present
- name: Remove linux computer from Active Directory using a windows machine
@@ -233,26 +248,26 @@ EXAMPLES = r"""
identity: TheComputer
spn:
add:
- - HOST/TheComputer
- - HOST/TheComputer.domain.test
- - HOST/TheComputer.domain.test:1234
+ - HOST/TheComputer
+ - HOST/TheComputer.domain.test
+ - HOST/TheComputer.domain.test:1234
- name: Remove SPNs on the computer
microsoft.ad.computer:
identity: TheComputer
spn:
remove:
- - HOST/TheComputer
- - HOST/TheComputer.domain.test
- - HOST/TheComputer.domain.test:1234
+ - HOST/TheComputer
+ - HOST/TheComputer.domain.test
+ - HOST/TheComputer.domain.test:1234
- name: Set the principals the computer trusts for delegation from
microsoft.ad.computer:
identity: TheComputer
delegates:
set:
- - CN=FileShare,OU=Computers,DC=domain,DC=test
- - CN=DC,OU=Domain Controllers,DC=domain,DC=test
+ - CN=FileShare,OU=Computers,DC=domain,DC=test
+ - OtherServer$ # Lookup by sAMAaccountName
"""
RETURN = r"""
diff --git a/ansible_collections/microsoft/ad/plugins/modules/domain.py b/ansible_collections/microsoft/ad/plugins/modules/domain.py
index 15578f7fd..0d9359242 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/domain.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/domain.py
@@ -99,6 +99,7 @@ attributes:
bypass_host_loop:
support: none
seealso:
+- module: microsoft.ad.domain_child
- module: microsoft.ad.domain_controller
- module: microsoft.ad.group
- module: microsoft.ad.membership
diff --git a/ansible_collections/microsoft/ad/plugins/modules/domain_child.ps1 b/ansible_collections/microsoft/ad/plugins/modules/domain_child.ps1
new file mode 100644
index 000000000..85fe3053d
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/modules/domain_child.ps1
@@ -0,0 +1,242 @@
+#!powershell
+
+# Copyright (c) 2024 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#AnsibleRequires -CSharpUtil Ansible.Basic
+
+$spec = @{
+ options = @{
+ create_dns_delegation = @{
+ type = 'bool'
+ }
+ database_path = @{
+ type = 'path'
+ }
+ dns_domain_name = @{
+ type = 'str'
+ }
+ domain_admin_password = @{
+ type = 'str'
+ required = $true
+ no_log = $true
+ }
+ domain_admin_user = @{
+ type = 'str'
+ required = $true
+ }
+ domain_mode = @{
+ type = 'str'
+ }
+ domain_type = @{
+ choices = 'child', 'tree'
+ default = 'child'
+ type = 'str'
+ }
+ install_dns = @{
+ type = 'bool'
+ }
+ log_path = @{
+ type = 'path'
+ }
+ parent_domain_name = @{
+ type = 'str'
+ }
+ reboot = @{
+ default = $false
+ type = 'bool'
+ }
+ safe_mode_password = @{
+ type = 'str'
+ required = $true
+ no_log = $true
+ }
+ site_name = @{
+ type = 'str'
+ }
+ sysvol_path = @{
+ type = 'path'
+ }
+ }
+ required_if = @(
+ , @('domain_type', 'tree', @('parent_domain_name'))
+ )
+ required_together = @(
+ , @("domain_admin_user", "domain_admin_password")
+ )
+ supports_check_mode = $true
+}
+$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
+
+$module.Result.reboot_required = $false
+$module.Result._do_action_reboot = $false # Used by action plugin
+
+$createDnsDelegation = $module.Params.create_dns_delegation
+$databasePath = $module.Params.database_path
+$dnsDomainName = $module.Params.dns_domain_name
+$domainMode = $module.Params.domain_mode
+$domainType = $module.Params.domain_type
+$installDns = $module.Params.install_dns
+$logPath = $module.Params.log_path
+$parentDomainName = $module.Params.parent_domain_name
+$safeModePassword = $module.Params.safe_mode_password
+$siteName = $module.Params.site_name
+$sysvolPath = $module.Params.sysvol_path
+
+$domainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList @(
+ $module.Params.domain_admin_user,
+ (ConvertTo-SecureString -AsPlainText -Force -String $module.Params.domain_admin_password)
+)
+
+if ($domainType -eq 'child' -and $parentDomainName) {
+ $module.FailJson("parent_domain_name must not be set when domain_type=child")
+}
+
+$requiredFeatures = @("AD-Domain-Services", "RSAT-ADDS")
+$features = Get-WindowsFeature -Name $requiredFeatures
+$unavailableFeatures = Compare-Object -ReferenceObject $requiredFeatures -DifferenceObject $features.Name -PassThru
+
+if ($unavailableFeatures) {
+ $module.FailJson("The following features required for a domain child are unavailable: $($unavailableFeatures -join ',')")
+}
+
+$missingFeatures = $features | Where-Object InstallState -NE Installed
+if ($missingFeatures) {
+ $res = Install-WindowsFeature -Name $missingFeatures -WhatIf:$module.CheckMode
+ $module.Result.changed = $true
+ $module.Result.reboot_required = [bool]$res.RestartNeeded
+
+ # When in check mode and the prereq was "installed" we need to exit early as
+ # the AD cmdlets weren't really installed
+ if ($module.CheckMode) {
+ $module.ExitJson()
+ }
+}
+
+# Check that we got a valid domain_mode
+$validDomainModes = [Enum]::GetNames((Get-Command -Name Install-ADDSDomain).Parameters.DomainMode.ParameterType)
+if (($null -ne $domainMode) -and -not ($domainMode -in $validDomainModes)) {
+ $validModes = $validDomainModes -join ", "
+ $module.FailJson("The parameter 'domain_mode' does not accept '$domainMode', please use one of: $validModes")
+}
+
+$systemRole = Get-CimInstance -ClassName Win32_ComputerSystem -Property Domain, DomainRole
+if ($systemRole.DomainRole -in @(4, 5)) {
+ if ($systemRole.Domain -ne $dnsDomainName) {
+ $module.FailJson("Host is already a domain controller in another domain $($systemRole.Domain)")
+ }
+ $module.ExitJson()
+}
+
+$installParams = @{
+ Confirm = $false
+ Credential = $domainCredential
+ Force = $true
+ NoRebootOnCompletion = $true
+ SafeModeAdministratorPassword = (ConvertTo-SecureString $safeModePassword -AsPlainText -Force)
+ SkipPreChecks = $true
+ WhatIf = $module.CheckMode
+}
+
+if ($domainType -eq 'child') {
+ $newDomainName, $parentDomainName = $dnsDomainName.Split([char[]]".", 2)
+ $installParams.DomainType = 'ChildDomain'
+ $installParams.NewDomainName = $newDomainName
+ $installParams.ParentDomainName = $parentDomainName
+}
+else {
+ $installParams.DomainType = 'TreeDomain'
+ $installParams.NewDomainName = $dnsDomainName
+ $installParams.ParentDomainName = $parentDomainName
+}
+
+if ($null -ne $createDnsDelegation) {
+ $installParams.CreateDnsDelegation = $createDnsDelegation
+}
+if ($databasePath) {
+ $installParams.DatabasePath = $databasePath
+}
+if ($domainMode) {
+ $installParams.DomainMode = $domainMode
+}
+if ($null -ne $installDns) {
+ $installParams.InstallDns = $installDns
+}
+if ($logPath) {
+ $installParams.LogPath = $logPath
+}
+if ($siteName) {
+ $installParams.SiteName = $siteName
+}
+if ($sysvolPath) {
+ $installParams.SysvolPath = $sysvolPath
+}
+
+try {
+ $null = Install-ADDSDomain @installParams
+}
+catch [Microsoft.DirectoryServices.Deployment.DCPromoExecutionException] {
+ # ExitCode 15 == 'Role change is in progress or this computer needs to be restarted.'
+ # DCPromo exit codes details can be found at
+ # https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/deploy/troubleshooting-domain-controller-deployment
+ if ($_.Exception.ExitCode -in @(15, 19)) {
+ $module.Result.reboot_required = $true
+ $module.Result._do_action_reboot = $true
+ }
+
+ $module.FailJson("Failed to install ADDSDomain, DCPromo exited with $($_.Exception.ExitCode)", $_)
+}
+finally {
+ # The Netlogon service is set to auto start but is not started. This is
+ # required for Ansible to connect back to the host and reboot in a
+ # later task. Even if this fails Ansible can still connect but only
+ # with ansible_winrm_transport=basic so we just display a warning if
+ # this fails.
+ if (-not $module.CheckMode) {
+ try {
+ Start-Service -Name Netlogon
+ }
+ catch {
+ $msg = -join @(
+ "Failed to start the Netlogon service after promoting the host, "
+ "Ansible may be unable to connect until the host is manually rebooted: $($_.Exception.Message)"
+ )
+ $module.Warn($msg)
+ }
+ }
+}
+
+$module.Result.changed = $true
+$module.Result.reboot_required = $true
+
+if ($module.Result.reboot_required -and $module.Params.reboot -and -not $module.CheckMode) {
+ # Promoting or depromoting puts the server in a very funky state and it may
+ # not be possible for Ansible to connect back without a reboot is done. If
+ # the user requested the action plugin to perform the reboot then start it
+ # here and get the action plugin to continue where this left off.
+
+ $lastBootTime = (Get-CimInstance -ClassName Win32_OperatingSystem -Property LastBootUpTime).LastBootUpTime.ToFileTime()
+ $module.Result._previous_boot_time = $lastBootTime
+
+ $shutdownRegPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoLogonChecked'
+ Remove-Item -LiteralPath $shutdownRegPath -Force -ErrorAction SilentlyContinue
+
+ $comment = 'Reboot initiated by Ansible'
+ $stdout = $null
+ $stderr = . { shutdown.exe /r /t 10 /c $comment | Set-Variable stdout } 2>&1 | ForEach-Object ToString
+ if ($LASTEXITCODE -eq 1190) {
+ # A reboot was already scheduled, abort it and try again
+ shutdown.exe /a
+ $stdout = $null
+ $stderr = . { shutdown.exe /r /t 10 /c $comment | Set-Variable stdout } 2>&1 | ForEach-Object ToString
+ }
+
+ if ($LASTEXITCODE) {
+ $module.Result.rc = $LASTEXITCODE
+ $module.Result.stdout = $stdout
+ $module.Result.stderr = $stderr
+ $module.FailJson("Failed to initiate reboot, see rc, stdout, stderr for more information")
+ }
+}
+
+$module.ExitJson()
diff --git a/ansible_collections/microsoft/ad/plugins/modules/domain_child.yml b/ansible_collections/microsoft/ad/plugins/modules/domain_child.yml
new file mode 100644
index 000000000..0f3308098
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/modules/domain_child.yml
@@ -0,0 +1,184 @@
+# Copyright (c) 2024 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+DOCUMENTATION:
+ module: domain_child
+ short_description: Manage domain children in an existing Active Directory forest.
+ description:
+ - Ensure that a Windows Server host is configured as a domain controller as
+ a new domain in an existing forest.
+ - This module may require subsequent use of the
+ M(ansible.windows.win_reboot) action if changes are made.
+ - This module will only check if the domain specified by I(dns_domain_name)
+ exists or not. If the domain already exists under the same name, no other
+ options, other than the domain name will be checked during the run.
+ options:
+ create_dns_delegation:
+ description:
+ - Whether to create a DNS delegation that references the new DNS
+ server that was installed.
+ - Valid for Active Directory-integrated DNS only.
+ - The default is computed automatically based on the environment.
+ type: bool
+ database_path:
+ description:
+ - The path to a directory on a fixed disk of the Windows host where the
+ domain database will be created..
+ - If not set then the default path is C(%SYSTEMROOT%\NTDS).
+ type: path
+ dns_domain_name:
+ description:
+ - The full DNS name of the domain to create.
+ - When I(domain_type=child), the parent DNS domain name is derived
+ from this value.
+ type: str
+ domain_admin_password:
+ description:
+ - Password for the specified I(domain_admin_user).
+ type: str
+ required: true
+ domain_admin_user:
+ description:
+ - Username of a domain admin for the parent domain.
+ type: str
+ required: true
+ domain_mode:
+ description:
+ - Specifies the domain functional level of child/tree.
+ - The domain functional level cannot be lower than the forest
+ functional level, but it can be higher.
+ - The default is automatically computed and set.
+ - Current known modes are C(Win2003), C(Win2008), C(Win2008R2),
+ C(Win2012), C(Win2012R2), or C(WinThreshold).
+ type: str
+ domain_type:
+ description:
+ - Specifies the type of domain to create.
+ - Set to C(child) to create a child of an existing domain as specified
+ by I(dns_domain_name).
+ - Set to C(tree) to create a new domain tree in an existing forest as
+ specified by I(parent_domain_name). The I(dns_domain_name) must be
+ the full domain name of the new domain tree to create.
+ choices:
+ - child
+ - tree
+ default: child
+ type: str
+ install_dns:
+ description:
+ - Whether to install the DNS service when creating the domain
+ controller.
+ - If not specified then the C(-InstallDns) option is not supplied to
+ the C(Install-ADDSDomain) command, see
+ L(Install-ADDSDomain,https://learn.microsoft.com/en-us/powershell/module/addsdeployment/install-addsdomain#-installdns)
+ for more information.
+ type: bool
+ log_path:
+ description:
+ - Specified the fully qualified, non-UNC path to a directory on a fixed
+ disk of the local computer that will contain the domain log files.
+ type: path
+ parent_domain_name:
+ description:
+ - The fully qualified domain name of an existing parent domain to
+ create a new domain tree in.
+ - This can only be set when I(domain_type=tree).
+ type: str
+ reboot:
+ description:
+ - If C(true), this will reboot the host if a reboot was create the
+ domain.
+ - If C(false), this will not reboot the host if a reboot was required
+ and instead sets the I(reboot_required) return value to C(true).
+ - Multiple reboots may occur if the host required a reboot before the
+ domain promotion.
+ - This cannot be used with async mode.
+ type: bool
+ default: false
+ safe_mode_password:
+ description:
+ - Safe mode password for the domain controller.
+ required: true
+ type: str
+ site_name:
+ description:
+ - Specifies the name of an existing site where you can place the new
+ domain controller.
+ type: str
+ sysvol_path:
+ description:
+ - The path to a directory on a fixed disk of the Windows host where the
+ Sysvol folder will be created.
+ - If not set then the default path is C(%SYSTEMROOT%\SYSVOL).
+ type: path
+ notes:
+ - It is highly recommended to set I(reboot=true) to have Ansible manage the
+ host reboot phase as the actions done by this module puts the host in a
+ state where it may not be possible for Ansible to reconnect in a
+ subsequent task without a reboot.
+ - This module must be run on a Windows target host.
+ extends_documentation_fragment:
+ - ansible.builtin.action_common_attributes
+ - ansible.builtin.action_common_attributes.flow
+ attributes:
+ check_mode:
+ support: full
+ diff_mode:
+ support: none
+ platform:
+ platforms:
+ - windows
+ action:
+ support: full
+ async:
+ support: partial
+ details: Supported for all scenarios except with I(reboot=True).
+ bypass_host_loop:
+ support: none
+ seealso:
+ - module: microsoft.ad.domain
+ - module: microsoft.ad.domain_controller
+ author:
+ - Jordan Borean (@jborean93)
+
+EXAMPLES: |
+ - name: Create a child domain foo.example.com with parent example.com
+ microsoft.ad.domain_child:
+ dns_domain_name: foo.example.com
+ domain_admin_user: testguy@example.com
+ domain_admin_password: password123!
+ safe_mode_password: password123!
+ reboot: true
+
+ - name: Create a domain tree foo.example.com with parent bar.example.com
+ microsoft.ad.domain_child:
+ dns_domain_name: foo.example.com
+ parent_domain_name: bar.example.com
+ domain_type: tree
+ domain_admin_user: testguy@bar.example.com
+ domain_admin_password: password123!
+ local_admin_password: password123!
+ reboot: true
+
+ # This scenario is not recommended, use reboot: true when possible
+ - name: Promote server with custom paths with manual reboot task
+ microsoft.ad.domain_child:
+ dns_domain_name: foo.ansible.vagrant
+ domain_admin_user: testguy@ansible.vagrant
+ domain_admin_password: password123!
+ safe_mode_password: password123!
+ sysvol_path: D:\SYSVOL
+ database_path: D:\NTDS
+ log_path: D:\NTDS
+ register: dc_promotion
+
+ - name: Reboot after promotion
+ microsoft.ad.win_reboot:
+ when: dc_promotion.reboot_required
+
+RETURNS:
+ reboot_required:
+ description: True if changes were made that require a reboot.
+ returned: always
+ type: bool
+ sample: true
diff --git a/ansible_collections/microsoft/ad/plugins/modules/domain_controller.py b/ansible_collections/microsoft/ad/plugins/modules/domain_controller.py
index df4641741..69971243b 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/domain_controller.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/domain_controller.py
@@ -114,6 +114,7 @@ attributes:
seealso:
- module: microsoft.ad.computer
- module: microsoft.ad.domain
+- module: microsoft.ad.domain_child
- module: microsoft.ad.group
- module: microsoft.ad.membership
- module: microsoft.ad.user
@@ -150,7 +151,7 @@ EXAMPLES = r"""
domain_admin_password: password123!
safe_mode_password: password123!
state: domain_controller
- read_only: yes
+ read_only: true
site_name: London
reboot: true
@@ -168,7 +169,7 @@ EXAMPLES = r"""
register: dc_promotion
- name: Reboot after promotion
- microsoft.ad.win_reboot:
+ ansible.windows.win_reboot:
when: dc_promotion.reboot_required
"""
diff --git a/ansible_collections/microsoft/ad/plugins/modules/group.ps1 b/ansible_collections/microsoft/ad/plugins/modules/group.ps1
index bbb3aa8d7..ed4a52164 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/group.ps1
+++ b/ansible_collections/microsoft/ad/plugins/modules/group.ps1
@@ -26,141 +26,14 @@ $setParams = @{
Name = 'managed_by'
Option = @{ type = 'str' }
Attribute = 'ManagedBy'
+ DNLookup = $true
}
[PSCustomObject]@{
Name = 'members'
- Option = @{
- type = 'dict'
- options = @{
- add = @{
- type = 'list'
- elements = 'str'
- }
- remove = @{
- type = 'list'
- elements = 'str'
- }
- set = @{
- type = 'list'
- elements = 'str'
- }
- }
- }
+ Option = @{ type = 'add_remove_set' }
Attribute = 'member'
- New = {
- param($Module, $ADParams, $NewParams)
-
- $newMembers = @(
- foreach ($actionKvp in $Module.Params.members.GetEnumerator()) {
- if ($null -eq $actionKvp.Value -or $actionKvp.Key -eq 'remove') { continue }
-
- $invalidMembers = [System.Collections.Generic.List[string]]@()
-
- foreach ($m in $actionKvp.Value) {
- $obj = Get-AnsibleADObject -Identity $m @ADParams |
- Select-Object -ExpandProperty DistinguishedName
- if ($obj) {
- $obj
- }
- else {
- $invalidMembers.Add($m)
- }
- }
-
- if ($invalidMembers) {
- $module.FailJson("Failed to find the following ad objects for group members: '$($invalidMembers -join "', '")'")
- }
- }
- )
-
- if ($newMembers) {
- if (-not $NewParams.ContainsKey('OtherAttributes')) {
- $NewParams.OtherAttributes = @{}
- }
- # The AD cmdlets don't like explicitly casted arrays, use
- # ForEach-Object to get back a vanilla object[] to set.
- $NewParams.OtherAttributes.member = $newMembers | ForEach-Object { "$_" }
- }
- $Module.Diff.after.members = @($newMembers | Sort-Object)
- }
- Set = {
- param($Module, $ADParams, $SetParams, $ADObject)
-
- [string[]]$existingMembers = $ADObject.member
-
- $desiredState = @{}
- foreach ($actionKvp in $Module.Params.members.GetEnumerator()) {
- if ($null -eq $actionKvp.Value) { continue }
-
- $invalidMembers = [System.Collections.Generic.List[string]]@()
-
- $dns = foreach ($m in $actionKvp.Value) {
- $obj = Get-AnsibleADObject -Identity $m @ADParams |
- Select-Object -ExpandProperty DistinguishedName
- if ($obj) {
- $obj
- }
- else {
- $invalidMembers.Add($m)
- }
- }
-
- if ($invalidMembers) {
- $module.FailJson("Failed to find the following ad objects for group members: '$($invalidMembers -join "', '")'")
- }
-
- $desiredState[$actionKvp.Key] = @($dns)
- }
-
- $ignoreCase = [System.StringComparer]::OrdinalIgnoreCase
- [string[]]$diffAfter = @()
- if ($desiredState.ContainsKey('set')) {
- [string[]]$desiredMembers = $desiredState.set
- $diffAfter = $desiredMembers
-
- $toAdd = [string[]][System.Linq.Enumerable]::Except($desiredMembers, $existingMembers, $ignoreCase)
- $toRemove = [string[]][System.Linq.Enumerable]::Except($existingMembers, $desiredMembers, $ignoreCase)
-
- if ($toAdd -or $toRemove) {
- if (-not $SetParams.ContainsKey('Replace')) {
- $SetParams.Replace = @{}
- }
- $SetParams.Replace.member = $desiredMembers
- }
- }
- else {
- [string[]]$toAdd = @()
- [string[]]$toRemove = @()
- $diffAfter = $existingMembers
-
- if ($desiredState.ContainsKey('add') -and $desiredState.add) {
- [string[]]$desiredMembers = $desiredState.add
- $toAdd = [string[]][System.Linq.Enumerable]::Except($desiredMembers, $existingMembers, $ignoreCase)
- $diffAfter = [System.Linq.Enumerable]::Union($desiredMembers, $diffAfter, $ignoreCase)
- }
- if ($desiredState.ContainsKey('remove') -and $desiredState.remove) {
-
- [string[]]$desiredMembers = $desiredState.remove
- $toRemove = [string[]][System.Linq.Enumerable]::Intersect($desiredMembers, $existingMembers, $ignoreCase)
- $diffAfter = [System.Linq.Enumerable]::Except($diffAfter, $desiredMembers, $ignoreCase)
- }
-
- if ($toAdd) {
- if (-not $SetParams.ContainsKey('Add')) {
- $SetParams.Add = @{}
- }
- $SetParams.Add.member = $toAdd
- }
- if ($toRemove) {
- if (-not $SetParams.ContainsKey('Remove')) {
- $SetParams.Remove = @{}
- }
- $SetParams.Remove.member = $toRemove
- }
- }
-
- $Module.Diff.after.members = ($diffAfter | Sort-Object)
- }
+ DNLookup = $true
+ IsRawAttribute = $true
}
[PSCustomObject]@{
Name = 'sam_account_name'
diff --git a/ansible_collections/microsoft/ad/plugins/modules/group.py b/ansible_collections/microsoft/ad/plugins/modules/group.py
index 9fb28e819..df2c70440 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/group.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/group.py
@@ -32,19 +32,29 @@ options:
description:
- The user or group that manages the group.
- The value can be in the form of a C(distinguishedName), C(objectGUID),
- C(objectSid), or C(sAMAccountName).
+ C(objectSid), C(sAMAccountName), or C(userPrincipalName) string or a
+ dictionary with the I(name) and optional I(server) key.
- This is the value set on the C(managedBy) LDAP attribute.
- type: str
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information on how DN lookups work.
+ type: raw
members:
description:
- The members of the group to set.
- The value is a dictionary that contains 3 keys, I(add), I(remove), and
I(set).
- - Each subkey is set to a list of AD principal objects to add, remove or
- set as the members of this AD group respectively. A principal can be in
- the form of a C(distinguishedName), C(objectGUID), C(objectSid), or
- C(sAMAccountName).
- - The module will fail if it cannot find any of the members referenced.
+ - Each subkey value is a list of values in the form of a
+ C(distinguishedName), C(objectGUID), C(objectSid), C(sAMAccountName),
+ or C(userPrincipalName) string or a dictionary with the I(name) and
+ optional I(server) key.
+ - The value for each subkey can either be specified as a string or a
+ dictionary with the I(name) and optional I(server) key. The I(name) is
+ the identity to lookup and I(server) is an optional key to override what
+ AD server to lookup the identity on.
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information.
type: dict
suboptions:
add:
@@ -52,13 +62,22 @@ options:
- Adds the principals specified as members of the group, keeping the
existing membership if they are not specified.
type: list
- elements: str
+ elements: raw
+ lookup_failure_action:
+ description:
+ - Control the action to take when the lookup fails to find the DN.
+ - C(fail) will cause the task to fail.
+ - C(ignore) will ignore the value and continue.
+ - C(warn) will ignore the value and display a warning.
+ choices: ['fail', 'ignore', 'warn']
+ default: fail
+ type: str
remove:
description:
- Removes the principals specified as members of the group, keeping the
existing membership if they are not specified.
type: list
- elements: str
+ elements: raw
set:
description:
- Sets only the principals specified as members of the group.
@@ -66,7 +85,7 @@ options:
if not specified in this list.
- Set this to an empty list to remove all members from a group.
type: list
- elements: str
+ elements: raw
sam_account_name:
description:
- The C(sAMAccountName) value to set for the group.
@@ -179,8 +198,8 @@ EXAMPLES = r"""
scope: domainlocal
members:
add:
- - Domain Admins
- - Domain Users
+ - Domain Admins
+ - Domain Users
- name: Remove members from the group, preserving existing membership
microsoft.ad.group:
@@ -188,8 +207,8 @@ EXAMPLES = r"""
scope: domainlocal
members:
remove:
- - Domain Admins
- - Domain Users
+ - Domain Admins
+ - Domain Users
- name: Replace entire membership of group
microsoft.ad.group:
@@ -197,8 +216,14 @@ EXAMPLES = r"""
scope: domainlocal
members:
set:
- - Domain Admins
- - Domain Users
+ - Domain Admins
+ - Domain Users
+ - name: UserInOtherDomain
+ server: OtherDomain
+ domain_credentials:
+ - name: OtherDomain
+ username: OtherDomainUser
+ password: '{{ other_domain_password }}'
"""
RETURN = r"""
diff --git a/ansible_collections/microsoft/ad/plugins/modules/membership.ps1 b/ansible_collections/microsoft/ad/plugins/modules/membership.ps1
index d2be34e9f..963733a97 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/membership.ps1
+++ b/ansible_collections/microsoft/ad/plugins/modules/membership.ps1
@@ -143,7 +143,7 @@ Function Get-CurrentState {
}
[PSCustomObject]@{
- HostName = $env:COMPUTERNAME
+ HostName = [System.Net.Dns]::GetHostName()
PartOfDomain = $cs.PartOfDomain
DnsDomainName = $domainName
WorkgroupName = $cs.Workgroup
diff --git a/ansible_collections/microsoft/ad/plugins/modules/object.py b/ansible_collections/microsoft/ad/plugins/modules/object.py
index c6396619a..6b305afa2 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/object.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/object.py
@@ -128,8 +128,8 @@ EXAMPLES = r"""
attributes:
add:
extensionName:
- - value 1
- - value 2
+ - value 1
+ - value 2
type: container
state: present
@@ -139,8 +139,8 @@ EXAMPLES = r"""
attributes:
remove:
extensionName:
- - value 1
- - value 3
+ - value 1
+ - value 3
type: container
state: present
"""
diff --git a/ansible_collections/microsoft/ad/plugins/modules/object_info.py b/ansible_collections/microsoft/ad/plugins/modules/object_info.py
index 0cdcf06a7..88460979b 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/object_info.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/object_info.py
@@ -130,13 +130,13 @@ EXAMPLES = r"""
microsoft.ad.object_info:
filter: ObjectClass -eq 'user' -and objectCategory -eq 'Person'
properties:
- - objectSid
+ - objectSid
- name: Get the SID for all user accounts as a LDAP filter
microsoft.ad.object_info:
ldap_filter: (&(objectClass=user)(objectCategory=Person))
properties:
- - objectSid
+ - objectSid
- name: Search all computer accounts in a specific path that were added after February 1st
microsoft.ad.object_info:
diff --git a/ansible_collections/microsoft/ad/plugins/modules/ou.ps1 b/ansible_collections/microsoft/ad/plugins/modules/ou.ps1
index 6af68b5ae..909b13cd9 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/ou.ps1
+++ b/ansible_collections/microsoft/ad/plugins/modules/ou.ps1
@@ -22,6 +22,7 @@ $setParams = @{
Name = 'managed_by'
Option = @{ type = 'str' }
Attribute = 'ManagedBy'
+ DNLookup = $true
}
[PSCustomObject]@{
Name = 'postal_code'
diff --git a/ansible_collections/microsoft/ad/plugins/modules/ou.py b/ansible_collections/microsoft/ad/plugins/modules/ou.py
index 5d1d60503..1e31cc890 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/ou.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/ou.py
@@ -26,9 +26,13 @@ options:
description:
- The user or group that manages the object.
- The value can be in the form of a C(distinguishedName), C(objectGUID),
- C(objectSid), or sAMAccountName).
+ C(objectSid), C(sAMAccountName), or C(userPrincipalName) string or a
+ dictionary with the I(name) and optional I(server) key.
- This is the value set on the C(managedBy) LDAP attribute.
- type: str
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information on how DN lookups work.
+ type: raw
postal_code:
description:
- Configures the user's postal code / zip code.
@@ -116,6 +120,13 @@ EXAMPLES = r"""
attributes:
set:
comment: A comment for the OU
+
+- name: Set managedBy using an identity from another DC
+ microsoft.ad.ou:
+ name: MyOU
+ managed_by:
+ name: manager-user
+ server: OtherDC
"""
RETURN = r"""
diff --git a/ansible_collections/microsoft/ad/plugins/modules/user.ps1 b/ansible_collections/microsoft/ad/plugins/modules/user.ps1
index 267c77627..8eef49635 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/user.ps1
+++ b/ansible_collections/microsoft/ad/plugins/modules/user.ps1
@@ -66,6 +66,9 @@ $setParams = @{
type = 'bool'
}
Attribute = 'LockedOut'
+ # We cannot lock a user and creating a user that is unlocked
+ # requires no action.
+ New = {}
Set = {
param($Module, $ADParams, $SetParams, $ADObject)
@@ -100,15 +103,10 @@ $setParams = @{
Name = 'delegates'
Option = @{
aliases = 'principals_allowed_to_delegate'
- type = 'dict'
- options = @{
- add = @{ type = 'list'; elements = 'str' }
- remove = @{ type = 'list'; elements = 'str' }
- set = @{ type = 'list'; elements = 'str' }
- }
+ type = 'add_remove_set'
}
Attribute = 'PrincipalsAllowedToDelegateToAccount'
- CaseInsensitive = $true
+ DNLookup = $true
}
[PSCustomObject]@{
@@ -134,10 +132,11 @@ $setParams = @{
Option = @{
type = 'dict'
options = @{
- add = @{ type = 'list'; elements = 'str' }
- remove = @{ type = 'list'; elements = 'str' }
- set = @{ type = 'list'; elements = 'str' }
- missing_behaviour = @{
+ add = @{ type = 'list'; elements = 'raw' }
+ remove = @{ type = 'list'; elements = 'raw' }
+ set = @{ type = 'list'; elements = 'raw' }
+ lookup_failure_action = @{
+ aliases = @('missing_behaviour')
choices = 'fail', 'ignore', 'warn'
default = 'fail'
type = 'str'
@@ -367,27 +366,19 @@ $setParams = @{
return
}
- $groupMissingBehaviour = $Module.Params.groups.missing_behaviour
- $lookupGroup = {
- try {
- (Get-ADGroup -Identity $args[0] @ADParams).DistinguishedName
- }
- catch {
- if ($groupMissingBehaviour -eq "fail") {
- $module.FailJson("Failed to locate group $($args[0]): $($_.Exception.Message)", $_)
- }
- elseif ($groupMissingBehaviour -eq "warn") {
- $module.Warn("Failed to locate group $($args[0]) but continuing on: $($_.Exception.Message)")
- }
- }
- }
-
[string[]]$existingGroups = @(
# In check mode the ADObject won't be given
if ($ADObject) {
try {
- Get-ADPrincipalGroupMembership -Identity $ADObject.ObjectGUID @ADParams -ErrorAction Stop |
- Select-Object -ExpandProperty DistinguishedName
+ # Get-ADPrincipalGroupMembership doesn't work well with
+ # cross domain membership. It also gets the primary group
+ # so this code reflects that using Get-ADUser instead.
+ $userMembership = Get-ADUser -Identity $ADObject.ObjectGUID @ADParams -Properties @(
+ 'MemberOf',
+ 'PrimaryGroup'
+ ) -ErrorAction Stop
+ $userMembership.memberOf
+ $userMembership.PrimaryGroup
}
catch {
$module.Warn("Failed to enumerate user groups but continuing on: $($_.Exception.Message)")
@@ -403,14 +394,42 @@ $setParams = @{
CaseInsensitive = $true
Existing = $existingGroups
}
- 'add', 'remove', 'set' | ForEach-Object -Process {
- if ($null -ne $Module.Params.groups[$_]) {
- $compareParams[$_] = @(
- foreach ($group in $Module.Params.groups[$_]) {
- & $lookupGroup $group
+ $dnServerParams = @{}
+ foreach ($actionKvp in $Module.Params.groups.GetEnumerator()) {
+ if ($null -eq $actionKvp.Value -or $actionKvp.Key -in @('lookup_failure_action', 'missing_behaviour')) {
+ continue
+ }
+
+ $convertParams = @{
+ Module = $Module
+ Context = "groups.$($actionKvp.Key)"
+ FailureAction = $Module.Params.groups.lookup_failure_action
+ }
+ $dns = foreach ($lookupId in $actionKvp.Value) {
+ $dn = $lookupId | ConvertTo-AnsibleADDistinguishedName @ADParams @convertParams
+ if (-not $dn) {
+ continue # Warning was written
+ }
+
+ # As membership is done on the group server, we need to store
+ # correct server and credentials that was used for the lookup.
+ if ($lookupId -is [System.Collections.IDictionary] -and $lookupId.server) {
+ $dnServerParams[$dn] = @{
+ Server = $lookupId.server
+ }
+
+ if ($Module.ServerCredentials.ContainsKey($lookupId.server)) {
+ $dnServerParams[$dn].Credential = $Module.ServerCredentials[$lookupId.server]
}
- )
+ }
+ else {
+ $dnServerParams[$dn] = $ADParams
+ }
+
+ $dn
}
+
+ $compareParams[$actionKvp.Key] = @($dns)
}
$res = Compare-AnsibleADIdempotentList @compareParams
@@ -422,15 +441,32 @@ $setParams = @{
WhatIf = $Module.CheckMode
}
foreach ($member in $res.ToAdd) {
+ $lookupParams = if ($dnServerParams.ContainsKey($member)) {
+ $dnServerParams[$member]
+ }
+ else {
+ $ADParams
+ }
if ($ADObject) {
- Add-ADGroupMember -Identity $member -Members $ADObject.ObjectGUID @ADParams @commonParams
+ Set-ADObject -Identity $member -Add @{
+ member = $ADObject.DistinguishedName
+ } @lookupParams @commonParams
+
}
$Module.Result.changed = $true
}
foreach ($member in $res.ToRemove) {
+ $lookupParams = if ($dnServerParams.ContainsKey($member)) {
+ $dnServerParams[$member]
+ }
+ else {
+ $ADParams
+ }
if ($ADObject) {
try {
- Remove-ADGroupMember -Identity $member -Members $ADObject.ObjectGUID @ADParams @commonParams
+ Set-ADObject -Identity $member -Remove @{
+ member = $ADObject.DistinguishedName
+ } @lookupParams @commonParams
}
catch [Microsoft.ActiveDirectory.Management.ADException] {
if ($_.Exception.ErrorCode -eq 0x0000055E) {
diff --git a/ansible_collections/microsoft/ad/plugins/modules/user.py b/ansible_collections/microsoft/ad/plugins/modules/user.py
index a3e7d1ecb..81a48b41d 100644
--- a/ansible_collections/microsoft/ad/plugins/modules/user.py
+++ b/ansible_collections/microsoft/ad/plugins/modules/user.py
@@ -40,14 +40,19 @@ options:
description:
- The principal objects that the current AD object can trust for
delegation to either add, remove or set.
- - The values for each sub option must be specified as a distinguished name
- C(CN=shenetworks,CN=Users,DC=ansible,DC=test)
+ - Each subkey value is a list of values in the form of a
+ C(distinguishedName), C(objectGUID), C(objectSid), C(sAMAccountName),
+ or C(userPrincipalName) string or a dictionary with the I(name) and
+ optional I(server) key.
- This is the value set on the C(msDS-AllowedToActOnBehalfOfOtherIdentity)
LDAP attribute.
- This is a highly sensitive attribute as it allows the principals
specified to impersonate any account when authenticating with the AD
computer object being managed.
- To clear all principals, use I(set) with an empty list.
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information on how DN lookups work.
- See R(Setting list option values,ansible_collections.microsoft.ad.docsite.guide_list_values)
for more information on how to add/remove/set list options.
aliases:
@@ -56,29 +61,36 @@ options:
suboptions:
add:
description:
- - The AD objects by their C(DistinguishedName) to add as a principal
- allowed to delegate.
+ - Adds the principals specified as principals allowed to delegate to.
- Any existing principals not specified by I(add) will be untouched
unless specified by I(remove) or not in I(set).
type: list
- elements: str
+ elements: raw
+ lookup_failure_action:
+ description:
+ - Control the action to take when the lookup fails to find the DN.
+ - C(fail) will cause the task to fail.
+ - C(ignore) will ignore the value and continue.
+ - C(warn) will ignore the value and display a warning.
+ choices: ['fail', 'ignore', 'warn']
+ default: fail
+ type: str
remove:
description:
- - The AD objects by their C(DistinguishedName) to remove as a principal
- allowed to delegate.
+ - Removes the principals specified as principals allowed to delegate to.
- Any existing principals not specified by I(remove) will be untouched
unless I(set) is defined.
type: list
- elements: str
+ elements: raw
set:
description:
- - The AD objects by their C(DistinguishedName) to set as the only
+ - Sets the principals specified as principals allowed to delegate to.
principals allowed to delegate.
- This will remove any existing principals if not specified in this
list.
- Specify an empty list to remove all principals allowed to delegate.
type: list
- elements: str
+ elements: raw
email:
description:
- Configures the user's email address.
@@ -104,10 +116,20 @@ options:
- To clear all group memberships, use I(set) with an empty list.
- Note that users cannot be removed from their principal group (for
example, "Domain Users"). Attempting to do so will display a warning.
+ - Adding and removing a user from a group is done on the group AD object.
+ If the group is an object in a different domain, then it may require
+ explicit I(server) and I(domain_credentials) for it to work.
- Each subkey is set to a list of groups objects to add, remove or
set as the membership of this AD user respectively. A group can be in
the form of a C(distinguishedName), C(objectGUID), C(objectSid), or
C(sAMAccountName).
+ - Each subkey value is a list of group objects in the form of a
+ C(distinguishedName), C(objectGUID), C(objectSid), C(sAMAccountName),
+ or C(userPrincipalName) string or a dictionary with the I(name) and
+ optional I(server) key.
+ - See
+ R(DN Lookup Attributes,ansible_collections.microsoft.ad.docsite.guide_attributes.dn_lookup_attributes)
+ for more information on how DN lookups work.
- See R(Setting list option values,ansible_collections.microsoft.ad.docsite.guide_list_values)
for more information on how to add/remove/set list options.
type: dict
@@ -116,20 +138,20 @@ options:
description:
- The groups to add the user to.
type: list
- elements: str
+ elements: raw
remove:
description:
- The groups to remove the user from.
type: list
- elements: str
+ elements: raw
set:
description:
- The only groups the user is a member of.
- This will clear out any existing groups if not in the specified list.
- Set to an empty list to clear all group membership of the user.
type: list
- elements: str
- missing_behaviour:
+ elements: raw
+ lookup_failure_action:
description:
- Controls what happens when a group specified by C(groups) is an
invalid group name.
@@ -138,6 +160,8 @@ options:
- C(ignore) will ignore any groups that does not exist.
- C(warn) will display a warning for any groups that do not exist but
will continue without failing.
+ aliases:
+ - missing_behaviour
choices:
- fail
- ignore
@@ -287,7 +311,7 @@ EXAMPLES = r"""
state: present
groups:
set:
- - Domain Admins
+ - Domain Admins
street: 123 4th St.
city: Sometown
state_province: IN
@@ -316,8 +340,8 @@ EXAMPLES = r"""
path: ou=test,dc=domain,dc=local
groups:
set:
- - Domain Admins
- - Domain Users
+ - Domain Admins
+ - Domain Users
- name: Ensure user bob is absent
microsoft.ad.user:
@@ -329,15 +353,15 @@ EXAMPLES = r"""
identity: liz.kenyon
spn:
set:
- - MSSQLSvc/us99db-svr95:1433
- - MSSQLSvc/us99db-svr95.vmware.com:1433
+ - MSSQLSvc/us99db-svr95:1433
+ - MSSQLSvc/us99db-svr95.vmware.com:1433
- name: Ensure user has spn added
microsoft.ad.user:
identity: liz.kenyon
spn:
add:
- - MSSQLSvc/us99db-svr95:2433
+ - MSSQLSvc/us99db-svr95:2433
- name: Ensure user is created with delegates and spn's defined
microsoft.ad.user:
@@ -346,17 +370,17 @@ EXAMPLES = r"""
state: present
groups:
set:
- - Domain Admins
- - Domain Users
- - Enterprise Admins
+ - Domain Admins
+ - Domain Users
+ - Enterprise Admins
delegates:
set:
- - CN=shenetworks,CN=Users,DC=ansible,DC=test
- - CN=mk.ai,CN=Users,DC=ansible,DC=test
- - CN=jessiedotjs,CN=Users,DC=ansible,DC=test
+ - CN=shenetworks,CN=Users,DC=ansible,DC=test
+ - CN=mk.ai,CN=Users,DC=ansible,DC=test
+ - CN=jessiedotjs,CN=Users,DC=ansible,DC=test
spn:
set:
- - MSSQLSvc/us99db-svr95:2433
+ - MSSQLSvc/us99db-svr95:2433
# The name option is the name of the AD object as seen in dsa.msc and not the
# sAMAccountName. For example, this will change the sAMAccountName of the user