DSCResources/MSFT_ADGroup/MSFT_ADGroup.psm1
$resourceModulePath = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent $modulesFolderPath = Join-Path -Path $resourceModulePath -ChildPath 'Modules' $aDCommonModulePath = Join-Path -Path $modulesFolderPath -ChildPath 'ActiveDirectoryDsc.Common' Import-Module -Name $aDCommonModulePath $dscResourceCommonModulePath = Join-Path -Path $modulesFolderPath -ChildPath 'DscResource.Common' Import-Module -Name $dscResourceCommonModulePath $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' <# .SYNOPSIS Returns the current state of the Active Directory group. .PARAMETER GroupName Name of the Active Directory group. .PARAMETER Credential The credential to be used to perform the operation on Active Directory. .PARAMETER DomainController Active Directory domain controller to enact the change upon. .PARAMETER MembershipAttribute Active Directory attribute used to perform membership operations. Default value is 'SamAccountName'. .NOTES Used Functions: Name | Module ------------------------------|-------------------------- Get-ADGroup | ActiveDirectory Get-ADGroupMember | ActiveDirectory Assert-Module | ActiveDirectoryDsc.Common Get-ADCommonParameters | ActiveDirectoryDsc.Common Get-ADObjectParentDN | ActiveDirectoryDsc.Common New-InvalidOperationException | ActiveDirectoryDsc.Common #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $GroupName, [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Credential, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $DomainController, [Parameter()] [ValidateSet('SamAccountName', 'DistinguishedName', 'SID', 'ObjectGUID')] [System.String] $MembershipAttribute = 'SamAccountName' ) Assert-Module -ModuleName 'ActiveDirectory' $commonParameters = Get-ADCommonParameters @PSBoundParameters Write-Verbose -Message ($script:localizedData.RetrievingGroup -f $GroupName) $getADGroupProperties = ('Name', 'GroupScope', 'GroupCategory', 'DistinguishedName', 'Description', 'DisplayName', 'ManagedBy', 'Members', 'Info') try { $adGroup = Get-ADGroup @commonParameters -Properties $getADGroupProperties } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { $adGroup = $null } catch { $errorMessage = $script:localizedData.RetrievingGroupError -f $GroupName New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } if ($adGroup) { Write-Verbose -Message ($script:localizedData.GroupIsPresent -f $GroupName) Write-Verbose -Message ($script:localizedData.RetrievingGroupMembers -f $MembershipAttribute) try { [System.Array] $adGroupMembers = (Get-ADGroupMember @commonParameters).$MembershipAttribute } catch { # This FullyQualifiedErrorId is indicative of a failure to retrieve members with Get-ADGroupMember # for a one-way trust $oneWayTrustFullyQualifiedErrorId = ` 'ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember' if ($_.FullyQualifiedErrorId -eq $oneWayTrustFullyQualifiedErrorId) { # Get-ADGroupMember returns property name 'SID' while Get-ADObject returns property name 'ObjectSID' if ($MembershipAttribute -eq 'SID') { $selectProperty = 'ObjectSID' } else { $selectProperty = $MembershipAttribute } # Use the same results from Get-ADCommonParameters but remove the Identity # for usage with Get-ADObject $getADObjectParameters = $commonParameters.Clone() $getADObjectParameters.Remove('Identity') # Retrieve the current list of members, returning the specified membership attribute [System.Array] $adGroupMembers = $adGroup.Members | ForEach-Object -Process { # Adding a Filter and additional Properties for the AD object retrieval $getADObjectParameters['Filter'] = "DistinguishedName -eq '$($_)'" $getADObjectParameters['Properties'] = @( 'SamAccountName', 'ObjectSID' ) $adObject = Get-ADObject @getADObjectParameters # Perform SID translation to a readable name as the SamAccountName if the member is # of objectClass "foreignSecurityPrincipal" $classMatchForResolve = $adObject.objectClass -eq 'foreignSecurityPrincipal' $attributeMatchForResolve = $MembershipAttribute -eq 'SamAccountName' if ($classMatchForResolve -and $attributeMatchForResolve) { Resolve-SamAccountName -ObjectSid $adObject.objectSid } else { $adObject.$selectProperty } } } else { $errorMessage = $script:localizedData.RetrievingGroupMembersError -f $GroupName New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } $targetResource = @{ Ensure = 'Present' GroupName = $adGroup.Name GroupScope = $adGroup.GroupScope Category = $adGroup.GroupCategory DistinguishedName = $adGroup.DistinguishedName Path = Get-ADObjectParentDN -DN $adGroup.DistinguishedName Description = $adGroup.Description DisplayName = $adGroup.DisplayName Members = $adGroupMembers MembersToInclude = $null MembersToExclude = $null MembershipAttribute = $MembershipAttribute ManagedBy = $adGroup.ManagedBy Notes = $adGroup.Info } } else { Write-Verbose -Message ($script:localizedData.GroupIsAbsent -f $GroupName) $targetResource = @{ Ensure = 'Absent' GroupName = $GroupName GroupScope = $null Category = $null DistinguishedName = $null Path = $null Description = $null DisplayName = $null Members = @() MembersToInclude = $null MembersToExclude = $null MembershipAttribute = $MembershipAttribute ManagedBy = $null Notes = $null } } return $targetResource } <# .SYNOPSIS Determines if the Active Directory group is in the desired state. .PARAMETER GroupName Name of the Active Directory group. .PARAMETER GroupScope Active Directory group scope. Default value is 'Global'. .PARAMETER Category Active Directory group category. Default value is 'Security'. .PARAMETER Path Location of the group within Active Directory expressed as a Distinguished Name. .PARAMETER Ensure Specifies if this Active Directory group should be present or absent. Default value is 'Present'. .PARAMETER Description Description of the Active Directory group. .PARAMETER DisplayName Display name of the Active Directory group. .PARAMETER Credential The credential to be used to perform the operation on Active Directory. .PARAMETER DomainController Active Directory domain controller to enact the change upon. .PARAMETER Members Active Directory group membership should match membership exactly. .PARAMETER MembersToInclude Active Directory group should include these members. .PARAMETER MembersToExclude Active Directory group should NOT include these members. .PARAMETER MembershipAttribute Active Directory attribute used to perform membership operations. Default value is 'SamAccountName'. .PARAMETER ManagedBy Active Directory managed by attribute specified as a DistinguishedName. .PARAMETER Notes Active Directory group notes field. .PARAMETER RestoreFromRecycleBin Try to restore the group from the recycle bin before creating a new one. .NOTES Used Functions: Name | Module ------------------------------------------|-------------------------- Assert-MemberParameters | ActiveDirectoryDsc.Common Test-Members | ActiveDirectoryDsc.Common Compare-ResourcePropertyState | ActiveDirectoryDsc.Common #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $GroupName, [Parameter()] [ValidateSet('DomainLocal', 'Global', 'Universal')] [System.String] $GroupScope = 'Global', [Parameter()] [ValidateSet('Security', 'Distribution')] [System.String] $Category = 'Security', [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Path, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Description, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $DisplayName, [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Credential, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $DomainController, [Parameter()] [System.String[]] $Members, [Parameter()] [System.String[]] $MembersToInclude, [Parameter()] [System.String[]] $MembersToExclude, [Parameter()] [ValidateSet('SamAccountName', 'DistinguishedName', 'SID', 'ObjectGUID')] [System.String] $MembershipAttribute = 'SamAccountName', # This must be the user's DN [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ManagedBy, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Notes, [Parameter()] [ValidateNotNull()] [System.Boolean] $RestoreFromRecycleBin ) $assertMemberParameters = @{} if ($PSBoundParameters.ContainsKey('Members')) { $assertMemberParameters['Members'] = $Members } if ($PSBoundParameters.ContainsKey('MembersToInclude') -and -not [System.String]::IsNullOrEmpty($MembersToInclude)) { $assertMemberParameters['MembersToInclude'] = $MembersToInclude } if ($PSBoundParameters.ContainsKey('MembersToExclude') -and -not [System.String]::IsNullOrEmpty($MembersToExclude)) { $assertMemberParameters['MembersToExclude'] = $MembersToExclude } Assert-MemberParameters @assertMemberParameters [HashTable] $parameters = $PSBoundParameters $parameters['MembershipAttribute'] = $MembershipAttribute $getTargetResourceParameters = @{ GroupName = $GroupName DomainController = $DomainController Credential = $Credential MembershipAttribute = $MembershipAttribute } # Remove parameters that have not been specified @($getTargetResourceParameters.Keys) | ForEach-Object { if (-not $parameters.ContainsKey($_)) { $getTargetResourceParameters.Remove($_) } } $getTargetResourceResult = Get-TargetResource @getTargetResourceParameters if ($getTargetResourceResult.Ensure -eq 'Present') { # Resource exists if ($Ensure -eq 'Present') { # Resource should exist # Test group members match passed membership parameters if (-not (Test-Members @assertMemberParameters -ExistingMembers $getTargetResourceResult.Members ` -Verbose:$VerbosePreference)) { Write-Verbose -Message $script:localizedData.GroupMembershipNotDesiredState $membersInDesiredState = $false } else { $membersInDesiredState = $true } $ignoreProperties = @('DomainController', 'Credential', 'MembershipAttribute', 'Members', 'MembersToInclude', 'MembersToExclude') $propertiesNotInDesiredState = (Compare-ResourcePropertyState -CurrentValues $getTargetResourceResult ` -DesiredValues $parameters -IgnoreProperties $ignoreProperties -Verbose:$VerbosePreference | Where-Object -Property InDesiredState -eq $false) if ($propertiesNotInDesiredState -or $membersInDesiredState -eq $false) { $inDesiredState = $false } else { # Resource is in desired state Write-Verbose -Message ($script:localizedData.ResourceInDesiredStateMessage -f $GroupName) $inDesiredState = $true } } else { # Resource should not exist Write-Verbose -Message ($script:localizedData.ResourceExistsButShouldNotMessage -f $GroupName) $inDesiredState = $false } } else { # Resource does not exist if ($Ensure -eq 'Present') { # Resource should exist Write-Verbose -Message ($script:localizedData.ResourceDoesNotExistButShouldMessage -f $GroupName) $inDesiredState = $false } else { # Resource should not exist Write-Verbose -Message ($script:localizedData.ResourceInDesiredStateMessage -f $GroupName) $inDesiredState = $true } } return $inDesiredState } <# .SYNOPSIS Sets the state of an Active Directory group. .PARAMETER GroupName Name of the Active Directory group. .PARAMETER GroupScope Active Directory group scope. Default value is 'Global'. .PARAMETER Category Active Directory group category. Default value is 'Security'. .PARAMETER Path Location of the group within Active Directory expressed as a Distinguished Name. .PARAMETER Ensure Specifies if this Active Directory group should be present or absent. Default value is 'Present'. .PARAMETER Description Description of the Active Directory group. .PARAMETER DisplayName Display name of the Active Directory group. .PARAMETER Credential The credential to be used to perform the operation on Active Directory. .PARAMETER DomainController Active Directory domain controller to enact the change upon. .PARAMETER Members Active Directory group membership should match membership exactly. .PARAMETER MembersToInclude Active Directory group should include these members. .PARAMETER MembersToExclude Active Directory group should NOT include these members. .PARAMETER MembershipAttribute Active Directory attribute used to perform membership operations. Default value is 'SamAccountName'. .PARAMETER ManagedBy Active Directory managed by attribute specified as a DistinguishedName. .PARAMETER Notes Active Directory group notes field. .PARAMETER RestoreFromRecycleBin Try to restore the group from the recycle bin before creating a new one. .NOTES Used Functions: Name | Module ------------------------------------------|-------------------------- Assert-MemberParameters | ActiveDirectoryDsc.Common Get-ADCommonParameters | ActiveDirectoryDsc.Common Compare-ResourcePropertyState | ActiveDirectoryDsc.Common New-InvalidOperationException | ActiveDirectoryDsc.Common Remove-DuplicateMembers | ActiveDirectoryDsc.Common Set-ADCommonGroupMember | ActiveDirectoryDsc.Common Restore-ADCommonObject | ActiveDirectoryDsc.Common Set-ADGroup | ActiveDirectory Move-ADObject | ActiveDirectory New-ADGroup | ActiveDirectory Remove-ADGroup | ActiveDirectory #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $GroupName, [Parameter()] [ValidateSet('DomainLocal', 'Global', 'Universal')] [System.String] $GroupScope = 'Global', [Parameter()] [ValidateSet('Security', 'Distribution')] [System.String] $Category = 'Security', [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Path, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Description, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $DisplayName, [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $Credential, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $DomainController, [Parameter()] [System.String[]] $Members, [Parameter()] [System.String[]] $MembersToInclude, [Parameter()] [System.String[]] $MembersToExclude, [Parameter()] [ValidateSet('SamAccountName', 'DistinguishedName', 'SID', 'ObjectGUID')] [System.String] $MembershipAttribute = 'SamAccountName', # This must be the user's DN [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ManagedBy, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Notes, [Parameter()] [ValidateNotNull()] [System.Boolean] $RestoreFromRecycleBin ) $assertMemberParameters = @{} # Members parameter should always be added to enforce an empty group (issue #189) if ($PSBoundParameters.ContainsKey('Members')) { $assertMemberParameters['Members'] = $Members } if ($PSBoundParameters.ContainsKey('MembersToInclude') -and -not [System.String]::IsNullOrEmpty($MembersToInclude)) { $assertMemberParameters['MembersToInclude'] = $MembersToInclude } if ($PSBoundParameters.ContainsKey('MembersToExclude') -and -not [System.String]::IsNullOrEmpty($MembersToExclude)) { $assertMemberParameters['MembersToExclude'] = $MembersToExclude } Assert-MemberParameters @assertMemberParameters [HashTable] $parameters = $PSBoundParameters $parameters['MembershipAttribute'] = $MembershipAttribute $getTargetResourceParameters = @{ GroupName = $GroupName DomainController = $DomainController Credential = $Credential MembershipAttribute = $MembershipAttribute } # Remove parameters that have not been specified @($getTargetResourceParameters.Keys) | ForEach-Object { if (-not $parameters.ContainsKey($_)) { $getTargetResourceParameters.Remove($_) } } $getTargetResourceResult = Get-TargetResource @getTargetResourceParameters $commonParameters = Get-ADCommonParameters @PSBoundParameters if ($Ensure -eq 'Present') { # Resource should be present if ($getTargetResourceResult.Ensure -eq 'Present') { # Resource is present $moveAdGroupRequired = $false $ignoreProperties = @('DomainController', 'Credential', 'MembershipAttribute', 'MembersToInclude', 'MembersToExclude') $propertiesNotInDesiredState = Compare-ResourcePropertyState -CurrentValues $getTargetResourceResult ` -DesiredValues $parameters -IgnoreProperties $ignoreProperties -Verbose:$VerbosePreference | Where-Object -Property InDesiredState -eq $false if ($propertiesNotInDesiredState) { $setADGroupParameters = $commonParameters.Clone() $setADGroupParameters['Identity'] = $getTargetResourceResult.DistinguishedName $SetAdGroupRequired = $false foreach ($property in $propertiesNotInDesiredState) { if ($property.ParameterName -eq 'Path') { # The path has changed, so the account needs moving, but not until after any other changes $moveAdGroupRequired = $true } elseif ($property.ParameterName -eq 'Category') { $setAdGroupRequired = $true Write-Verbose -Message ($script:localizedData.UpdatingResourceProperty -f $GroupName, $property.ParameterName, ($property.Expected -join ', ')) $setADGroupParameters['GroupCategory'] = $property.Expected } elseif ($property.ParameterName -eq 'GroupScope') { if ($GroupScope -ne 'Universal' -and $getTargetResourceResult.GroupScope -ne 'Universal') { # Cannot change DomainLocal <-> Global directly, so need to change to a Universal group first Write-Verbose -Message ($script:localizedData.UpdatingResourceProperty -f $GroupName, $property.ParameterName, 'Universal') $setADGroupUniversalGroupScopeParameters = $commonParameters.Clone() $setADGroupUniversalGroupScopeParameters['Identity'] = $getTargetResourceResult.DistinguishedName $setADGroupUniversalGroupScopeParameters['GroupScope'] = 'Universal' try { Set-ADGroup @setADGroupUniversalGroupScopeParameters } catch { $errorMessage = ($script:localizedData.SettingGroupError -f $GroupName) New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } $setAdGroupRequired = $true Write-Verbose -Message ($script:localizedData.UpdatingResourceProperty -f $GroupName, $property.ParameterName, $property.Expected) $SetAdGroupParameters[$property.ParameterName] = $property.Expected } elseif ($property.ParameterName -eq 'Notes') { $setAdGroupRequired = $true Write-Verbose -Message ($script:localizedData.UpdatingResourceProperty -f $GroupName, $property.ParameterName, ($property.Expected -join ', ')) $setADGroupParameters['Replace'] = @{ Info = $property.Expected } } elseif ($property.ParameterName -eq 'Members') { $Members = Remove-DuplicateMembers -Members $Members if (-not [System.String]::IsNullOrEmpty($property.Actual) -and -not [System.String]::IsNullOrEmpty($property.Expected)) { $compareResult = Compare-Object -ReferenceObject $property.Actual ` -DifferenceObject $property.Expected $membersToAdd = ($compareResult | Where-Object -Property SideIndicator -eq '=>').InputObject $membersToRemove = ($compareResult | Where-Object -Property SideIndicator -eq '<=').InputObject } elseif ([System.String]::IsNullOrEmpty($property.Expected)) { $membersToRemove = $property.Actual $membersToAdd = $null } else { $membersToAdd = $property.Expected $membersToRemove = $null } if (-not [System.String]::IsNullOrEmpty($membersToAdd)) { Write-Verbose -Message ($script:localizedData.AddingGroupMembers -f ($MembersToAdd -join ', '), $GroupName) $setADCommonGroupMemberParms = @{ Members = $MembersToAdd MembershipAttribute = $MembershipAttribute Parameters = $commonParameters Action = 'Add' } Set-ADCommonGroupMember @setADCommonGroupMemberParms } if (-not [System.String]::IsNullOrEmpty($membersToRemove)) { Write-Verbose -Message ($script:localizedData.RemovingGroupMembers -f ($MembersToRemove -join ', '), $GroupName) $setADCommonGroupMemberParms = @{ Members = $MembersToRemove MembershipAttribute = $MembershipAttribute Parameters = $commonParameters Action = 'Remove' } Set-ADCommonGroupMember @setADCommonGroupMemberParms } } else { $setAdGroupRequired = $true Write-Verbose -Message ($script:localizedData.UpdatingResourceProperty -f $GroupName, $property.ParameterName, ($property.Expected -join ', ')) $SetAdGroupParameters[$property.ParameterName] = $property.Expected } } if ($setAdGroupRequired) { try { Set-ADGroup @setADGroupParameters } catch { $errorMessage = ($script:localizedData.SettingGroupError -f $GroupName) New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } } if ($PSBoundParameters.ContainsKey('MembersToInclude') -and -not [System.String]::IsNullOrEmpty($MembersToInclude)) { $MembersToInclude = Remove-DuplicateMembers -Members $MembersToInclude if (-not [System.String]::IsNullOrEmpty($getTargetResourceResult.Members)) { $compareResult = Compare-Object -ReferenceObject $getTargetResourceResult.Members ` -DifferenceObject $MembersToInclude $membersToAdd = ($compareResult | Where-Object -Property SideIndicator -eq '=>').InputObject } else { $membersToAdd = $MembersToInclude } if (-not [System.String]::IsNullOrEmpty($membersToAdd)) { Write-Verbose -Message ($script:localizedData.AddingGroupMembers -f ($MembersToAdd -join ', '), $GroupName) $setADCommonGroupMemberParms = @{ Members = $MembersToAdd MembershipAttribute = $MembershipAttribute Parameters = $commonParameters Action = 'Add' } Set-ADCommonGroupMember @setADCommonGroupMemberParms } } if ($PSBoundParameters.ContainsKey('MembersToExclude') -and -not [System.String]::IsNullOrEmpty($MembersToExclude)) { $MembersToExclude = Remove-DuplicateMembers -Members $MembersToExclude if (-not [System.String]::IsNullOrEmpty($getTargetResourceResult.Members)) { $compareResult = Compare-Object -ReferenceObject $getTargetResourceResult.Members ` -DifferenceObject $MembersToExclude -IncludeEqual $membersToRemove = ($compareResult | Where-Object -Property SideIndicator -eq '==').InputObject } else { $membersToRemove = $null } if (-not [System.String]::IsNullOrEmpty($membersToRemove)) { Write-Verbose -Message ($script:localizedData.RemovingGroupMembers -f ($MembersToRemove -join ', '), $GroupName) $setADCommonGroupMemberParms = @{ Members = $MembersToRemove MembershipAttribute = $MembershipAttribute Parameters = $commonParameters Action = 'Remove' } Set-ADCommonGroupMember @setADCommonGroupMemberParms } } if ($moveAdGroupRequired) { Write-Verbose -Message ($script:localizedData.MovingGroup -f $GroupName, $Path) $moveADObjectParameters = $commonParameters.Clone() $moveADObjectParameters['Identity'] = $getTargetResourceResult.DistinguishedName try { Move-ADObject @moveADObjectParameters -TargetPath $Path } catch { $errorMessage = ($script:localizedData.MovingGroupError -f $GroupName, $getTargetResourceResult.Path, $Path) New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } } else { # Resource is absent $newAdGroupParameters = Get-ADCommonParameters @PSBoundParameters -UseNameParameter $newAdGroupParameters['GroupCategory'] = $Category $newAdGroupParameters['GroupScope'] = $GroupScope if ($PSBoundParameters.ContainsKey('Description')) { $newAdGroupParameters['Description'] = $Description } if ($PSBoundParameters.ContainsKey('DisplayName')) { $newAdGroupParameters['DisplayName'] = $DisplayName } if ($PSBoundParameters.ContainsKey('ManagedBy')) { $newAdGroupParameters['ManagedBy'] = $ManagedBy } if ($PSBoundParameters.ContainsKey('Path')) { $newAdGroupParameters['Path'] = $Path } if ($PSBoundParameters.ContainsKey('Notes')) { $newAdGroupParameters['OtherAttributes'] = @{ Info = $Notes } } $adGroup = $null # Create group. Try to restore account first if it exists. if ($RestoreFromRecycleBin) { Write-Verbose -Message ($script:localizedData.RestoringGroup -f $GroupName) $adGroup = Restore-ADCommonObject @commonParameters -ObjectClass 'Group' } # Check if the Active Directory group was restored, if not create the group. if (-not $adGroup) { Write-Verbose -Message ($script:localizedData.AddingGroup -f $GroupName) try { $adGroup = New-ADGroup @newAdGroupParameters -PassThru } catch { $errorMessage = ($script:localizedData.AddingGroupError -f $GroupName) New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } # Add the required members if ($PSBoundParameters.ContainsKey('Members') -and -not [System.String]::IsNullOrEmpty($Members)) { $Members = Remove-DuplicateMembers -Members $Members Write-Verbose -Message ($script:localizedData.AddingGroupMembers -f ($Members -join ', '), $GroupName) $setADCommonGroupMemberParms = @{ Members = $Members MembershipAttribute = $MembershipAttribute Parameters = $commonParameters Action = 'Add' } Set-ADCommonGroupMember @setADCommonGroupMemberParms } elseif ($PSBoundParameters.ContainsKey('MembersToInclude') -and -not [System.String]::IsNullOrEmpty($MembersToInclude)) { $MembersToInclude = Remove-DuplicateMembers -Members $MembersToInclude Write-Verbose -Message ($script:localizedData.AddingGroupMembers -f ($MembersToInclude -join ', '), $GroupName) $setADCommonGroupMemberParms = @{ Members = $MembersToInclude MembershipAttribute = $MembershipAttribute Parameters = $commonParameters Action = 'Add' } Set-ADCommonGroupMember @setADCommonGroupMemberParms } } } else { # Resource should be absent if ($getTargetResourceResult.Ensure -eq 'Present') { # Resource is present Write-Verbose -Message ($script:localizedData.RemovingGroup -f $GroupName) try { Remove-ADGroup @commonParameters -Confirm:$false } catch { $errorMessage = ($script:localizedData.RemovingGroupError -f $GroupName) New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } else { # Resource is absent Write-Verbose -Message ($script:localizedData.ResourceInDesiredStateMessage -f $GroupName) } } } Export-ModuleMember -Function *-TargetResource |