forked from ansible/ansible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding module win_domain_computer (ansible#35954)
* Adding module win_domain_computer This module is a wrapper of powershell *-ADComputer commands. The main use case is to add non-windows computers to Active Directory through a bridge windows computer. * Replace `Set-Attr` * Fix case insensitive comparisons * Add omitted parameters in cmdlets * Enhance module documentation * Simplify `state` as case insensitive. * Simplify try catch * Fix indentation * Make message errors more descriptive. * Specify type in boolean parameters * Keep parameter ingestion together * Delete superfluous resultobj * Workaround failing Erroraction * Add target info in error * Cosmetic changes * Fix up Fail-Json to use correct message param
- Loading branch information
1 parent
57c801c
commit ee2adb4
Showing
2 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
#!powershell | ||
# | ||
# Copyright: (c) 2017, AMTEGA - Xunta de Galicia | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
#Requires -Module Ansible.ModuleUtils.Legacy | ||
|
||
|
||
# ------------------------------------------------------------------------------ | ||
$ErrorActionPreference = "Stop" | ||
|
||
# Preparing result | ||
$result = @{} | ||
$result.changed = $false | ||
|
||
# Parameter ingestion | ||
$params = Parse-Args $args -supports_check_mode $true | ||
|
||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false | ||
$diff_support = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false | ||
|
||
$name = Get-AnsibleParam -obj $params -name "name" -failifempty $true -resultobj $result | ||
$sam_account_name = Get-AnsibleParam -obj $params -name "sam_account_name" -default "$name$" | ||
If (-not $sam_account_name.EndsWith("$")) { | ||
Fail-Json -obj $result -message "sam_account_name must end in $" | ||
} | ||
$enabled = Get-AnsibleParam -obj $params -name "enabled" -type "bool" -default $true | ||
$description = Get-AnsibleParam -obj $params -name "description" -default "" | ||
$state = Get-AnsibleParam -obj $params -name "state" -ValidateSet "present","absent" -default "present" | ||
If ($state -eq "present") { | ||
$dns_hostname = Get-AnsibleParam -obj $params -name "dns_hostname" -failifempty $true -resultobj $result | ||
$ou = Get-AnsibleParam -obj $params -name "ou" -failifempty $true -resultobj $result | ||
$distinguished_name = "CN=$name,$ou" | ||
|
||
$desired_state = @{ | ||
name = $name | ||
sam_account_name = $sam_account_name | ||
dns_hostname = $dns_hostname | ||
ou = $ou | ||
distinguished_name = $distinguished_name | ||
description = $description | ||
enabled = $enabled | ||
state = $state | ||
} | ||
} Else { | ||
$desired_state = @{ | ||
name = $name | ||
state = $state | ||
} | ||
} | ||
|
||
# ------------------------------------------------------------------------------ | ||
Function Get-InitialState($desired_state) { | ||
# Test computer exists | ||
$computer = Try { | ||
Get-ADComputer ` | ||
-Identity $desired_state.name ` | ||
-Properties DistinguishedName,DNSHostName,Enabled,Name,SamAccountName,Description,ObjectClass | ||
} Catch { $null } | ||
If ($computer) { | ||
$initial_state = @{ | ||
name = $computer.Name | ||
sam_account_name = $computer.SamAccountName | ||
dns_hostname = $computer.DNSHostName | ||
# Get OU from regexp that removes all characters to the first "," | ||
ou = $computer.DistinguishedName -creplace "^[^,]*,","" | ||
distinguished_name = $computer.DistinguishedName | ||
description = $computer.Description | ||
enabled = $computer.Enabled | ||
state = "present" | ||
} | ||
} Else { | ||
$initial_state = @{ | ||
name = $desired_state.name | ||
state = "absent" | ||
} | ||
} | ||
|
||
return $initial_state | ||
} | ||
|
||
# ------------------------------------------------------------------------------ | ||
Function Set-ConstructedState($initial_state, $desired_state) { | ||
Try { | ||
Set-ADComputer ` | ||
-Identity $desired_state.name ` | ||
-SamAccountName $desired_state.name ` | ||
-DNSHostName $desired_state.dns_hostname ` | ||
-Enabled $desired_state.enabled ` | ||
-Description $desired_state.description ` | ||
-WhatIf:$check_mode | ||
} Catch { | ||
Fail-Json -obj $result -message "Failed to set the AD object $($desired_state.name): $($_.Exception.Message)" | ||
} | ||
|
||
If ($initial_state.distinguished_name -cne $desired_state.distinguished_name) { | ||
# Move computer to OU | ||
Try { | ||
Get-ADComputer -Identity $desired_state.name | | ||
Move-ADObject ` | ||
-TargetPath $desired_state.ou ` | ||
-Confirm:$False ` | ||
-WhatIf:$check_mode | ||
} Catch { | ||
Fail-Json -obj $result -message "Failed to move the AD object $($desired_state.name) to $($desired_state.ou) OU: $($_.Exception.Message)" | ||
} | ||
} | ||
$result.changed = $true | ||
} | ||
|
||
# ------------------------------------------------------------------------------ | ||
Function Add-ConstructedState($desired_state) { | ||
Try { | ||
New-ADComputer ` | ||
-Name $desired_state.name ` | ||
-SamAccountName $desired_state.sam_account_name ` | ||
-DNSHostName $desired_state.dns_hostname ` | ||
-Path $desired_state.ou ` | ||
-Enabled $desired_state.enabled ` | ||
-Description $desired_state.description ` | ||
-WhatIf:$check_mode | ||
} Catch { | ||
Fail-Json -obj $result -message "Failed to create the AD object $($desired_state.name): $($_.Exception.Message)" | ||
} | ||
|
||
$result.changed = $true | ||
} | ||
|
||
# ------------------------------------------------------------------------------ | ||
Function Remove-ConstructedState($initial_state) { | ||
Try { | ||
Remove-ADComputer ` | ||
-Identity $initial_state.name ` | ||
-Confirm:$False ` | ||
-WhatIf:$check_mode | ||
} Catch { | ||
Fail-Json -obj $result -message "Failed to remove the AD object $($desired_state.name): $($_.Exception.Message)" | ||
} | ||
|
||
$result.changed = $true | ||
} | ||
|
||
# ------------------------------------------------------------------------------ | ||
Function are_hashtables_equal($x, $y) { | ||
# Compare not nested HashTables | ||
Foreach ($key in $x.Keys) { | ||
If (($y.Keys -notcontains $key) -or ($x[$key] -cne $y[$key])) { | ||
Return $false | ||
} | ||
} | ||
foreach ($key in $y.Keys) { | ||
if (($x.Keys -notcontains $key) -or ($x[$key] -cne $y[$key])) { | ||
Return $false | ||
} | ||
} | ||
Return $true | ||
} | ||
|
||
# ------------------------------------------------------------------------------ | ||
$initial_state = Get-InitialState($desired_state) | ||
|
||
If ($desired_state.state -eq "present") { | ||
If ($initial_state.state -eq "present") { | ||
$in_desired_state = are_hashtables_equal $initial_state $desired_state | ||
|
||
If (-not $in_desired_state) { | ||
Set-ConstructedState $initial_state $desired_state | ||
} | ||
} Else { # $desired_state.state = "Present" & $initial_state.state = "Absent" | ||
Add-ConstructedState($desired_state) | ||
} | ||
} Else { # $desired_state.state = "Absent" | ||
If ($initial_state.state -eq "present") { | ||
Remove-ConstructedState($initial_state) | ||
} | ||
} | ||
|
||
If ($diff_support) { | ||
$diff = @{ | ||
before = $initial_state | ||
after = $desired_state | ||
} | ||
$result.diff = $diff | ||
} | ||
|
||
Exit-Json -obj $result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright: (c) 2017, AMTEGA - Xunta de Galicia | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
|
||
ANSIBLE_METADATA = {'metadata_version': '1.1', | ||
'status': ['preview'], | ||
'supported_by': 'community'} | ||
|
||
|
||
DOCUMENTATION = ''' | ||
--- | ||
module: win_domain_computer | ||
short_description: Manage computers in Active Directory | ||
description: | ||
- Create, read, update and delete computers in Active Directory using a | ||
windows brigde computer to launch New-ADComputer, Get-ADComputer, | ||
Set-ADComputer, Remove-ADComputer and Move-ADObject powershell commands. | ||
options: | ||
name: | ||
description: | ||
- Specifies the name of the object. This parameter sets the Name property | ||
of the Active Directory object. The LDAP display name (ldapDisplayName) | ||
of this property is name. | ||
required: true | ||
sam_account_name: | ||
description: | ||
- Specifies the Security Account Manager (SAM) account name of the | ||
computer. It maximum is 256 characters, 15 is advised for older | ||
operating systems compatibility. The LDAP display name | ||
(ldapDisplayName) for this property is sAMAccountName. If ommitted the | ||
value is the same as C(name). | ||
Note. All computer SAMAccountNames needs to end with a $. | ||
enabled: | ||
description: | ||
- Specifies if an account is enabled. An enabled account requires a | ||
password. This parameter sets the Enabled property for an account | ||
object. This parameter also sets the ADS_UF_ACCOUNTDISABLE flag of the | ||
Active Directory User Account Control (UAC) attribute. | ||
type: bool | ||
default: 'yes' | ||
ou: | ||
description: | ||
- Specifies the X.500 path of the Organizational Unit (OU) or container | ||
where the new object is created. Required when I(state=present). | ||
description: | ||
description: | ||
- Specifies a description of the object. This parameter sets the value | ||
of the Description property for the object. The LDAP display name | ||
(ldapDisplayName) for this property is description. | ||
default: '' | ||
dns_hostname: | ||
description: | ||
- Specifies the fully qualified domain name (FQDN) of the computer. This | ||
parameter sets the DNSHostName property for a computer object. The LDAP | ||
display name for this property is dNSHostName. Required when | ||
I(state=present). | ||
state: | ||
description: | ||
- Specified whether the computer should be C(present) or C(absent) in | ||
Active Directory. | ||
choices: | ||
- present | ||
- absent | ||
default: present | ||
notes: | ||
version_added: 2.6 | ||
author: Daniel Sánchez Fábregas (@Daniel-Sanchez-Fabregas) | ||
''' | ||
|
||
EXAMPLES = ''' | ||
- name: Add linux computer to Active Directory OU using a windows machine | ||
win_domain_computer: | ||
name: one_linux_server.my_org.local | ||
sam_account_name: linux_server | ||
dns_hostname: one_linux_server.my_org.local | ||
ou: "OU=servers,DC=my_org,DC=local" | ||
description: Example of linux server | ||
enabled: yes | ||
state: present | ||
delegate_to: my_windows_bridge.my_org.local | ||
- name: Remove linux computer from Active Directory using a windows machine | ||
win_domain_computer: | ||
name: one_linux_server.my_org.local | ||
state: absent | ||
delegate_to: my_windows_bridge.my_org.local | ||
''' | ||
|
||
RETURN = ''' | ||
''' |