Skip to content

Commit

Permalink
xADGroup: Implemented multidomain group members (#240)
Browse files Browse the repository at this point in the history
- Updated xADGroup to support group membership from multiple domains (issue #152).
  • Loading branch information
nyanhp authored and johlju committed Mar 5, 2019
1 parent e4baf12 commit e330e28
Show file tree
Hide file tree
Showing 8 changed files with 459 additions and 47 deletions.
165 changes: 142 additions & 23 deletions DSCResources/MSFT_xADCommon/MSFT_xADCommon.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ data localizedString
IncludeAndExcludeAreEmptyError = The '{0}' and '{1}' parameters are either both null or empty. At least one member must be specified in one of these parameters.
ModeConversionError = Converted mode {0} is not a {1}.
RecycleBinRestoreFailed = Restoring {0} ({1}) from the recycle bin failed. Error message: {2}.
EmptyDomainError = No domain name retrieved for group member {0} in group {1}.
CheckingMembers = Checking for '{0}' members.
MembershipCountMismatch = Membership count is not correct. Expected '{0}' members, actual '{1}' members.
Expand All @@ -22,6 +23,7 @@ data localizedString
FindInRecycleBin = Finding objects in the recycle bin matching the filter {0}.
FoundRestoreTargetInRecycleBin = Found object {0} ({1}) in the recycle bin as {2}. Attempting to restore the object.
RecycleBinRestoreSuccessful = Successfully restored object {0} ({1}) from the recycle bin.
AddingGroupMember = Adding member '{0}' from domain '{1}' to AD group '{2}'.
'@
}

Expand Down Expand Up @@ -55,7 +57,8 @@ function Assert-Module
} #end function Assert-Module

