win_domain_user: added ability to explicitly set credentials and user when interacting with AD (#34562)

This commit is contained in:
Jordan Borean 2018-01-08 09:38:13 +10:00 committed by GitHub
parent e545127c2e
commit 71ff77e51f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 83 deletions

View file

@ -25,7 +25,7 @@ $organizational_unit = Get-AnsibleParam -obj $params -name "organizational_unit"
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent" $state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent"
$protect = Get-AnsibleParam -obj $params -name "protect" -type "bool" $protect = Get-AnsibleParam -obj $params -name "protect" -type "bool"
$ignore_protection = Get-AnsibleParam -obj $params -name "ignore_protection" -type "bool" -default $false $ignore_protection = Get-AnsibleParam -obj $params -name "ignore_protection" -type "bool" -default $false
$server = Get-AnsibleParam -obj $params -name "server" -type "str" $domain_server = Get-AnsibleParam -obj $params -name "domain_server" -type "str"
$result = @{ $result = @{
changed = $false changed = $false
@ -46,8 +46,8 @@ if ($domain_username -ne $null) {
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password
$extra_args.Credential = $credential $extra_args.Credential = $credential
} }
if ($server -ne $null) { if ($domain_server -ne $null) {
$extra_args.Server = $server $extra_args.Server = $domain_server
} }
try { try {

View file

@ -45,6 +45,13 @@ options:
domain_password: domain_password:
description: description:
- The password for C(username). - The password for C(username).
domain_server:
description:
- Specifies the Active Directory Domain Services instance to connect to.
- Can be in the form of an FQDN or NetBIOS name.
- If not specified then the value is based on the domain of the computer
running PowerShell.
version_added: '2.5'
ignore_protection: ignore_protection:
description: description:
- Will ignore the C(ProtectedFromAccidentalDeletion) flag when deleting or - Will ignore the C(ProtectedFromAccidentalDeletion) flag when deleting or
@ -89,13 +96,6 @@ options:
- If C(state=absent) this module will delete the group if it exists - If C(state=absent) this module will delete the group if it exists
default: present default: present
choices: [ absent, present ] choices: [ absent, present ]
server:
description:
- Specifies the Active Directory Domain Services instance to connect to.
- Can be in the form of an FQDN or NetBIOS name.
- If not specified then the value is based on the domain of the computer
running PowerShell.
version_added: '2.5'
notes: notes:
- This must be run on a host that has the ActiveDirectory powershell module - This must be run on a host that has the ActiveDirectory powershell module
installed. installed.
@ -146,10 +146,10 @@ EXAMPLES = r'''
- name: add group and specify the AD domain services to use for the create - name: add group and specify the AD domain services to use for the create
win_domain_group: win_domain_group:
name: Test Group name: Test Group
domain_admin_user: user@CORP.ANSIBLE.COM domain_username: user@CORP.ANSIBLE.COM
domain_admin_password: Password01! domain_password: Password01!
domain_server: corp-DC12.corp.ansible.com
scope: domainlocal scope: domainlocal
server: corp-DC12.corp.ansible.com
''' '''
RETURN = r''' RETURN = r'''

View file

@ -1,23 +1,10 @@
#!powershell #!powershell
# This file is part of Ansible # This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# WANT_JSON # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# POWERSHELL_COMMON
#Requires -Module Ansible.ModuleUtils.Legacy
########
try { try {
Import-Module ActiveDirectory Import-Module ActiveDirectory
} }
@ -30,6 +17,8 @@ $result = @{
password_updated = $false password_updated = $false
} }
$ErrorActionPreference = "Stop"
$params = Parse-Args $args -supports_check_mode $true $params = Parse-Args $args -supports_check_mode $true
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default $false $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default $false
@ -37,6 +26,9 @@ $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent","query" $state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent","query"
$update_password = Get-AnsibleParam -obj $params -name "update_password" -type "str" -default "always" -validateset "always","on_create" $update_password = Get-AnsibleParam -obj $params -name "update_password" -type "str" -default "always" -validateset "always","on_create"
$groups_action = Get-AnsibleParam -obj $params -name "groups_action" -type "str" -default "replace" -validateset "add","remove","replace" $groups_action = Get-AnsibleParam -obj $params -name "groups_action" -type "str" -default "replace" -validateset "add","remove","replace"
$domain_username = Get-AnsibleParam -obj $params -name "domain_username" -type "str"
$domain_password = Get-AnsibleParam -obj $params -name "domain_password" -type "str" -failifempty ($domain_username -ne $null)
$domain_server = Get-AnsibleParam -obj $params -name "domain_server" -type "str"
# User account parameters # User account parameters
$username = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true $username = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
@ -75,8 +67,18 @@ If (($password_expired -ne $null) -and ($password_never_expires -ne $null)) {
Fail-Json $result "password_expired and password_never_expires are mutually exclusive but have both been set" Fail-Json $result "password_expired and password_never_expires are mutually exclusive but have both been set"
} }
$extra_args = @{}
if ($domain_username -ne $null) {
$domain_password = ConvertTo-SecureString $domain_password -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password
$extra_args.Credential = $credential
}
if ($domain_server -ne $null) {
$extra_args.Server = $domain_server
}
try { try {
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
} }
catch { catch {
$user_obj = $null $user_obj = $null
@ -90,64 +92,64 @@ If ($state -eq 'present') {
# If the account does not exist, create it # If the account does not exist, create it
If (-not $user_obj) { If (-not $user_obj) {
If ($path -ne $null){ If ($path -ne $null){
New-ADUser -Name $username -Path $path -WhatIf:$check_mode New-ADUser -Name $username -Path $path -WhatIf:$check_mode @extra_args
} }
Else { Else {
New-ADUser -Name $username -WhatIf:$check_mode New-ADUser -Name $username -WhatIf:$check_mode @extra_args
} }
$new_user = $true $new_user = $true
$result.changed = $true $result.changed = $true
If ($check_mode) { If ($check_mode) {
Exit-Json $result Exit-Json $result
} }
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
} }
# Set the password if required # Set the password if required
If ($password -and (($new_user -and $update_password -eq "on_create") -or $update_password -eq "always")) { If ($password -and (($new_user -and $update_password -eq "on_create") -or $update_password -eq "always")) {
$secure_password = ConvertTo-SecureString $password -AsPlainText -Force $secure_password = ConvertTo-SecureString $password -AsPlainText -Force
Set-ADAccountPassword -Identity $username -Reset:$true -Confirm:$false -NewPassword $secure_password -WhatIf:$check_mode Set-ADAccountPassword -Identity $username -Reset:$true -Confirm:$false -NewPassword $secure_password -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.password_updated = $true $result.password_updated = $true
$result.changed = $true $result.changed = $true
} }
# Configure password policies # Configure password policies
If (($password_never_expires -ne $null) -and ($password_never_expires -ne $user_obj.PasswordNeverExpires)) { If (($password_never_expires -ne $null) -and ($password_never_expires -ne $user_obj.PasswordNeverExpires)) {
Set-ADUser -Identity $username -PasswordNeverExpires $password_never_expires -WhatIf:$check_mode Set-ADUser -Identity $username -PasswordNeverExpires $password_never_expires -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
If (($password_expired -ne $null) -and ($password_expired -ne $user_obj.PasswordExpired)) { If (($password_expired -ne $null) -and ($password_expired -ne $user_obj.PasswordExpired)) {
Set-ADUser -Identity $username -ChangePasswordAtLogon $password_expired -WhatIf:$check_mode Set-ADUser -Identity $username -ChangePasswordAtLogon $password_expired -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
If (($user_cannot_change_password -ne $null) -and ($user_cannot_change_password -ne $user_obj.CannotChangePassword)) { If (($user_cannot_change_password -ne $null) -and ($user_cannot_change_password -ne $user_obj.CannotChangePassword)) {
Set-ADUser -Identity $username -CannotChangePassword $user_cannot_change_password -WhatIf:$check_mode Set-ADUser -Identity $username -CannotChangePassword $user_cannot_change_password -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
# Assign other account settings # Assign other account settings
If (($upn -ne $null) -and ($upn -ne $user_obj.UserPrincipalName)) { If (($upn -ne $null) -and ($upn -ne $user_obj.UserPrincipalName)) {
Set-ADUser -Identity $username -UserPrincipalName $upn -WhatIf:$check_mode Set-ADUser -Identity $username -UserPrincipalName $upn -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
If (($description -ne $null) -and ($description -ne $user_obj.Description)) { If (($description -ne $null) -and ($description -ne $user_obj.Description)) {
Set-ADUser -Identity $username -description $description -WhatIf:$check_mode Set-ADUser -Identity $username -description $description -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
If ($enabled -ne $user_obj.Enabled) { If ($enabled -ne $user_obj.Enabled) {
Set-ADUser -Identity $username -Enabled $enabled -WhatIf:$check_mode Set-ADUser -Identity $username -Enabled $enabled -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
If ((-not $account_locked) -and ($user_obj.LockedOut -eq $true)) { If ((-not $account_locked) -and ($user_obj.LockedOut -eq $true)) {
Unlock-ADAccount -Identity $username -WhatIf:$check_mode Unlock-ADAccount -Identity $username -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
@ -158,17 +160,16 @@ If ($state -eq 'present') {
} }
$value = $user_info[$key] $value = $user_info[$key]
If ($value -ne $user_obj.$key) { If ($value -ne $user_obj.$key) {
$expression = "Set-ADUser -Identity $username -$key '$value'" $set_args = $extra_args.Clone()
If (-not $check_mode) { $set_args.$key = $value
Invoke-Expression $expression Set-ADUser -Identity $username -WhatIf:$check_mode @set_args
}
$result.changed = $true $result.changed = $true
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
} }
} }
# Set additional attributes # Set additional attributes
$set_args = @{} $set_args = $extra_args.Clone()
$run_change = $false $run_change = $false
if ($attributes -ne $null) { if ($attributes -ne $null) {
$add_attributes = @{} $add_attributes = @{}
@ -213,11 +214,11 @@ If ($state -eq 'present') {
$groups = @() $groups = @()
Foreach ($group in $group_list) { Foreach ($group in $group_list) {
$groups += (Get-ADGroup -Identity $group).DistinguishedName $groups += (Get-ADGroup -Identity $group @extra_args).DistinguishedName
} }
$assigned_groups = @() $assigned_groups = @()
Foreach ($group in (Get-ADPrincipalGroupMembership -Identity $username)) { Foreach ($group in (Get-ADPrincipalGroupMembership -Identity $username @extra_args)) {
$assigned_groups += $group.DistinguishedName $assigned_groups += $group.DistinguishedName
} }
@ -225,8 +226,8 @@ If ($state -eq 'present') {
"add" { "add" {
Foreach ($group in $groups) { Foreach ($group in $groups) {
If (-not ($assigned_groups -Contains $group)) { If (-not ($assigned_groups -Contains $group)) {
Add-ADGroupMember -Identity $group -Members $username -WhatIf:$check_mode Add-ADGroupMember -Identity $group -Members $username -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
} }
@ -234,8 +235,8 @@ If ($state -eq 'present') {
"remove" { "remove" {
Foreach ($group in $groups) { Foreach ($group in $groups) {
If ($assigned_groups -Contains $group) { If ($assigned_groups -Contains $group) {
Remove-ADGroupMember -Identity $group -Members $username -Confirm:$false -WhatIf:$check_mode Remove-ADGroupMember -Identity $group -Members $username -Confirm:$false -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
} }
@ -243,15 +244,15 @@ If ($state -eq 'present') {
"replace" { "replace" {
Foreach ($group in $assigned_groups) { Foreach ($group in $assigned_groups) {
If (($group -ne $user_obj.PrimaryGroup) -and -not ($groups -Contains $group)) { If (($group -ne $user_obj.PrimaryGroup) -and -not ($groups -Contains $group)) {
Remove-ADGroupMember -Identity $group -Members $username -Confirm:$false -WhatIf:$check_mode Remove-ADGroupMember -Identity $group -Members $username -Confirm:$false -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
} }
Foreach ($group in $groups) { Foreach ($group in $groups) {
If (-not ($assigned_groups -Contains $group)) { If (-not ($assigned_groups -Contains $group)) {
Add-ADGroupMember -Identity $group -Members $username -WhatIf:$check_mode Add-ADGroupMember -Identity $group -Members $username -WhatIf:$check_mode @extra_args
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.changed = $true $result.changed = $true
} }
} }
@ -267,7 +268,7 @@ If ($state -eq 'present') {
# Ensure user does not exist # Ensure user does not exist
try { try {
If ($user_obj) { If ($user_obj) {
Remove-ADUser $user_obj -Confirm:$false -WhatIf:$check_mode Remove-ADUser $user_obj -Confirm:$false -WhatIf:$check_mode @extra_args
$result.changed = $true $result.changed = $true
If ($check_mode) { If ($check_mode) {
Exit-Json $result Exit-Json $result
@ -282,7 +283,7 @@ If ($state -eq 'present') {
try { try {
If ($user_obj) { If ($user_obj) {
$user_obj = Get-ADUser -Identity $username -Properties * $user_obj = Get-ADUser -Identity $username -Properties * @extra_args
$result.name = $user_obj.Name $result.name = $user_obj.Name
$result.firstname = $user_obj.GivenName $result.firstname = $user_obj.GivenName
$result.surname = $user_obj.Surname $result.surname = $user_obj.Surname
@ -303,7 +304,7 @@ try {
$result.sid = [string]$user_obj.SID $result.sid = [string]$user_obj.SID
$result.upn = $user_obj.UserPrincipalName $result.upn = $user_obj.UserPrincipalName
$user_groups = @() $user_groups = @()
Foreach ($group in (Get-ADPrincipalGroupMembership $username)) { Foreach ($group in (Get-ADPrincipalGroupMembership $username @extra_args)) {
$user_groups += $group.name $user_groups += $group.name
} }
$result.groups = $user_groups $result.groups = $user_groups

View file

@ -1,20 +1,9 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# This file is part of Ansible # This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# this is a windows documentation stub. actual code lives in the .ps1 # this is a windows documentation stub. actual code lives in the .ps1
# file of the same name # file of the same name
@ -155,10 +144,28 @@ options:
parameters, e.g. C(telephoneNumber). parameters, e.g. C(telephoneNumber).
- See the examples on how to format this parameter. - See the examples on how to format this parameter.
version_added: "2.5" version_added: "2.5"
domain_username:
description:
- The username to use when interacting with AD.
- If this is not set then the user Ansible used to log in with will be
used instead when using CredSSP or Kerberos with credential delegation.
version_added: '2.5'
domain_password:
description:
- The password for C(username).
version_added: '2.5'
domain_server:
description:
- Specifies the Active Directory Domain Services instance to connect to.
- Can be in the form of an FQDN or NetBIOS name.
- If not specified then the value is based on the domain of the computer
running PowerShell.
version_added: '2.5'
notes: notes:
- Works with Windows 2012R2 and newer. - Works with Windows 2012R2 and newer.
- If running on a server that is not a Domain Controller, credential - If running on a server that is not a Domain Controller, credential
delegation through CredSSP or Kerberos with delegation must be used. delegation through CredSSP or Kerberos with delegation must be used or the
I(domain_username), I(domain_password) must be set.
- Note that some individuals have confirmed successful operation on Windows - Note that some individuals have confirmed successful operation on Windows
2008R2 servers with AD and AD Web Services enabled, but this has not 2008R2 servers with AD and AD Web Services enabled, but this has not
received the same degree of testing as Windows 2012R2. received the same degree of testing as Windows 2012R2.
@ -185,6 +192,17 @@ EXAMPLES = r'''
attributes: attributes:
telephoneNumber: 555-123456 telephoneNumber: 555-123456
- name: Ensure user bob is created and use custom credentials to create the user
win_domain_user:
name: bob
firstname: Bob
surname: Smith
password: B0bP4ssw0rd
state: present
domain_username: DOMAIN\admin-account
domain_password: SomePas2w0rd
domain_server: domain@DOMAIN.COM
- name: Ensure user bob is present in OU ou=test,dc=domain,dc=local - name: Ensure user bob is present in OU ou=test,dc=domain,dc=local
win_domain_user: win_domain_user:
name: bob name: bob