2017-07-21 00:08:08 +00:00
#!powershell
2017-12-22 01:06:22 +00:00
2018-07-17 21:29:05 +00:00
# Copyright: (c) 2017, Jordan Borean <jborean93@gmail.com>, and others
2017-12-22 01:06:22 +00:00
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
2017-07-21 00:08:08 +00:00
2017-12-22 01:06:22 +00:00
# Requires -Module Ansible.ModuleUtils.Legacy
2017-07-21 00:08:08 +00:00
$ErrorActionPreference = " Stop "
$params = Parse-Args -arguments $args -supports_check_mode $true
$check_mode = Get-AnsibleParam -obj $params -name " _ansible_check_mode " -type " bool " -default $false
2018-07-17 21:29:05 +00:00
$diff_mode = Get-AnsibleParam -obj $params -name " _ansible_diff " -type " bool " -default $false
2017-07-21 00:08:08 +00:00
$name = Get-AnsibleParam -obj $params -name " name " -type " str " -failifempty $true
$display_name = Get-AnsibleParam -obj $params -name " display_name " -type " str "
$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 )
$description = Get-AnsibleParam -obj $params -name " description " -type " str "
$category = Get-AnsibleParam -obj $params -name " category " -type " str " -validateset " distribution " , " security "
$scope = Get-AnsibleParam -obj $params -name " scope " -type " str " -validateset " domainlocal " , " global " , " universal "
$managed_by = Get-AnsibleParam -obj $params -name " managed_by " -type " str "
$attributes = Get-AnsibleParam -obj $params -name " attributes "
$organizational_unit = Get-AnsibleParam -obj $params -name " organizational_unit " -type " str " -aliases " ou " , " path "
$state = Get-AnsibleParam -obj $params -name " state " -type " str " -default " present " -validateset " present " , " absent "
$protect = Get-AnsibleParam -obj $params -name " protect " -type " bool "
$ignore_protection = Get-AnsibleParam -obj $params -name " ignore_protection " -type " bool " -default $false
2018-01-07 23:38:13 +00:00
$domain_server = Get-AnsibleParam -obj $params -name " domain_server " -type " str "
2017-07-21 00:08:08 +00:00
$result = @ {
changed = $false
}
if ( $diff_mode ) {
$result . diff = @ { }
}
if ( -not ( Get-Module -Name ActiveDirectory -ListAvailable ) ) {
Fail-Json $result " win_domain_group requires the ActiveDirectory PS module to be installed "
}
Import-Module ActiveDirectory
$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
}
2018-01-07 23:38:13 +00:00
if ( $domain_server -ne $null ) {
$extra_args . Server = $domain_server
2017-12-22 01:06:22 +00:00
}
2017-07-21 00:08:08 +00:00
try {
$group = Get-ADGroup -Identity $name -Properties * @extra_args
} catch [ Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException ] {
$group = $null
} catch {
Fail-Json $result " failed to retrieve initial details for group $( $name ) : $( $_ . Exception . Message ) "
}
if ( $state -eq " absent " ) {
if ( $group -ne $null ) {
if ( $group . ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $true ) {
$group = $group | Set-ADObject -ProtectedFromAccidentalDeletion $false -WhatIf: $check_mode -PassThru @extra_args
} elseif ( $group . ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $false ) {
Fail-Json $result " cannot delete group $name when ProtectedFromAccidentalDeletion is turned on, run this module with ignore_protection=true to override this "
}
try {
$group | Remove-ADGroup -Confirm: $false -WhatIf: $check_mode @extra_args
} catch {
Fail-Json $result " failed to remove group $( $name ) : $( $_ . Exception . Message ) "
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . prepared = " -[ $name ] "
}
}
} else {
# validate that path is an actual path
if ( $organizational_unit -ne $null ) {
try {
Get-ADObject -Identity $organizational_unit @extra_args | Out-Null
} catch [ Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException ] {
Fail-Json $result " the group path $organizational_unit does not exist, please specify a valid LDAP path "
}
}
$diff_text = $null
if ( $group -ne $null ) {
# will be overriden later if no change actually occurs
$diff_text + = " [ $name ] `n "
# change the path of the group
if ( $organizational_unit -ne $null ) {
$group_cn = $group . CN
$existing_path = $group . DistinguishedName -replace " ^CN= $group_cn , " , ''
if ( $existing_path -ne $organizational_unit ) {
$protection_disabled = $false
if ( $group . ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $true ) {
$group | Set-ADObject -ProtectedFromAccidentalDeletion $false -WhatIf: $check_mode -PassThru @extra_args | Out-Null
$protection_disabled = $true
} elseif ( $group . ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $false ) {
Fail-Json $result " cannot move group $name when ProtectedFromAccidentalDeletion is turned on, run this module with ignore_protection=true to override this "
}
try {
$group = $group | Move-ADObject -Targetpath $organizational_unit -WhatIf: $check_mode -PassThru @extra_args
} catch {
Fail-Json $result " failed to move group from $existing_path to $( $organizational_unit ) : $( $_ . Exception . Message ) "
} finally {
if ( $protection_disabled -eq $true ) {
$group | Set-ADObject -ProtectedFromAccidentalDeletion $true -WhatIf: $check_mode -PassThru @extra_args | Out-Null
}
}
$result . changed = $true
$diff_text + = " -DistinguishedName = CN= $group_cn , $existing_path `n +DistinguishedName = CN= $group_cn , $organizational_unit `n "
if ( $protection_disabled -eq $true ) {
$group | Set-ADObject -ProtectedFromAccidentalDeletion $true -WhatIf: $check_mode @extra_args | Out-Null
}
# get the group again once we have moved it
$group = Get-ADGroup -Identity $name -Properties * @extra_args
}
}
# change attributes of group
$extra_scope_change = $null
$run_change = $false
$set_args = $extra_args . Clone ( )
if ( $scope -ne $null ) {
if ( $group . GroupScope -ne $scope ) {
# you cannot from from Global to DomainLocal and vice-versa, we
# need to change it to Universal and then finally to the target
# scope
if ( $group . GroupScope -eq " global " -and $scope -eq " domainlocal " ) {
$set_args . GroupScope = " Universal "
$extra_scope_change = $scope
} elseif ( $group . GroupScope -eq " domainlocal " -and $scope -eq " global " ) {
$set_args . GroupScope = " Universal "
$extra_scope_change = $scope
} else {
$set_args . GroupScope = $scope
}
$run_change = $true
$diff_text + = " -GroupScope = $( $group . GroupScope ) `n +GroupScope = $scope `n "
}
}
if ( $description -ne $null -and $group . Description -cne $description ) {
$set_args . Description = $description
$run_change = $true
$diff_text + = " -Description = $( $group . Description ) `n +Description = $description `n "
}
if ( $display_name -ne $null -and $group . DisplayName -cne $display_name ) {
$set_args . DisplayName = $display_name
$run_change = $true
$diff_text + = " -DisplayName = $( $group . DisplayName ) `n +DisplayName = $display_name `n "
}
if ( $category -ne $null -and $group . GroupCategory -ne $category ) {
$set_args . GroupCategory = $category
$run_change = $true
$diff_text + = " -GroupCategory = $( $group . GroupCategory ) `n +GroupCategory = $category `n "
}
if ( $managed_by -ne $null ) {
if ( $group . ManagedBy -eq $null ) {
$set_args . ManagedBy = $managed_by
$run_change = $true
$diff_text + = " +ManagedBy = $managed_by `n "
} else {
try {
$managed_by_object = Get-ADGroup -Identity $managed_by @extra_args
} catch [ Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException ] {
try {
$managed_by_object = Get-ADUser -Identity $managed_by @extra_args
} catch [ Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException ] {
Fail-Json $result " failed to find managed_by user or group $managed_by to be used for comparison "
}
}
if ( $group . ManagedBy -ne $managed_by_object . DistinguishedName ) {
$set_args . ManagedBy = $managed_by
$run_change = $true
$diff_text + = " -ManagedBy = $( $group . ManagedBy ) `n +ManagedBy = $( $managed_by_object . DistinguishedName ) `n "
}
}
}
if ( $attributes -ne $null ) {
$add_attributes = @ { }
$replace_attributes = @ { }
foreach ( $attribute in $attributes . GetEnumerator ( ) ) {
$attribute_name = $attribute . Name
$attribute_value = $attribute . Value
$valid_property = [ bool ] ( $group . PSobject . Properties . name -eq $attribute_name )
if ( $valid_property ) {
$existing_value = $group . $attribute_name
if ( $existing_value -cne $attribute_value ) {
$replace_attributes . $attribute_name = $attribute_value
$diff_text + = " - $attribute_name = $existing_value `n + $attribute_name = $attribute_value `n "
}
} else {
$add_attributes . $attribute_name = $attribute_value
$diff_text + = " + $attribute_name = $attribute_value `n "
}
}
if ( $add_attributes . Count -gt 0 ) {
$set_args . Add = $add_attributes
$run_change = $true
}
if ( $replace_attributes . Count -gt 0 ) {
$set_args . Replace = $replace_attributes
$run_change = $true
}
}
if ( $run_change ) {
try {
$group = $group | Set-ADGroup -WhatIf: $check_mode -PassThru @set_args
} catch {
Fail-Json $result " failed to change group $( $name ) : $( $_ . Exception . Message ) "
}
$result . changed = $true
if ( $extra_scope_change -ne $null ) {
try {
$group = $group | Set-ADGroup -GroupScope $extra_scope_change -WhatIf: $check_mode -PassThru @extra_args
} catch {
Fail-Json $result " failed to change scope of group $name to $( $scope ) : $( $_ . Exception . Message ) "
}
}
}
# make sure our diff text is null if no change occured
if ( $result . changed -eq $false ) {
$diff_text = $null
}
} else {
# validate if scope is set
if ( $scope -eq $null ) {
Fail-Json $result " scope must be set when state=present and the group doesn't exist "
}
$diff_text + = " +[ $name ] `n +Scope = $scope `n "
$add_args = $extra_args . Clone ( )
$add_args . Name = $name
$add_args . GroupScope = $scope
if ( $description -ne $null ) {
$add_args . Description = $description
$diff_text + = " +Description = $description `n "
}
if ( $display_name -ne $null ) {
$add_args . DisplayName = $display_name
$diff_text + = " +DisplayName = $display_name `n "
}
if ( $category -ne $null ) {
$add_args . GroupCategory = $category
$diff_text + = " +GroupCategory = $category `n "
}
if ( $managed_by -ne $null ) {
$add_args . ManagedBy = $managed_by
$diff_text + = " +ManagedBy = $managed_by `n "
}
if ( $attributes -ne $null ) {
$add_args . OtherAttributes = $attributes
foreach ( $attribute in $attributes . GetEnumerator ( ) ) {
$diff_text + = " + $( $attribute . Name ) = $( $attribute . Value ) `n "
}
}
if ( $organizational_unit -ne $null ) {
$add_args . Path = $organizational_unit
$diff_text + = " +Path = $organizational_unit `n "
}
try {
$group = New-AdGroup -WhatIf: $check_mode -PassThru @add_args
} catch {
Fail-Json $result " failed to create group $( $name ) : $( $_ . Exception . Message ) "
}
$result . changed = $true
}
# set the protection value
if ( $protect -ne $null ) {
if ( -not $check_mode ) {
$group = Get-ADGroup -Identity $name -Properties * @extra_args
}
$existing_protection_value = $group . ProtectedFromAccidentalDeletion
if ( $existing_protection_value -eq $null ) {
$existing_protection_value = $false
}
if ( $existing_protection_value -ne $protect ) {
$diff_text + = @"
-ProtectedFromAccidentalDeletion = $existing_protection_value
+ ProtectedFromAccidentalDeletion = $protect
" @
$group | Set-ADObject -ProtectedFromAccidentalDeletion $protect -WhatIf: $check_mode -PassThru @extra_args
$result . changed = $true
}
}
if ( $diff_mode -and $diff_text -ne $null ) {
$result . diff . prepared = $diff_text
}
if ( -not $check_mode ) {
$group = Get-ADGroup -Identity $name -Properties * @extra_args
$result . sid = $group . SID . Value
$result . description = $group . Description
$result . distinguished_name = $group . DistinguishedName
$result . display_name = $group . DisplayName
$result . name = $group . Name
$result . canonical_name = $group . CanonicalName
$result . guid = $group . ObjectGUID
$result . protected_from_accidental_deletion = $group . ProtectedFromAccidentalDeletion
$result . managed_by = $group . ManagedBy
$result . group_scope = ( $group . GroupScope ) . ToString ( )
$result . category = ( $group . GroupCategory ) . ToString ( )
if ( $attributes -ne $null ) {
$result . attributes = @ { }
foreach ( $attribute in $attributes . GetEnumerator ( ) ) {
$attribute_name = $attribute . Name
$result . attributes . $attribute_name = $group . $attribute_name
}
}
}
}
Exit-Json $result