# Internal function to test whether computer is a member of a domain
function Test-DomainMember {
function Test-DomainMember
{
[CmdletBinding()]
[OutputType([System.Boolean])]
param ( )
Expand All @@ -65,7 +68,8 @@ function Test-DomainMember {


# Internal function to get the domain name of the computer
function Get-DomainName {
function Get-DomainName
{
[CmdletBinding()]
[OutputType([System.String])]
param ( )
Expand All @@ -74,10 +78,11 @@ function Get-DomainName {
} # function Get-DomainName

# Internal function to build domain FQDN
function Resolve-DomainFQDN {
function Resolve-DomainFQDN
{
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[OutputType([System.String])]
[System.String] $DomainName,

Expand All @@ -99,7 +104,7 @@ function Test-ADDomain
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[System.String] $DomainName,

[Parameter()]
Expand Down Expand Up @@ -151,7 +156,7 @@ function Get-ADObjectParentDN
[OutputType([System.String])]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[System.String]
$DN
)
Expand All @@ -169,18 +174,22 @@ function Assert-MemberParameters
[CmdletBinding()]
param
(
[Parameter()]
[ValidateNotNull()]
[System.String[]]
$Members,

[Parameter()]
[ValidateNotNull()]
[System.String[]]
$MembersToInclude,

[Parameter()]
[ValidateNotNull()]
[System.String[]]
$MembersToExclude,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ModuleName = 'xActiveDirectory'
Expand Down Expand Up @@ -244,7 +253,9 @@ function Remove-DuplicateMembers
[OutputType([System.String[]])]
param
(
[System.String[]] $Members
[Parameter()]
[System.String[]]
$Members
)

Set-StrictMode -Version Latest
Expand Down Expand Up @@ -289,21 +300,25 @@ function Test-Members
param
(
## Existing array members
[Parameter()]
[AllowNull()]
[System.String[]]
$ExistingMembers,

## Explicit array members
[Parameter()]
[AllowNull()]
[System.String[]]
$Members,

## Compulsory array members
[Parameter()]
[AllowNull()]
[System.String[]]
$MembersToInclude,

## Excluded array members
[Parameter()]
[AllowNull()]
[System.String[]]
$MembersToExclude
Expand Down Expand Up @@ -380,12 +395,12 @@ function ConvertTo-TimeSpan
[OutputType([System.TimeSpan])]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.UInt32]
$TimeSpan,

[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateSet('Seconds','Minutes','Hours','Days')]
[System.String]
$TimeSpanType
Expand Down Expand Up @@ -419,12 +434,12 @@ function ConvertFrom-TimeSpan
[OutputType([System.Int32])]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.TimeSpan]
$TimeSpan,

[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateSet('Seconds','Minutes','Hours','Days')]
[System.String]
$TimeSpanType
Expand Down Expand Up @@ -466,7 +481,7 @@ function Get-ADCommonParameters
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Alias('UserName','GroupName','ComputerName')]
[System.String]
Expand Down Expand Up @@ -542,12 +557,12 @@ function ThrowInvalidOperationError
[CmdletBinding()]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorId,

[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorMessage
Expand All @@ -564,12 +579,12 @@ function ThrowInvalidArgumentError
[CmdletBinding()]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorId,

[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorMessage
Expand All @@ -589,10 +604,10 @@ function Test-ADReplicationSite
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[System.String] $SiteName,

[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[System.String] $DomainName,

[Parameter()]
Expand All @@ -601,7 +616,7 @@ function Test-ADReplicationSite
)

Write-Verbose -Message ($localizedString.CheckingSite -f $SiteName);

$existingDC = "$((Get-ADDomainController -Discover -DomainName $DomainName -ForceDiscover).HostName)";

try
Expand Down Expand Up @@ -635,6 +650,7 @@ function ConvertTo-DeploymentForestMode
[System.Nullable``1[Microsoft.ActiveDirectory.Management.ADForestMode]]
$Mode,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ModuleName = 'xActiveDirectory'
Expand All @@ -646,7 +662,7 @@ function ConvertTo-DeploymentForestMode
{
$convertedMode = $Mode -as [Microsoft.DirectoryServices.Deployment.Types.ForestMode]
}

if ($PSCmdlet.ParameterSetName -eq 'ById')
{
$convertedMode = $ModeId -as [Microsoft.DirectoryServices.Deployment.Types.ForestMode]
Expand Down Expand Up @@ -679,18 +695,19 @@ function ConvertTo-DeploymentDomainMode
[System.Nullable``1[Microsoft.ActiveDirectory.Management.ADDomainMode]]
$Mode,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ModuleName = 'xActiveDirectory'
)

$convertedMode = $null

if ($PSCmdlet.ParameterSetName -eq 'ByName' -and $Mode)
{
$convertedMode = $Mode -as [Microsoft.DirectoryServices.Deployment.Types.DomainMode]
}

if ($PSCmdlet.ParameterSetName -eq 'ById')
{
$convertedMode = $ModeId -as [Microsoft.DirectoryServices.Deployment.Types.DomainMode]
Expand All @@ -709,7 +726,7 @@ function Restore-ADCommonObject
[CmdletBinding()]
param
(
[Parameter(Mandatory)]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Alias('UserName','GroupName','ComputerName')]
[System.String]
Expand Down Expand Up @@ -772,3 +789,105 @@ function Restore-ADCommonObject

return $restoredObject
}

<#
.SYNOPSIS
Author: Robert D. Biddle (https://github.com/RobBiddle)
Created: December.20.2017
.DESCRIPTION
Takes an Active Directory DistinguishedName as input, returns the domain FQDN
.EXAMPLE
Get-ADDomainNameFromDistinguishedName -DistinguishedName 'CN=ExampleObject,OU=ExampleOU,DC=example,DC=com'
#>
function Get-ADDomainNameFromDistinguishedName
{
[CmdletBinding()]
param
(
[Parameter()]
[System.String]
$DistinguishedName
)

if ($DistinguishedName -notlike '*DC=*')
{
return
}

$splitDistinguishedName = ($DistinguishedName -split 'DC=')
$splitDistinguishedNameParts = $splitDistinguishedName[1..$splitDistinguishedName.Length]
$domainFqdn = ""
foreach ($part in $splitDistinguishedNameParts)
{
$domainFqdn += "DC=$part"
}

$domainName = $domainFqdn -replace 'DC=', '' -replace ',', '.'
return $domainName

} #end function Get-ADDomainNameFromDistinguishedName

<#
.SYNOPSIS
Add group member from current or different domain
.NOTES
Author original code: Robert D. Biddle (https://github.com/RobBiddle)
Author refactored code: Jan-Hendrik Peters (https://github.com/nyanhp)
#>
function Add-ADCommonGroupMember
{
[CmdletBinding()]
param
(
[Parameter()]
[string[]]
$Members,

[Parameter()]
[hashtable]
$Parameters,

[Parameter()]
[switch]
$MembersInMultipleDomains
)

Assert-Module -ModuleName ActiveDirectory

if ($MembersInMultipleDomains.IsPresent)
{
foreach($member in $Members)
{
$memberDomain = Get-ADDomainNameFromDistinguishedName -DistinguishedName $member

if (-not $memberDomain)
{
ThrowInvalidArgumentError -ErrorId "$($member)_EmptyDomainError" -ErrorMessage ($localizedString.EmptyDomainError -f $member, $Parameters.GroupName)
}

Write-Verbose -Message ($localizedString.AddingGroupMember -f $member, $memberDomain, $Parameters.GroupName)
$memberObjectClass = (Get-ADObject -Identity $member -Server $memberDomain -Properties ObjectClass).ObjectClass
if ($memberObjectClass -eq 'computer')
{
$memberObject = Get-ADComputer -Identity $member -Server $memberDomain
}
elseif ($memberObjectClass -eq 'group')
{
$memberObject = Get-ADGroup -Identity $member -Server $memberDomain
}
elseif ($memberObjectClass -eq 'user')
{
$memberObject = Get-ADUser -Identity $member -Server $memberDomain
}

Add-ADGroupMember @Parameters -Members $memberObject
}
}
else
{
Add-ADGroupMember @Parameters -Members $Members
}
}
Loading

0 comments on commit e330e28

Please sign in to comment.