From bb2cf2f4e16a992f8a1651da084b584d154acd32 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Wed, 10 Jul 2019 13:18:44 +0200 Subject: [PATCH 01/16] Changes to xActiveDirectory - Added new helper functions in xActiveDirectory.Common. - New-CimCredentialInstance - Add-TypeAssembly - New-ADDirectoryContext --- .../xActiveDirectory.Common.strings.psd1 | 9 +- .../xActiveDirectory.Common.psm1 | 189 +++++++++++++++++- Tests/Unit/xActiveDirectory.Common.Tests.ps1 | 131 ++++++++++++ 3 files changed, 322 insertions(+), 7 deletions(-) diff --git a/Modules/xActiveDirectory.Common/en-US/xActiveDirectory.Common.strings.psd1 b/Modules/xActiveDirectory.Common/en-US/xActiveDirectory.Common.strings.psd1 index 6bf9054ba..16692289e 100644 --- a/Modules/xActiveDirectory.Common/en-US/xActiveDirectory.Common.strings.psd1 +++ b/Modules/xActiveDirectory.Common/en-US/xActiveDirectory.Common.strings.psd1 @@ -10,7 +10,7 @@ ConvertFrom-StringData @' ArrayValueThatDoesNotMatch = {0} - {1} (ADCOMMON0007) PropertyValueOfTypeDoesNotMatch = {0} value does not match. Current value is '{1}', but expected the value '{2}'. (ADCOMMON0008) UnableToCompareType = Unable to compare the type {0} as it is not handled by the Test-DscPropertyState cmdlet. (ADCOMMON0009) - RoleNotFoundError = Please ensure that the PowerShell module for role '{0}' is installed. (ADCOMMON0010) + ModuleNotFoundError = Please ensure that the PowerShell module for role '{0}' is installed. (ADCOMMON0010) MembersAndIncludeExcludeError = The '{0}' and '{1}' and/or '{2}' parameters conflict. The '{0}' parameter should not be used in any combination with the '{1}' and '{2}' parameters. (ADCOMMON0011) MembersIsNullError = The Members parameter value is null. The '{0}' parameter must be provided if neither '{1}' nor '{2}' is provided. (ADCOMMON0012) IncludeAndExcludeConflictError = The member '{0}' is included in both '{1}' and '{2}' parameter values. The same member must not be included in both '{1}' and '{2}' parameter values. (ADCOMMON0014) @@ -39,4 +39,11 @@ ConvertFrom-StringData @' ValueOfTypeDoesNotMatch = {0} value for property {1} does not match. Current state is '{2}' and desired state is '{3}'. (ADCOMMON0039) UnableToCompareProperty = Unable to compare property {0} as the type {1} is not handled by the Test-DscParameterState cmdlet. (ADCOMMON0040) StartProcess = Started the process with id {0} using the path '{1}', and with a timeout value of {2} seconds. (ADCOMMON0041) + CouldNotLoadAssembly = The assembly '{0}' could not be loaded into the PowerShell session. (ADCOMMON0042) + TypeAlreadyExistInSession = The type '{0}' is already loaded into the PowerShell session. (ADCOMMON0043) + TypeDoesNotExistInSession = Missing the type '{0}' from the PowerShell session. (ADCOMMON0044) + AddingAssemblyToSession = Adding the assembly '{0}' into the PowerShell session. (ADCOMMON0045) + NewDirectoryContext = Get a new Active Directory context of the type '{0}'. (ADCOMMON0046) + NewDirectoryContextTarget = The Active Directory context will target '{0}'. (ADCOMMON0047) + NewDirectoryContextCredential = The Active Directory context will be accessed using the '{0}' credentials. (ADCOMMON0048) '@ diff --git a/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 b/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 index f91c8ca83..bb87d25af 100644 --- a/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 +++ b/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 @@ -488,7 +488,7 @@ function Assert-Module if (-not (Get-Module -Name $ModuleName -ListAvailable)) { - $errorMessage = $script:localizedData.RoleNotFoundError -f $moduleName + $errorMessage = $script:localizedData.ModuleNotFoundError -f $moduleName New-ObjectNotFoundException -Message $errorMessage } @@ -1500,10 +1500,9 @@ function Convert-PropertyMapToObjectProperties values. Normally set to $PSBoundParameters. .PARAMETER Properties - An array of property names to filter out from the keys provided in - DesiredValues. If left out, only those keys in the DesiredValues will - be compared. This parameter can be used to remove certain keys from - the comparison. + An array of property names, from the keys provided in DesiredValues, that + will be compared. If this parameter is left out, all the keys in the + DesiredValues will be compared. #> function Compare-ResourcePropertyState { @@ -1730,7 +1729,8 @@ function Assert-ADPSDrive if ($null -eq $activeDirectoryPSDrive) { - Write-Verbose -Message $script:localizedData.CreatingNewADPSDrive + Write-Verbose -Message $script:localizedData.CreatingNewADPSDrive -Verbose + try { New-PSDrive -Name AD -PSProvider 'ActiveDirectory' -Root $Root -Scope Script -ErrorAction 'Stop' | @@ -1768,6 +1768,180 @@ function Set-DscADComputer Set-ADComputer @Parameters | Out-Null } +<# + .SYNOPSIS + This returns a new MSFT_Credential CIM instance credential object to be + used when returning credential objects from Get-TargetResource. + This returns a credential object without the password. + + .PARAMETER Credential + The PSCredential object to return as a MSFT_Credential CIM instance + credential object. + + .NOTES + When returning a PSCredential object from Get-TargetResource, the + credential object does not contain the username. The object is empty. + + Password UserName PSComputerName + -------- -------- -------------- + localhost + + When the MSFT_Credential CIM instance credential object is returned by + the Get-TargetResource then the credential object contains the values + provided in the object. + + Password UserName PSComputerName + -------- -------- -------------- + COMPANY\TestAccount localhost +#> +function New-CimCredentialInstance +{ + [CmdletBinding()] + [OutputType([Microsoft.Management.Infrastructure.CimInstance])] + param + ( + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $Credential + ) + + $newCimInstanceParameters = @{ + ClassName = 'MSFT_Credential' + ClientOnly = $true + Namespace = 'root/microsoft/windows/desiredstateconfiguration' + Property = @{ + UserName = [System.String] $Credential.UserName + Password = [System.String] $null + } + } + + return New-CimInstance @newCimInstanceParameters +} + +<# + .SYNOPSIS + This loads the assembly type, optionally after a check + if the type is missing in the PowerShell session. + + .PARAMETER AssemblyName + The assembly to load into the PowerShell session. + + .PARAMETER TypeName + An optional parameter to check if the type exist, if it exist then the + assembly is not loaded again. +#> +function Add-TypeAssembly +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $AssemblyName, + + [Parameter()] + [System.String] + $TypeName + ) + + if ($PSBoundParameters.ContainsKey('TypeName')) + { + if ($TypeName -as [Type]) + { + Write-Verbose -Message ($script:localizedData.TypeAlreadyExistInSession -f $TypeName) -Verbose + + # The type already exist so no need to load the type again. + return + } + else + { + Write-Verbose -Message ($script:localizedData.TypeDoesNotExistInSession -f $TypeName) -Verbose + } + } + + try + { + Write-Verbose -Message ($script:localizedData.AddingAssemblyToSession -f $AssemblyName) -Verbose + + Add-Type -AssemblyName $AssemblyName + } + catch + { + $missingRoleMessage = $script:localizedData.CouldNotLoadAssembly -f $AssemblyName + New-ObjectNotFoundException -Message $missingRoleMessage -ErrorRecord $_ + } +} + +<# + .SYNOPSIS + This returns a new object of the type System.DirectoryServices.ActiveDirectory.DirectoryContext. + + .PARAMETER DirectoryContextType + The context type of the object to return. Valid values are 'Domain', 'Forest', + 'ApplicationPartition', 'ConfigurationSet' or 'DirectoryServer'. + + .PARAMETER Name + An optional parameter for the target of the directory context. + For the correct format for this parameter depending on context type, see + the article https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectory.directorycontext?view=netframework-4.8 +#> +function Get-ADDirectoryContext +{ + [CmdletBinding()] + [OutputType([System.DirectoryServices.ActiveDirectory.DirectoryContext])] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Domain', 'Forest', 'ApplicationPartition', 'ConfigurationSet', 'DirectoryServer')] + [System.String] + $DirectoryContextType, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential + ) + + $typeName = 'System.DirectoryServices.ActiveDirectory.DirectoryContext' + + Add-TypeAssembly -AssemblyName 'System.DirectoryServices' -TypeName $typeName + + Write-Verbose -Message ($script:localizedData.NewDirectoryContext -f $DirectoryContextType) -Verbose + + $newObjectArgumentList = @( + $DirectoryContextType + ) + + if ($PSBoundParameters.ContainsKey('Name')) + { + Write-Verbose -Message ($script:localizedData.NewDirectoryContextTarget -f $Name) -Verbose + + $newObjectArgumentList += @( + $Name + ) + } + + if ($PSBoundParameters.ContainsKey('Credential')) + { + Write-Verbose -Message ($script:localizedData.NewDirectoryContextCredential -f $Credential.UserName) -Verbose + + $newObjectArgumentList += @( + $Credential.UserName + $Credential.GetNetworkCredential().Password + ) + } + + $newObjectParameters = @{ + TypeName = $typeName + ArgumentList = $newObjectArgumentList + } + + return New-Object @newObjectParameters +} + $script:localizedData = Get-LocalizedData -ResourceName 'xActiveDirectory.Common' -ScriptRoot $PSScriptRoot Export-ModuleMember -Function @( @@ -1802,4 +1976,7 @@ Export-ModuleMember -Function @( 'Test-DscPropertyState' 'Assert-ADPSDrive' 'Set-DscADComputer' + 'New-CimCredentialInstance' + 'Add-TypeAssembly' + 'Get-ADDirectoryContext' ) diff --git a/Tests/Unit/xActiveDirectory.Common.Tests.ps1 b/Tests/Unit/xActiveDirectory.Common.Tests.ps1 index 1d0b7b3b3..5384fec1c 100644 --- a/Tests/Unit/xActiveDirectory.Common.Tests.ps1 +++ b/Tests/Unit/xActiveDirectory.Common.Tests.ps1 @@ -2133,4 +2133,135 @@ InModuleScope 'xActiveDirectory.Common' { } } } + + Describe 'xActiveDirectory.CommonNew-CimCredentialInstance' { + Context 'When creating a new MSFT_Credential CIM instance credential object' { + BeforeAll { + $mockAdministratorUser = 'admin@contoso.com' + $mockAdministratorPassword = 'P@ssw0rd-12P@ssw0rd-12' + $mockAdministratorCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( + $mockAdministratorUser, + ($mockAdministratorPassword | ConvertTo-SecureString -AsPlainText -Force) + ) + } + + It 'Should return the correct values' { + $newCimCredentialInstanceResult = New-CimCredentialInstance -Credential $mockAdministratorCredential + $newCimCredentialInstanceResult | Should -BeOfType 'Microsoft.Management.Infrastructure.CimInstance' + $newCimCredentialInstanceResult.CimClass.CimClassName | Should -Be 'MSFT_Credential' + $newCimCredentialInstanceResult.UserName | Should -Be $mockAdministratorUser + $newCimCredentialInstanceResult.Password | Should -BeNullOrEmpty + } + } + } + + Describe 'xActiveDirectory.Common\Add-TypeAssembly' { + Context 'When assembly fails to load' { + BeforeAll { + Mock -CommandName Add-Type -MockWith { + throw + } + + $mockAssembly = 'MyAssembly' + } + + It 'Should throw the correct error' { + { Add-TypeAssembly -AssemblyName $mockAssembly } | Should -Throw ($script:localizedData.CouldNotLoadAssembly -f $mockAssembly) + } + } + + Context 'When loading an assembly into the session' { + BeforeAll { + Mock -CommandName Add-Type + + $mockAssembly = 'MyAssembly' + } + + It 'Should not throw and call the correct mocks' { + { Add-TypeAssembly -AssemblyName $mockAssembly } | Should -Not -Throw + + Assert-MockCalled -CommandName Add-Type -ParameterFilter { + $AssemblyName -eq $mockAssembly + } -Exactly -Times 1 -Scope It + } + + Context 'When the type is already loaded into the session' { + It 'Should not throw and not call any mocks' { + { Add-TypeAssembly -AssemblyName $mockAssembly -TypeName 'System.String' } | Should -Not -Throw + + Assert-MockCalled -CommandName Add-Type -Exactly -Times 0 -Scope It + } + } + + Context 'When the type is missing from the session' { + It 'Should not throw and call the correct mocks' { + { Add-TypeAssembly -AssemblyName $mockAssembly -TypeName 'My.Type' } | Should -Not -Throw + + Assert-MockCalled -CommandName Add-Type -ParameterFilter { + $AssemblyName -eq $mockAssembly + } -Exactly -Times 1 -Scope It + } + } + } + } + + Describe 'xActiveDirectory.Common\New-ADDirectoryContext' { + Context 'When creating a new Active Directory context' { + BeforeAll { + # This credential object must be created before we mock New-Object. + $mockAdministratorUser = 'admin@contoso.com' + $mockAdministratorPassword = 'P@ssw0rd-12P@ssw0rd-12' + $mockAdministratorCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( + $mockAdministratorUser, + ($mockAdministratorPassword | ConvertTo-SecureString -AsPlainText -Force) + ) + + Mock -CommandName Add-TypeAssembly -Verifiable + Mock -CommandName New-Object + } + + Context 'When the calling with only parameter DirectoryContextType' { + It 'Should not throw and call the correct mocks' { + { Get-ADDirectoryContext -DirectoryContextType 'Domain' } | Should -Not -Throw + + Assert-MockCalled -CommandName New-Object -ParameterFilter { + $ArgumentList.Count -eq 1 ` + -and $ArgumentList[0] -eq 'Domain' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When the calling with parameters DirectoryContextType and Name' { + It 'Should not throw and call the correct mocks' { + { + Get-ADDirectoryContext -DirectoryContextType 'Domain' -Name 'my.domain' + } | Should -Not -Throw + + Assert-MockCalled -CommandName New-Object -ParameterFilter { + $ArgumentList.Count -eq 2 ` + -and $ArgumentList[0] -eq 'Domain' ` + -and $ArgumentList[1] -eq 'my.domain' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When the calling with parameters DirectoryContextType, Name and Credential' { + It 'Should not throw and call the correct mocks' { + { + Get-ADDirectoryContext -DirectoryContextType 'Domain' -Name 'my.domain' -Credential $mockAdministratorCredential + } | Should -Not -Throw + + Assert-MockCalled -CommandName New-Object -ParameterFilter { + $ArgumentList.Count -eq 4 ` + -and $ArgumentList[0] -eq 'Domain' ` + -and $ArgumentList[1] -eq 'my.domain' ` + -and $ArgumentList[2] -eq $mockAdministratorUser ` + -and $ArgumentList[3] -eq $mockAdministratorPassword + } -Exactly -Times 1 -Scope It + } + } + + Assert-VerifiableMock + } + } } From 88b967e7118ad7e9dbc71ada324a23ee405c7dc6 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Wed, 10 Jul 2019 13:19:23 +0200 Subject: [PATCH 02/16] Changes to xADDomainTrust - Refactored the resource to enable unit tests, and at the same time changed it to use the same code pattern as the resource xADObjectEnabledState. - Added unit tests (issue #324). - Added comment-based help (issue #337). --- CHANGELOG.md | 9 + .../MSFT_xADDomainTrust.psm1 | 682 ++++++++----- .../MSFT_xADDomainTrust.schema.mof | 15 +- .../en-US/MSFT_xADDomainTrust.strings.psd1 | 24 +- .../en-US/about_xADDomainTrust.help.txt | 12 +- Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 | 938 ++++++++++++++++++ 6 files changed, 1422 insertions(+), 258 deletions(-) create mode 100644 Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index e41e8d997..a81e6e4d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ - The default value on resource parameters are now reflected in the parameter descriptions in the schema.mof (so that Wiki will be updated) ([issue #426](https://github.com/PowerShell/xActiveDirectory/issues/426)). + - Added new helper functions in xActiveDirectory.Common. + - New-CimCredentialInstance + - Add-TypeAssembly + - New-ADDirectoryContext - Changes to xADManagedServiceAccount - Added a requirement to README stating "Group Managed Service Accounts need at least one Windows Server 2012 Domain Controller" @@ -54,6 +58,11 @@ - Changes to xADServicePrincipalName - Minor change to the unit tests that did not correct assert the localized string when an account is not found. +- Changes to xADDomainTrust + - Refactored the resource to enable unit tests, and at the same time changed + it to use the same code pattern as the resource xADObjectEnabledState. + - Added unit tests ([issue #324](https://github.com/PowerShell/xActiveDirectory/issues/324)). + - Added comment-based help ([issue #337](https://github.com/PowerShell/xActiveDirectory/issues/337)). ## 3.0.0.0 diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index 16c0122fb..1180904fd 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -6,6 +6,29 @@ Import-Module -Name (Join-Path -Path $script:localizationModulePath -ChildPath ' $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_xADDomainTrust' +<# + .SYNOPSIS + Returns the current state of the Active Directory trust. + + .PARAMETER SourceDomainName + Specifies the name of the Active Directory domain that is requesting the + trust. + + .PARAMETER TargetDomainName + Specifies the name of the Active Directory domain that is being trusted. + + .PARAMETER TargetDomainAdministratorCredential + Specifies the credentials to authenticate to the target domain.. + + .PARAMETER TrustType + Specifies the type of trust. Valid values are 'External' or 'Forest'. + 'External' means the context Domain, while 'Forest' means the context + 'Forest'. + + .PARAMETER TrustDirection + Specifies the direction of the trust. Valid values are 'Bidirectional', + 'Inbound', and 'Outbound'. +#> function Get-TargetResource { [CmdletBinding()] @@ -32,84 +55,106 @@ function Get-TargetResource [Parameter(Mandatory = $true)] [ValidateSet('Bidirectional', 'Inbound', 'Outbound')] [System.String] - $TrustDirection, - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present' + $TrustDirection ) - # Load the .NET assembly - try + # Return a credential object without the password. + $cimCredentialInstance = New-CimCredentialInstance -Credential $TargetDomainAdministratorCredential + + $returnValue = @{ + SourceDomainName = $SourceDomainName + TargetDomainName = $TargetDomainName + TargetDomainAdministratorCredential = $cimCredentialInstance + } + + $directoryContextType = ConvertTo-DirectoryContextType -TrustType $TrustType + + # Create the target object. + $newADDirectoryContextParameters = @{ + DirectoryContextType = $directoryContextType + Name = $TargetDomainName + Credential = $TargetDomainAdministratorCredential + } + + $targetDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters + + # Create the source object. + $newADDirectoryContextParameters = @{ + DirectoryContextType = $directoryContextType + Name = $SourceDomainName + } + + $sourceDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters + + if ($directoryContextType -eq 'Domain') { - Add-type -AssemblyName System.DirectoryServices + $trustSource = Get-ActiveDirectoryDomain -DirectoryContext $sourceDirectoryContext + $trustTarget = Get-ActiveDirectoryDomain -DirectoryContext $targetDirectoryContext } - # If not found, means ADDS role is not installed - catch + else { - $missingRoleMessage = $($script:localizedData.MissingRoleMessage) -f 'AD-Domain-Services' - New-ObjectNotFoundException -Message $missingRoleMessage -ErrorRecord $_ + $trustSource = Get-ActiveDirectoryForest -DirectoryContext $sourceDirectoryContext + $trustTarget = Get-ActiveDirectoryForest -DirectoryContext $targetDirectoryContext } try { - switch ($TrustType) - { - 'External' - { - $DomainOrForest = 'Domain' - } - - 'Forest' - { - $DomainOrForest = 'Forest' - } - } + # Find trust between source & destination. + Write-Verbose -Message ( + $script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName, $directoryContextTyp + ) - # Create the target object - $trgDirectoryContext = New-Object -TypeName 'System.DirectoryServices.ActiveDirectory.DirectoryContext' -ArgumentList @($DomainOrForest, $TargetDomainName, $TargetDomainAdministratorCredential.UserName, $TargetDomainAdministratorCredential.GetNetworkCredential().Password) - $trgDomain = ([type]"System.DirectoryServices.ActiveDirectory.$DomainOrForest")::"Get$DomainOrForest"($trgDirectoryContext) + $trust = $trustSource.GetTrustRelationship($trustTarget) - # Create the source object - $srcDirectoryContext = New-Object -TypeName 'System.DirectoryServices.ActiveDirectory.DirectoryContext' -ArgumentList @($DomainOrForest, $SourceDomainName) - $srcDomain = ([type]"System.DirectoryServices.ActiveDirectory.$DomainOrForest")::"Get$DomainOrForest"($srcDirectoryContext) + $returnValue['TrustDirection'] = $trust.TrustDirection + $returnValue['TrustType'] = ConvertFrom-DirectoryContextType -DirectoryContextType $trust.TrustType - # Find trust between source & destination. - Write-Verbose -Message ($script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName) - $trust = $srcDomain.GetTrustRelationship($trgDomain) + Write-Verbose -Message ($script:localizedData.TrustPresentMessage -f $SourceDomainName, $TargetDomainName, $directoryContextType) - Write-Verbose -Message ($script:localizedData.TrustPresentMessage -f $SourceDomainName, $TargetDomainName) - $Ensure = 'Present' + $returnValue['Ensure'] = 'Present' } catch { - Write-Verbose -Message ($script:localizedData.TrustAbsentMessage -f $SourceDomainName, $TargetDomainName) - $Ensure = 'Absent' - } + Write-Verbose -Message ($script:localizedData.TrustAbsentMessage -f $SourceDomainName, $TargetDomainName, $directoryContextType) - # return a credential object without password - $CIMCredential = New-CimInstance -ClassName MSFT_Credential -ClientOnly ` - -Namespace 'root/microsoft/windows/desiredstateconfiguration' ` - -Property @{ - UserName = [System.String] $TargetDomainAdministratorCredential.UserName - Password = [System.String] $null + $returnValue['Ensure'] = 'Absent' + $returnValue['TrustDirection'] = $null + $returnValue['TrustType'] = $null } - return @{ - SourceDomainName = $SourceDomainName - TargetDomainName = $TargetDomainName - Ensure = $Ensure - TrustType = $trust.TrustType - TrustDirection = $trust.TrustDirection - TargetDomainAdministratorCredential = $CIMCredential - } + return $returnValue } +<# + .SYNOPSIS + Creates, removes, or updates the Active Directory trust so it is in the + desired state. + + .PARAMETER SourceDomainName + Specifies the name of the Active Directory domain that is requesting the + trust. + + .PARAMETER TargetDomainName + Specifies the name of the Active Directory domain that is being trusted. + + .PARAMETER TargetDomainAdministratorCredential + Specifies the credentials to authenticate to the target domain.. + + .PARAMETER TrustType + Specifies the type of trust. Valid values are 'External' or 'Forest'. + 'External' means the context Domain, while 'Forest' means the context + 'Forest'. + + .PARAMETER TrustDirection + Specifies the direction of the trust. Valid values are 'Bidirectional', + 'Inbound', and 'Outbound'. + + .PARAMETER Ensure + Specifies whether the computer account is present or absent. Valid values + are 'Present' and 'Absent'. The default is 'Present'. +#> function Set-TargetResource { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "", - Justification = 'Verbose messaging in helper function')] [CmdletBinding()] param ( @@ -141,18 +186,167 @@ function Set-TargetResource $Ensure = 'Present' ) - if ($PSBoundParameters.ContainsKey('Debug')) + $directoryContextType = ConvertTo-DirectoryContextType -TrustType $TrustType + + # Create the target object. + $newADDirectoryContextParameters = @{ + DirectoryContextType = $directoryContextType + Name = $TargetDomainName + Credential = $TargetDomainAdministratorCredential + } + + $targetDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters + + # Create the source object. + $newADDirectoryContextParameters = @{ + DirectoryContextType = $directoryContextType + Name = $SourceDomainName + } + + $sourceDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters + + if ($directoryContextType -eq 'Domain') + { + $trustSource = Get-ActiveDirectoryDomain -DirectoryContext $sourceDirectoryContext + $trustTarget = Get-ActiveDirectoryDomain -DirectoryContext $targetDirectoryContext + } + else + { + $trustSource = Get-ActiveDirectoryForest -DirectoryContext $sourceDirectoryContext + $trustTarget = Get-ActiveDirectoryForest -DirectoryContext $targetDirectoryContext + } + + $compareTargetResourceStateResult = Compare-TargetResourceState @PSBoundParameters + + # Get all properties that are not in desired state. + $propertiesNotInDesiredState = $compareTargetResourceStateResult | + Where-Object -FilterScript { + -not $_.InDesiredState + } + + if ($propertiesNotInDesiredState.Where({ $_.ParameterName -eq 'Ensure' })) { - $null = $PSBoundParameters.Remove('Debug') + if ($Ensure -eq 'Present') + { + # Create trust. + $trustSource.CreateTrustRelationship($trustTarget, $TrustDirection) + + Write-Verbose -Message ( + $script:localizedData.AddedTrust -f @( + $SourceDomainName, + $TargetDomainName, + $TrustType, + $TrustDirection + ) + ) + + } + else + { + # Remove trust. + $trustSource.DeleteTrustRelationship($trustTarget) + + Write-Verbose -Message ( + $script:localizedData.RemovedTrust -f @( + $SourceDomainName, + $TargetDomainName, + $TrustType, + $TrustDirection + ) + ) + } } + else + { + if ($Ensure -eq 'Present') + { + $trustRecreated = $false + + # Check properties. + $trustTypeProperty = $propertiesNotInDesiredState.Where({ $_.ParameterName -eq 'TrustType' }) + if ($trustTypeProperty) + { + Write-Verbose -Message ( + $script:localizedData.NeedToRecreateTrust -f @( + $SourceDomainName, + $TargetDomainName, + (ConvertFrom-DirectoryContextType -DirectoryContextType $trustTypeProperty.Actual), + $TrustType + ) + ) + + $trustSource.DeleteTrustRelationship($trustTarget) + $trustSource.CreateTrustRelationship($trustTarget, $TrustDirection) + + Write-Verbose -Message ( + $script:localizedData.RecreatedTrustType -f @( + $SourceDomainName, + $TargetDomainName, + $TrustType, + $TrustDirection + ) + ) + + $trustRecreated = $true + } - Confirm-ResourceProperties @PSBoundParameters -Apply + <# + In case the trust direction property should be wrong, there + are no need to update that property twice since it was set + to the correct value when the trust was recreated. + #> + if (-not $trustRecreated) + { + if ($propertiesNotInDesiredState.Where({ $_.ParameterName -eq 'TrustDirection' })) + { + $trustSource.UpdateTrustRelationship($trustTarget, $TrustDirection) + + Write-Verbose -Message ( + $script:localizedData.SetTrustDirection -f $TrustDirection + ) + } + } + + Write-Verbose -Message $script:localizedData.InDesiredState + } + else + { + # The trust is already absent, so in desired state. + Write-Verbose -Message $script:localizedData.InDesiredState + } + } } +<# + .SYNOPSIS + Determines if the properties of the Active Directory trust is in + the desired state. + + .PARAMETER SourceDomainName + Specifies the name of the Active Directory domain that is requesting the + trust. + + .PARAMETER TargetDomainName + Specifies the name of the Active Directory domain that is being trusted. + + .PARAMETER TargetDomainAdministratorCredential + Specifies the credentials to authenticate to the target domain.. + + .PARAMETER TrustType + Specifies the type of trust. Valid values are 'External' or 'Forest'. + 'External' means the context Domain, while 'Forest' means the context + 'Forest'. + + .PARAMETER TrustDirection + Specifies the direction of the trust. Valid values are 'Bidirectional', + 'Inbound', and 'Outbound'. + + .PARAMETER Ensure + Specifies whether the computer account is present or absent. Valid values + are 'Present' and 'Absent'. The default is 'Present'. +#> function Test-TargetResource { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "", - Justification = 'Verbose messaging in helper function')] [CmdletBinding()] [OutputType([System.Boolean])] param @@ -185,34 +379,63 @@ function Test-TargetResource $Ensure = 'Present' ) - #region Input Validation + Write-Verbose -Message ( + $script:localizedData.TestConfiguration -f $SourceDomainName, $TargetDomainName, $TrustType + ) - # Load the .NET assembly - try + <# + This returns array of hashtables which contain the properties ParameterName, + Expected, Actual, and InDesiredState. + #> + $compareTargetResourceStateResult = Compare-TargetResourceState @PSBoundParameters + + if ($false -in $compareTargetResourceStateResult.InDesiredState) { - Add-type -AssemblyName System.DirectoryServices + $testTargetResourceReturnValue = $false + + Write-Verbose -Message $script:localizedData.NotInDesiredState } - # If not found, means ADDS role is not installed - catch + else { - $missingRoleMessage = $($script:localizedData.MissingRoleMessage) -f 'AD-Domain-Services' - New-ObjectNotFoundException -Message $missingRoleMessage -ErrorRecord $_ - } + $testTargetResourceReturnValue = $true - #endregion - - if ($PSBoundParameters.ContainsKey('Debug')) - { - $null = $PSBoundParameters.Remove('Debug') + Write-Verbose -Message $script:localizedData.InDesiredState } - Confirm-ResourceProperties @PSBoundParameters + return $testTargetResourceReturnValue } -function Confirm-ResourceProperties +<# + .SYNOPSIS + Compares the properties in the current state with the properties of the + desired state and returns a hashtable with the comaprison result. + + .PARAMETER SourceDomainName + Specifies the name of the Active Directory domain that is requesting the + trust. + + .PARAMETER TargetDomainName + Specifies the name of the Active Directory domain that is being trusted. + + .PARAMETER TargetDomainAdministratorCredential + Specifies the credentials to authenticate to the target domain.. + + .PARAMETER TrustType + Specifies the type of trust. Valid values are 'External' or 'Forest'. + 'External' means the context Domain, while 'Forest' means the context + 'Forest'. + + .PARAMETER TrustDirection + Specifies the direction of the trust. Valid values are 'Bidirectional', + 'Inbound', and 'Outbound'. + + .PARAMETER Ensure + Specifies whether the computer account is present or absent. Valid values + are 'Present' and 'Absent'. The default is 'Present'. +#> +function Compare-TargetResourceState { [CmdletBinding()] - [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] @@ -240,180 +463,179 @@ function Confirm-ResourceProperties [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Apply + $Ensure = 'Present' ) - try - { - $checkingTrustMessage = $script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName - Write-Verbose -Message $checkingTrustMessage - - switch ($TrustType) - { - 'External' - { - $DomainOrForest = 'Domain' - } - - 'Forest' - { - $DomainOrForest = 'Forest' - } - } - - # Create the target object - $trgDirectoryContext = New-Object -TypeName 'System.DirectoryServices.ActiveDirectory.DirectoryContext' -ArgumentList @($DomainOrForest, $TargetDomainName, $TargetDomainAdministratorCredential.UserName, $TargetDomainAdministratorCredential.GetNetworkCredential().Password) - $trgDomain = ([type]"System.DirectoryServices.ActiveDirectory.$DomainOrForest")::"Get$DomainOrForest"($trgDirectoryContext) - - # Create the source object - $srcDirectoryContext = New-Object -TypeName 'System.DirectoryServices.ActiveDirectory.DirectoryContext' -ArgumentList @($DomainOrForest, $SourceDomainName) - $srcDomain = ([type]"System.DirectoryServices.ActiveDirectory.$DomainOrForest")::"Get$DomainOrForest"($srcDirectoryContext) + $getTargetResourceParameters = @{ + SourceDomainName = $SourceDomainName + TargetDomainName = $TargetDomainName + TargetDomainAdministratorCredential = $TargetDomainAdministratorCredential + TrustType = $TrustType + TrustDirection = $TrustDirection + } - # Find trust - try - { - # Find trust between source & destination. - $trust = $srcDomain.GetTrustRelationship($TargetDomainName) + $getTargetResourceResult = Get-TargetResource @getTargetResourceParameters - $TestTrustMessage = $script:localizedData.TestTrustMessage -f 'present', $Ensure - Write-Verbose -Message $TestTrustMessage + <# + If the desired state should be Absent, then there is no need to + compare properties other than 'Ensure'. If the other properties + would be compared, they would return a false negative during test. + #> + if ($Ensure -eq 'Present') + { + $propertiesToEvaluate = @( + 'Ensure' + 'TrustType' + 'TrustDirection' + ) + } + else + { + $propertiesToEvaluate = @( + 'Ensure' + ) + } - if ($Ensure -eq 'Present') - { - #region Test for trust direction - $CheckPropertyMessage = $script:localizedData.CheckPropertyMessage -f 'trust direction' - Write-Verbose -Message $CheckPropertyMessage + <# + If the user did not specify Ensure property, then it is not part of + the $PSBoundParameters, but it still need to be compared. + Copy the hashtable $PSBoundParameters and add 'Ensure' property to make + sure it is part of the DesiredValues. + #> + $desiredValues = @{ } + $PSBoundParameters + $desiredValues['Ensure'] = $Ensure + + $compareTargetResourceStateParameters = @{ + CurrentValues = $getTargetResourceResult + DesiredValues = $desiredValues + Properties = $propertiesToEvaluate + } - if ($trust.TrustDirection -ne $TrustDirection) - { - # Set the trust direction if not correct - - $notDesiredPropertyMessage = $script:localizedData.NotDesiredPropertyMessage -f 'Trust direction', $TrustDirection, $trust.TrustDirection - Write-Verbose -Message $notDesiredPropertyMessage - - if ($Apply) - { - $srcDomain.UpdateTrustRelationship($trgDomain, $TrustDirection) - - $setPropertyMessage = $script:localizedData.SetPropertyMessage -f 'Trust direction' - Write-Verbose -Message $setPropertyMessage - } - else - { - return $false - } - } # end trust direction is not correct - else - { - # Trust direction is correct + return Compare-ResourcePropertyState @compareTargetResourceStateParameters +} - $desiredPropertyMessage = $script:localizedData.DesiredPropertyMessage -f 'Trust direction' - Write-Verbose -Message $desiredPropertyMessage - } - #endregion trust direction +<# + .SYNOPSIS + This returns a new object of the type System.DirectoryServices.ActiveDirectory.Domain + which is a class that represents an Active Directory Domain Services domain. + + .PARAMETER DirectoryContext + The Active Directory context from which the domain object is returned. + Calling the Get-ADDirectoryContext gets a value that can be provided in + this parameter. + + .NOTES + This is a wrapper for enable unit testing of this resource. + see issue https://github.com/PowerShell/xActiveDirectory/issues/324 + for more information. +#> +function Get-ActiveDirectoryDomain +{ + [CmdletBinding()] + [OutputType([System.DirectoryServices.ActiveDirectory.Domain])] + param + ( + [Parameter(Mandatory = $true)] + [System.DirectoryServices.ActiveDirectory.DirectoryContext] + $DirectoryContext + ) - #region Test for trust type - $CheckPropertyMessage = $script:localizedData.CheckPropertyMessage -f 'trust type' - Write-Verbose -Message $CheckPropertyMessage + return [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DirectoryContext) +} - if ($trust.TrustType -ne $TrustType) - { - # Set the trust type if not correct - - $notDesiredPropertyMessage = $script:localizedData.NotDesiredPropertyMessage -f 'Trust type', $TrustType, $trust.TrustType - Write-Verbose -Message $notDesiredPropertyMessage - - if ($Apply) - { - # Only way to fix the trust direction is to delete it and create again - # TODO: Add a property to ask user permission to delete an existing trust - $srcDomain.DeleteTrustRelationship($trgDomain) - $srcDomain.CreateTrustRelationship($trgDomain, $TrustDirection) - - $setPropertyMessage = $script:localizedData.SetPropertyMessage -f 'Trust type' - Write-Verbose -Message $setPropertyMessage - } - else - { - return $false - } - } # end trust type is not correct - else - { - # Trust type is correct +<# + .SYNOPSIS + This returns a new object of the type System.DirectoryServices.ActiveDirectory.Forest + which is a class that represents an Active Directory Domain Services forest. + + .PARAMETER DirectoryContext + The Active Directory context from which the forest object is returned. + Calling the Get-ADDirectoryContext gets a value that can be provided in + this parameter. + + .NOTES + This is a wrapper for enable unit testing of this resource. + see issue https://github.com/PowerShell/xActiveDirectory/issues/324 + for more information. +#> +function Get-ActiveDirectoryForest +{ + [CmdletBinding()] + [OutputType([System.DirectoryServices.ActiveDirectory.Forest])] + param + ( + [Parameter(Mandatory = $true)] + [System.DirectoryServices.ActiveDirectory.DirectoryContext] + $DirectoryContext + ) - $desiredPropertyMessage = $script:localizedData.DesiredPropertyMessage -f 'Trust type' - Write-Verbose -Message $desiredPropertyMessage - } - #endregion Test for trust type + return [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($DirectoryContext) +} - # If both trust type and trust direction are correct, return true - if (-not $Apply) - { - return $true - } - } # end Ensure -eq present - else - { - # If the trust should be absent, remove the trust +<# + .SYNOPSIS + This returns the converted value from a Trust Type value to the correct + Directory Context Type value. - if ($Apply) - { - $removingTrustMessage = $script:localizedData.RemovingTrustMessage -f $SourceDomainName, $TargetDomainName - Write-Verbose -Message $removingTrustMessage + .PARAMETER TrustType + The trust type value to convert. +#> +function ConvertTo-DirectoryContextType +{ + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $TrustType + ) - $srcDomain.DeleteTrustRelationship($trgDomain) + switch ($TrustType) + { + 'External' + { + $directoryContextType = 'Domain' + } - $deleteTrustMessage = $script:localizedData.DeleteTrustMessage - Write-Verbose -Message $deleteTrustMessage - } - else - { - return $false - } - } # end Ensure -eq absent - } # end find trust - catch [System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException] + 'Forest' { - # Trust does not exist between source and destination + $directoryContextType = 'Forest' + } + } - $TestTrustMessage = $script:localizedData.TestTrustMessage -f 'absent', $Ensure - Write-Verbose -Message $TestTrustMessage + return $directoryContextType +} - if ($Ensure -eq 'Present') - { - if ($Apply) - { - $addingTrustMessage = $script:localizedData.AddingTrustMessage -f $SourceDomainName, $TargetDomainName - Write-Verbose -Message $addingTrustMessage +<# + .SYNOPSIS + This returns the converted value from a Directory Context Type value to + the correct Trust Type value. - $srcDomain.CreateTrustRelationship($trgDomain, $TrustDirection) + .PARAMETER DirectoryContextType + The Directory Context Type value to convert. +#> +function ConvertFrom-DirectoryContextType +{ + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DirectoryContextType + ) - $setTrustMessage = $script:localizedData.SetTrustMessage - Write-Verbose -Message $setTrustMessage - } - else - { - return $false - } - } # end Ensure -eq Present - else - { - if (-not $Apply) - { - return $true - } - } - } # end no trust - } # end getting directory object - catch [System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException] + switch ($DirectoryContextType) { - throw + 'Domain' + { + $trustType = 'External' + } + + 'Forest' + { + $trustType = 'Forest' + } } + + return $trustType } Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof index 4f35d5a6c..5055df7b1 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof @@ -1,13 +1,10 @@ - [ClassVersion("1.0.1.0"), FriendlyName("xADDomainTrust")] class MSFT_xADDomainTrust : OMI_BaseResource { - [Write, Description("Should this resource be present or absent"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; - [Required, EmbeddedInstance("MSFT_Credential"), Description("Credentials to authenticate to the target domain")] String TargetDomainAdministratorCredential; - [Key, Description("Name of the AD domain that is being trusted")] String TargetDomainName; - [Required, Description("Type of trust"), ValueMap{"External","Forest"}, Values{"External","Forest"}] String TrustType; - [Required, Description("Direction of trust"), ValueMap{"Bidirectional","Inbound","Outbound"}, Values{"Bidirectional","Inbound","Outbound"}] String TrustDirection; - [Key, Description("Name of the AD domain that is requesting the trust")] String SourceDomainName; + [Write, Description("Specifies whether the computer account is present or absent. Valid values are 'Present' and 'Absent'. The default is 'Present'."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Required, Description("Specifies the credentials to authenticate to the target domain."), EmbeddedInstance("MSFT_Credential")] String TargetDomainAdministratorCredential; + [Key, Description("Specifies the name of the Active Directory domain that is being trusted.")] String TargetDomainName; + [Required, Description("Specifies the type of trust. Valid values are 'External' or 'Forest'. 'External' means the context Domain, while 'Forest' means the context 'Forest'."), ValueMap{"External","Forest"}, Values{"External","Forest"}] String TrustType; + [Required, Description("Specifies the direction of the trust. Valid values are 'Bidirectional', 'Inbound', and 'Outbound'."), ValueMap{"Bidirectional","Inbound","Outbound"}, Values{"Bidirectional","Inbound","Outbound"}] String TrustDirection; + [Key, Description("Specifies the name of the Active Directory domain that is requesting the trust.")] String SourceDomainName; }; - - diff --git a/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 b/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 index 92be13b4d..779f9fd86 100644 --- a/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 +++ b/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 @@ -1,16 +1,14 @@ # culture="en-US" ConvertFrom-StringData @' -MissingRoleMessage = Please ensure that the {0} role is installed -CheckingTrustMessage = Checking if Trust between {0} and {1} exists ... -TestTrustMessage = Trust is {0} between source and target domains and it should be {1} -RemovingTrustMessage = Removing trust between {0} and {1} domains ... -DeleteTrustMessage = Trust between specified domains is now absent -AddingTrustMessage = Adding domain trust between {0} and {1} ... -SetTrustMessage = Trust between specified domains is now present -CheckPropertyMessage = Checking for {0} between domains ... -DesiredPropertyMessage = {0} between domains is set correctly -NotDesiredPropertyMessage = {0} between domains is not correct. Expected {1}, actual {2} -SetPropertyMessage = {0} between domains is set -TrustPresentMessage = Trust between domains {0} and {1} is present -TrustAbsentMessage = Trust between domains {0} and {1} is absent +CheckingTrustMessage = Determining if the trust between the '{0}' and the '{1}' with the context type '{2}' exists. (ADDT0001) +RemovedTrust = Trust between between domains '{0}' and '{1}' with the context type '{2}' has been removed. (ADDT0002) +AddedTrust = Created the trust between domains '{0}' and '{1}' with the context type '{2}' and direction '{3}'. (ADDT0003) +SetTrustDirection = The trust direction has been changed to '{0}'. (ADDT0004) +TrustPresentMessage = The trust between domains '{0}' and '{1}' with the context type '{2}' exist. (ADDT0005) +TrustAbsentMessage = There is no trust between domains '{0}' and '{1}' with the context type '{2}'. (ADDT0006) +TestConfiguration = Determining the current state of the Active Directory trust with source domain '{0}', target domain '{1}' and context type '{2}'. (ADDT0007) +InDesiredState = The Active Directory trust is in the desired state. (ADDT0008) +NotInDesiredState = The Active Directory trust is not in the desired state. (ADDT0009) +NeedToRecreateTrust = The trust type is not in desired state, removing the trust between the domains '{0}' and '{1}' with the context type '{2}' to be able to recreate the trust with the correct context type '{3}'. (ADDT0010) +RecreatedTrustType = Recreated the trust between domains '{0}' and '{1}' with the context type '{2}' and direction '{3}'. (ADDT0011) '@ diff --git a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt index 9979d78de..30c553d60 100644 --- a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt +++ b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt @@ -11,29 +11,29 @@ .PARAMETER Ensure Write - String Allowed values: Present, Absent - Should this resource be present or absent + Specifies whether the computer account is present or absent. Valid values are 'Present' and 'Absent'. The default is 'Present'. .PARAMETER TargetDomainAdministratorCredential Required - String - Credentials to authenticate to the target domain + Specifies the credentials to authenticate to the target domain. .PARAMETER TargetDomainName Key - String - Name of the AD domain that is being trusted + Specifies the name of the Active Directory domain that is being trusted. .PARAMETER TrustType Required - String Allowed values: External, Forest - Type of trust + Specifies the type of trust. Valid values are 'External' or 'Forest'. 'External' means the context Domain, while 'Forest' means the context 'Forest'. .PARAMETER TrustDirection Required - String Allowed values: Bidirectional, Inbound, Outbound - Direction of trust + Specifies the direction of the trust. Valid values are 'Bidirectional', 'Inbound', and 'Outbound'. .PARAMETER SourceDomainName Key - String - Name of the AD domain that is requesting the trust + Specifies the name of the Active Directory domain that is requesting the trust. .EXAMPLE 1 diff --git a/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 b/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 new file mode 100644 index 000000000..ce8977633 --- /dev/null +++ b/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 @@ -0,0 +1,938 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')] +param () + +$script:dscModuleName = 'xActiveDirectory' +$script:dscResourceName = 'MSFT_xADDomainTrust' + +#region HEADER + +# Unit Test Template Version: 1.2.4 +$script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` + (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) +{ + & git @('clone', 'https://github.com/PowerShell/DscResource.Tests.git', (Join-Path -Path $script:moduleRoot -ChildPath 'DscResource.Tests')) +} + +Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -Force + +$TestEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType Unit + +#endregion HEADER + +function Invoke-TestSetup +{ +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $TestEnvironment +} + +# Begin Testing +try +{ + Invoke-TestSetup + + InModuleScope $script:dscResourceName { + $mockSourceDomainName = 'contoso.com' + $mockTargetDomainName = 'lab.local' + + $mockCredentialUserName = 'COMPANY\User' + $mockCredentialPassword = 'dummyPassw0rd' | ConvertTo-SecureString -AsPlainText -Force + $mockCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( + $mockCredentialUserName, $mockCredentialPassword + ) + + Describe 'MSFT_xADDomainTrust\Get-TargetResource' -Tag 'Get' { + BeforeAll { + Mock -CommandName Get-ADDirectoryContext -MockWith { + # This should work on any client, domain joined or not. + return [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new('Domain') + } + + $mockDefaultParameters = @{ + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + TrustDirection = 'Outbound' + Verbose = $true + } + } + + Context 'When the system is in the desired state' { + Context 'When the domain trust is present in Active Directory' { + Context 'When the called with the TrustType ''External''' { + BeforeAll { + Mock -CommandName Get-ActiveDirectoryDomain -MockWith { + return New-Object -TypeName Object | + Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { + $script:getTrustRelationshipMethodCallCount += 1 + + return @{ + TrustType = 'Domain' + TrustDirection = 'Outbound' + } + } -PassThru -Force + } + } + + BeforeEach { + $script:getTrustRelationshipMethodCallCount = 0 + + $mockGetTargetResourceParameters = $mockDefaultParameters.Clone() + $mockGetTargetResourceParameters['TrustType'] = 'External' + } + + AfterEach { + $script:getTrustRelationshipMethodCallCount | Should -Be 1 + + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + + It 'Should return the state as present' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.Ensure | Should -Be 'Present' + } + + It 'Should return the same values as passed as parameters' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.SourceDomainName | Should -Be $mockGetTargetResourceParameters.SourceDomainName + $getTargetResourceResult.TargetDomainName | Should -Be $mockGetTargetResourceParameters.TargetDomainName + $getTargetResourceResult.TargetDomainAdministratorCredential.UserName | Should -Be $mockCredential.UserName + } + + It 'Should return the correct values for the other properties' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.TrustDirection | Should -Be $mockGetTargetResourceParameters.TrustDirection + $getTargetResourceResult.TrustType | Should -Be $mockGetTargetResourceParameters.TrustType + } + } + + Context 'When the called with the TrustType ''Forest''' { + BeforeAll { + Mock -CommandName Get-ActiveDirectoryForest -MockWith { + return New-Object -TypeName Object | + Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { + $script:getTrustRelationshipMethodCallCount += 1 + + return @{ + TrustType = 'Forest' + TrustDirection = 'Outbound' + } + } -PassThru -Force + } + } + + BeforeEach { + $script:getTrustRelationshipMethodCallCount = 0 + + $mockGetTargetResourceParameters = $mockDefaultParameters.Clone() + $mockGetTargetResourceParameters['TrustType'] = 'Forest' + } + + AfterEach { + $script:getTrustRelationshipMethodCallCount | Should -Be 1 + + Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + } + + It 'Should return the state as present' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.Ensure | Should -Be 'Present' + } + + It 'Should return the same values as passed as parameters' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.SourceDomainName | Should -Be $mockGetTargetResourceParameters.SourceDomainName + $getTargetResourceResult.TargetDomainName | Should -Be $mockGetTargetResourceParameters.TargetDomainName + $getTargetResourceResult.TargetDomainAdministratorCredential.UserName | Should -Be $mockCredential.UserName + } + + It 'Should return the correct values for the other properties' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.TrustDirection | Should -Be $mockGetTargetResourceParameters.TrustDirection + $getTargetResourceResult.TrustType | Should -Be $mockGetTargetResourceParameters.TrustType + } + } + } + + Context 'When the domain trust is absent from Active Directory' { + BeforeAll { + Mock -CommandName Get-ActiveDirectoryForest -MockWith { + return New-Object -TypeName Object | + Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { + $script:GetTrustRelationshipMethodCallCount += 1 + + throw + } -PassThru -Force + } + } + + BeforeEach { + $script:GetTrustRelationshipMethodCallCount = 0 + + $mockGetTargetResourceParameters = $mockDefaultParameters.Clone() + $mockGetTargetResourceParameters['TrustType'] = 'Forest' + } + + AfterEach { + $script:getTrustRelationshipMethodCallCount | Should -Be 1 + + Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + } + + It 'Should return the state as absent' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.Ensure | Should -Be 'Absent' + } + + It 'Should return the same values as passed as parameters' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.SourceDomainName | Should -Be $mockGetTargetResourceParameters.SourceDomainName + $getTargetResourceResult.TargetDomainName | Should -Be $mockGetTargetResourceParameters.TargetDomainName + $getTargetResourceResult.TargetDomainAdministratorCredential.UserName | Should -Be $mockCredential.UserName + } + + It 'Should return the correct values for the other properties' { + $getTargetResourceResult = Get-TargetResource @mockGetTargetResourceParameters + $getTargetResourceResult.TrustDirection | Should -BeNullOrEmpty + $getTargetResourceResult.TrustType | Should -BeNullOrEmpty + } + } + } + + } + + Describe 'MSFT_xADDomainTrust\Test-TargetResource' -Tag 'Test' { + BeforeAll { + $mockDefaultParameters = @{ + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + Verbose = $true + } + } + + Context 'When the system is in the desired state' { + Context 'When the trust is absent from Active Directory' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $true + } + ) + } + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['Ensure'] = 'Absent' + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return $true' { + $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters + $testTargetResourceResult | Should -BeTrue + + Assert-MockCalled -CommandName Compare-TargetResourceState -Exactly -Times 1 -Scope It + } + } + + Context 'When the trust is present in Active Directory' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $true + } + ) + } + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return $true' { + $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters + $testTargetResourceResult | Should -BeTrue + + Assert-MockCalled -CommandName Compare-TargetResourceState -Exactly -Times 1 -Scope It + } + } + } + + Context 'When the system is not in the desired state' { + Context 'When the trust should be absent from Active Directory' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $false + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $true + } + ) + } + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['Ensure'] = 'Absent' + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return $false' { + $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters + $testTargetResourceResult | Should -BeFalse + + Assert-MockCalled -CommandName Compare-TargetResourceState -Exactly -Times 1 -Scope It + } + } + + Context 'When the trust should be present in Active Directory' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $false + } + ) + } + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return $false' { + $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters + $testTargetResourceResult | Should -BeFalse + + Assert-MockCalled -CommandName Compare-TargetResourceState -Exactly -Times 1 -Scope It + } + } + } + } + + Describe 'MSFT_xADDomainTrust\Compare-TargetResourceState' -Tag 'Compare' { + BeforeAll { + $mockDefaultParameters = @{ + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + Verbose = $true + } + + $mockGetTargetResource_Absent = { + return @{ + Ensure = 'Absent' + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + TrustDirection = $null + TrustType = $null + } + } + + $mockGetTargetResource_Present = { + return @{ + Ensure = 'Present' + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + TrustDirection = 'Outbound' + TrustType = 'External' + } + } + } + + Context 'When the system is in the desired state' { + Context 'When the trust is absent from Active Directory' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith $mockGetTargetResource_Absent + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['Ensure'] = 'Absent' + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return the correct values' { + $compareTargetResourceStateResult = Compare-TargetResourceState @testTargetResourceParameters + $compareTargetResourceStateResult | Should -HaveCount 1 + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'Ensure' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'Absent' + $comparedReturnValue.Actual | Should -Be 'Absent' + $comparedReturnValue.InDesiredState | Should -BeTrue + + Assert-MockCalled -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + } + } + + Context 'When the trust is present in Active Directory' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith $mockGetTargetResource_Present + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return the correct values' { + $compareTargetResourceStateResult = Compare-TargetResourceState @testTargetResourceParameters + $compareTargetResourceStateResult | Should -HaveCount 3 + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'Ensure' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'Present' + $comparedReturnValue.Actual | Should -Be 'Present' + $comparedReturnValue.InDesiredState | Should -BeTrue + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'TrustType' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'External' + $comparedReturnValue.Actual | Should -Be 'External' + $comparedReturnValue.InDesiredState | Should -BeTrue + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'TrustDirection' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'Outbound' + $comparedReturnValue.Actual | Should -Be 'Outbound' + $comparedReturnValue.InDesiredState | Should -BeTrue + + Assert-MockCalled -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + } + } + } + + Context 'When the system is not in the desired state' { + Context 'When the trust should be absent from Active Directory' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith $mockGetTargetResource_Present + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['Ensure'] = 'Absent' + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return the correct values' { + $compareTargetResourceStateResult = Compare-TargetResourceState @testTargetResourceParameters + $compareTargetResourceStateResult | Should -HaveCount 1 + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'Ensure' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'Absent' + $comparedReturnValue.Actual | Should -Be 'Present' + $comparedReturnValue.InDesiredState | Should -BeFalse + + Assert-MockCalled -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + } + } + + Context 'When the trust should be present in Active Directory' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith $mockGetTargetResource_Absent + + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + } + + It 'Should return the correct values' { + $compareTargetResourceStateResult = Compare-TargetResourceState @testTargetResourceParameters + $compareTargetResourceStateResult | Should -HaveCount 3 + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'Ensure' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'Present' + $comparedReturnValue.Actual | Should -Be 'Absent' + $comparedReturnValue.InDesiredState | Should -BeFalse + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'TrustType' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'External' + $comparedReturnValue.Actual | Should -BeNullOrEmpty + $comparedReturnValue.InDesiredState | Should -BeFalse + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq 'TrustDirection' }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be 'Outbound' + $comparedReturnValue.Actual | Should -BeNullOrEmpty + $comparedReturnValue.InDesiredState | Should -BeFalse + + Assert-MockCalled -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + } + } + + Context 'When a property is not in desired state' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith $mockGetTargetResource_Present + + + # One test case per property with a value that differs from the desired state. + $testCases_Properties = @( + @{ + ParameterName = 'TrustType' + Value = 'Forest' + }, + @{ + ParameterName = 'TrustDirection' + Value = 'Inbound' + } + ) + } + + It 'Should return the correct values when the property is not in desired state' -TestCases $testCases_Properties { + param + ( + [Parameter()] + $ParameterName, + + [Parameter()] + $Value + ) + + # Set up all mandatory parameters to use the values in the mock. + $testTargetResourceParameters = $mockDefaultParameters.Clone() + $testTargetResourceParameters['TrustType'] = 'External' + $testTargetResourceParameters['TrustDirection'] = 'Outbound' + + # Change the property we are currently testing to a different value. + $testTargetResourceParameters[$ParameterName] = $Value + + $compareTargetResourceStateResult = Compare-TargetResourceState @testTargetResourceParameters + $compareTargetResourceStateResult | Should -HaveCount 3 + + $comparedReturnValue = $compareTargetResourceStateResult.Where( { $_.ParameterName -eq $ParameterName }) + $comparedReturnValue | Should -Not -BeNullOrEmpty + $comparedReturnValue.Expected | Should -Be $Value + $comparedReturnValue.Actual | Should -Be (& $mockGetTargetResource_Present).$ParameterName + $comparedReturnValue.InDesiredState | Should -BeFalse + + Assert-MockCalled -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + } + } + } + } + + Describe 'MSFT_xADDomainTrust\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Get-ADDirectoryContext -MockWith { + # This should work on any client, domain joined or not. + return [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new('Domain') + } + + $mockGetActiveDirectoryDomainOrForest = { + return New-Object -TypeName Object | + Add-Member -MemberType ScriptMethod -Name 'CreateTrustRelationship' -Value { + $script:createTrustRelationshipMethodCallCount += 1 + } -PassThru | + Add-Member -MemberType ScriptMethod -Name 'DeleteTrustRelationship' -Value { + $script:deleteTrustRelationshipMethodCallCount += 1 + } -PassThru | + Add-Member -MemberType ScriptMethod -Name 'UpdateTrustRelationship' -Value { + $script:updateTrustRelationshipMethodCallCount += 1 + } -PassThru -Force + } + + Mock -CommandName Get-ActiveDirectoryDomain -MockWith $mockGetActiveDirectoryDomainOrForest + Mock -CommandName Get-ActiveDirectoryForest -MockWith $mockGetActiveDirectoryDomainOrForest + + $mockDefaultParameters = @{ + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + TrustDirection = 'Outbound' + Verbose = $true + } + } + + Context 'When the system is in the desired state' { + Context 'When the domain trust is present in Active Directory' { + Context 'When the called with the TrustType ''External''' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $true + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'External' + } + + It 'Should not throw and not call any methods' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 0 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 + $script:updateTrustRelationshipMethodCallCount | Should -Be 0 + + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + } + + Context 'When the called with the TrustType ''Forest''' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $true + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'Forest' + } + + It 'Should not throw and not call any methods' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 0 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 + $script:updateTrustRelationshipMethodCallCount | Should -Be 0 + + Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + } + } + } + + Context 'When the domain trust is absent in Active Directory' { + Context 'When the called with the TrustType ''External''' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $true + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'External' + $setTargetResourceParameters['Ensure'] = 'Absent' + } + + It 'Should not throw and not call any methods' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 0 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 + $script:updateTrustRelationshipMethodCallCount | Should -Be 0 + + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + } + } + } + + Context 'When the system is not in the desired state' { + Context 'When the domain trust should be present in Active Directory' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $false + } + @{ + ParameterName = 'TrustType' + InDesiredState = $false + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $false + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'External' + } + + It 'Should not throw and call the correct method' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 1 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 + $script:updateTrustRelationshipMethodCallCount | Should -Be 0 + + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + } + + Context 'When the domain trust should be absent from Active Directory' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + InDesiredState = $false + } + @{ + ParameterName = 'TrustType' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + InDesiredState = $true + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'External' + $setTargetResourceParameters['Ensure'] = 'Absent' + } + + It 'Should not throw and call the correct method' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 0 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 1 + $script:updateTrustRelationshipMethodCallCount | Should -Be 0 + + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + } + + Context 'When a property of a domain trust is not in desired state' { + Context 'When both properties TrustType and and TrustDirection is not in desired state' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + Actual = 'Present' + Expected = 'Present' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + Actual = 'Domain' + Expected = 'Forest' + InDesiredState = $false + } + @{ + ParameterName = 'TrustDirection' + Actual = 'Outbound' + Expected = 'Inbound' + InDesiredState = $false + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'Forest' + $setTargetResourceParameters['TrustDirection'] = 'Inbound' + } + + It 'Should not throw and call the correct methods' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 1 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 1 + $script:updateTrustRelationshipMethodCallCount | Should -Be 0 + + Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + } + } + + Context 'When property TrustDirection is not in desired state' { + BeforeAll { + Mock -CommandName Compare-TargetResourceState -MockWith { + return @( + @{ + ParameterName = 'Ensure' + Actual = 'Present' + Expected = 'Present' + InDesiredState = $true + } + @{ + ParameterName = 'TrustType' + Actual = 'Domain' + Expected = 'Domain' + InDesiredState = $true + } + @{ + ParameterName = 'TrustDirection' + Actual = 'Outbound' + Expected = 'Inbound' + InDesiredState = $false + } + ) + } + } + + BeforeEach { + $script:createTrustRelationshipMethodCallCount = 0 + $script:deleteTrustRelationshipMethodCallCount = 0 + $script:updateTrustRelationshipMethodCallCount = 0 + + $setTargetResourceParameters = $mockDefaultParameters.Clone() + $setTargetResourceParameters['TrustType'] = 'External' + $setTargetResourceParameters['TrustDirection'] = 'Inbound' + } + + It 'Should not throw and call the correct method' { + { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw + + $script:createTrustRelationshipMethodCallCount | Should -Be 0 + $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 + $script:updateTrustRelationshipMethodCallCount | Should -Be 1 + + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + } + } + } + } + + Describe 'MSFT_xADDomainTrust\ConvertTo-DirectoryContextType' -Tag 'Helper' { + BeforeAll { + $testCases = @( + @{ + TrustTypeValue = 'External' + DirectoryContextTypeValue = 'Domain' + }, + @{ + TrustTypeValue = 'Forest' + DirectoryContextTypeValue = 'Forest' + } + ) + } + + It 'Should return the correct converted value for the trust type value ' -TestCases $testCases { + param + ( + [Parameter()] + $TrustTypeValue, + + [Parameter()] + $DirectoryContextTypeValue + ) + + $convertToDirectoryContextTypeResult = ConvertTo-DirectoryContextType -TrustType $TrustTypeValue + $convertToDirectoryContextTypeResult | Should -Be $DirectoryContextTypeValue + } + + It 'Should return the correct converted value for the directory context type value ' -TestCases $testCases { + param + ( + [Parameter()] + $TrustTypeValue, + + [Parameter()] + $DirectoryContextTypeValue + ) + + $convertFromDirectoryContextTypeResult = ConvertFrom-DirectoryContextType -DirectoryContextType $DirectoryContextTypeValue + $convertFromDirectoryContextTypeResult | Should -Be $TrustTypeValue + } + } + } +} +finally +{ + Invoke-TestCleanup +} From dd366562742c4fb70fe03aeba3471a32546fcfba Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Wed, 10 Jul 2019 13:29:35 +0200 Subject: [PATCH 03/16] Update README.md --- DSCResources/MSFT_xADDomainTrust/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSCResources/MSFT_xADDomainTrust/README.md b/DSCResources/MSFT_xADDomainTrust/README.md index 4505d111a..260b0db36 100644 --- a/DSCResources/MSFT_xADDomainTrust/README.md +++ b/DSCResources/MSFT_xADDomainTrust/README.md @@ -1,6 +1,6 @@ # Description -The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains, that makes it possible for users in one domain to be authenticated by a domain controller in the other domain. +The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. That makes it possible for users in one domain to be authenticated by a domain controller in the other domain. ## Requirements From e3eff0b0f5283070c712ba188bdb6ba40f5af6dc Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Wed, 10 Jul 2019 16:53:33 +0200 Subject: [PATCH 04/16] Fix typo in varible --- DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index 1180904fd..4a9c2480c 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -101,7 +101,7 @@ function Get-TargetResource { # Find trust between source & destination. Write-Verbose -Message ( - $script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName, $directoryContextTyp + $script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName, $directoryContextType ) $trust = $trustSource.GetTrustRelationship($trustTarget) From e0bc9ec8f6b435ea2c8807b22efe38a24e49fed1 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Wed, 10 Jul 2019 16:57:13 +0200 Subject: [PATCH 05/16] Changes to xADDomainTrust - Added integration tests (issue #348). --- CHANGELOG.md | 1 + .../MSFT_xADDomainTrust.Integration.Tests.ps1 | 349 ++++++++++++++++++ .../MSFT_xADDomainTrust.config.ps1 | 193 ++++++++++ 3 files changed, 543 insertions(+) create mode 100644 Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 create mode 100644 Tests/Integration/MSFT_xADDomainTrust.config.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index a81e6e4d2..ce8d041b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ it to use the same code pattern as the resource xADObjectEnabledState. - Added unit tests ([issue #324](https://github.com/PowerShell/xActiveDirectory/issues/324)). - Added comment-based help ([issue #337](https://github.com/PowerShell/xActiveDirectory/issues/337)). + - Added integration tests ([issue #348](https://github.com/PowerShell/xActiveDirectory/issues/348)). ## 3.0.0.0 diff --git a/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 b/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 new file mode 100644 index 000000000..f6e52a493 --- /dev/null +++ b/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 @@ -0,0 +1,349 @@ +if ($env:APPVEYOR -eq $true) +{ + Write-Warning -Message 'Integration test is not supported in AppVeyor.' + return +} + +$script:dscModuleName = 'xActiveDirectory' +$script:dscResourceFriendlyName = 'xADDomainTrust' +$script:dscResourceName = "MSFT_$($script:dscResourceFriendlyName)" + +#region HEADER +# Integration Test Template Version: 1.3.3 +[System.String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` + (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) +{ + & git @('clone', 'https://github.com/PowerShell/DscResource.Tests.git', (Join-Path -Path $script:moduleRoot -ChildPath 'DscResource.Tests')) +} + +Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -Force +$TestEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -TestType Integration +#endregion + +try +{ + $configFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:dscResourceName).config.ps1" + . $configFile + + Describe "$($script:dscResourceName)_Integration" { + BeforeAll { + $resourceId = "[$($script:dscResourceFriendlyName)]Integration_Test" + } + + $configurationName = "$($script:dscResourceName)_CreateDomainTrust_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.Ensure | Should -Be 'Present' + $resourceCurrentState.SourceDomainName | Should -Be $configurationData.AllNodes.SourceDomain + $resourceCurrentState.TargetDomainName | Should -Be $configurationData.AllNodes.TargetDomain + $resourceCurrentState.TargetDomainAdministratorCredential.UserName | Should -Be $configurationData.AllNodes.TargetUserName + $resourceCurrentState.TrustType | Should -Be 'External' + $resourceCurrentState.TrustDirection | Should -Be 'Outbound' + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_ChangeDomainTrustDirection_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.Ensure | Should -Be 'Present' + $resourceCurrentState.SourceDomainName | Should -Be $configurationData.AllNodes.SourceDomain + $resourceCurrentState.TargetDomainName | Should -Be $configurationData.AllNodes.TargetDomain + $resourceCurrentState.TargetDomainAdministratorCredential.UserName | Should -Be $configurationData.AllNodes.TargetUserName + $resourceCurrentState.TrustType | Should -Be 'External' + $resourceCurrentState.TrustDirection | Should -Be 'Inbound' + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_RemoveDomainTrust_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.Ensure | Should -Be 'Absent' + $resourceCurrentState.SourceDomainName | Should -Be $configurationData.AllNodes.SourceDomain + $resourceCurrentState.TargetDomainName | Should -Be $configurationData.AllNodes.TargetDomain + $resourceCurrentState.TargetDomainAdministratorCredential.UserName | Should -Be $configurationData.AllNodes.TargetUserName + $resourceCurrentState.TrustType | Should -BeNullOrEmpty + $resourceCurrentState.TrustDirection | Should -BeNullOrEmpty + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_CreateForestTrust_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.Ensure | Should -Be 'Present' + $resourceCurrentState.SourceDomainName | Should -Be $configurationData.AllNodes.SourceForest + $resourceCurrentState.TargetDomainName | Should -Be $configurationData.AllNodes.TargetForest + $resourceCurrentState.TargetDomainAdministratorCredential.UserName | Should -Be $configurationData.AllNodes.TargetUserName + $resourceCurrentState.TrustType | Should -Be 'Forest' + $resourceCurrentState.TrustDirection | Should -Be 'Outbound' + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_ChangeForestTrustDirection_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.Ensure | Should -Be 'Present' + $resourceCurrentState.SourceDomainName | Should -Be $configurationData.AllNodes.SourceForest + $resourceCurrentState.TargetDomainName | Should -Be $configurationData.AllNodes.TargetForest + $resourceCurrentState.TargetDomainAdministratorCredential.UserName | Should -Be $configurationData.AllNodes.TargetUserName + $resourceCurrentState.TrustType | Should -Be 'Forest' + $resourceCurrentState.TrustDirection | Should -Be 'Inbound' + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_RemoveForestTrust_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.Ensure | Should -Be 'Absent' + $resourceCurrentState.SourceDomainName | Should -Be $configurationData.AllNodes.SourceForest + $resourceCurrentState.TargetDomainName | Should -Be $configurationData.AllNodes.TargetForest + $resourceCurrentState.TargetDomainAdministratorCredential.UserName | Should -Be $configurationData.AllNodes.TargetUserName + $resourceCurrentState.TrustType | Should -BeNullOrEmpty + $resourceCurrentState.TrustDirection | Should -BeNullOrEmpty + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + } +} +finally +{ + #region FOOTER + Restore-TestEnvironment -TestEnvironment $TestEnvironment + #endregion +} diff --git a/Tests/Integration/MSFT_xADDomainTrust.config.ps1 b/Tests/Integration/MSFT_xADDomainTrust.config.ps1 new file mode 100644 index 000000000..8bc536d22 --- /dev/null +++ b/Tests/Integration/MSFT_xADDomainTrust.config.ps1 @@ -0,0 +1,193 @@ +#region HEADER +# Integration Test Config Template Version: 1.2.0 +#endregion + +<# + .NOTES + To run this integration test there are prerequisites that need to + be setup. + + 1. One Domain Controller with forest contoso.com. + 2. One Domain Controller with forest lab.local. + 3. DNS working between the forests (conditional forwarder). + 4. Credentials with permission in the target domain (lab.local). + 5. If no certificate path is set to the environment variable + `$env:DscPublicCertificatePath` then `PSDscAllowPlainTextPassword = $true` + must be added to the ConfigurationData-block. +#> + +$configFile = [System.IO.Path]::ChangeExtension($MyInvocation.MyCommand.Path, 'json') +if (Test-Path -Path $configFile) +{ + <# + Allows reading the configuration data from a JSON file, for real testing + scenarios outside of the CI. + #> + $ConfigurationData = Get-Content -Path $configFile | ConvertFrom-Json +} +else +{ + $ConfigurationData = @{ + AllNodes = @( + @{ + NodeName = 'localhost' + CertificateFile = $env:DscPublicCertificatePath + + SourceDomain = 'contoso.com' + TargetDomain = 'lab.local' + + SourceForest = 'contoso.com' + TargetForest = 'lab.local' + + TargetUserName = "LAB\Administrator" + TargetPassword = 'P@ssw0rd1' + } + ) + } +} + +<# + .SYNOPSIS + Creates a domain trust. +#> +Configuration MSFT_xADDomainTrust_CreateDomainTrust_Config +{ + Import-DscResource -ModuleName 'xActiveDirectory' + + node $AllNodes.NodeName + { + xADDomainTrust 'Integration_Test' + { + SourceDomainName = $Node.SourceDomain + TargetDomainName = $Node.TargetDomain + TrustType = 'External' + TrustDirection = 'Outbound' + TargetDomainAdministratorCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.TargetUserName, (ConvertTo-SecureString -String $Node.TargetPassword -AsPlainText -Force)) + + } + } +} + +<# + .SYNOPSIS + Changes trust direction on an existing domain trust. +#> +Configuration MSFT_xADDomainTrust_ChangeDomainTrustDirection_Config +{ + Import-DscResource -ModuleName 'xActiveDirectory' + + node $AllNodes.NodeName + { + xADDomainTrust 'Integration_Test' + { + SourceDomainName = $Node.SourceDomain + TargetDomainName = $Node.TargetDomain + TrustType = 'External' + TrustDirection = 'Inbound' + TargetDomainAdministratorCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.TargetUserName, (ConvertTo-SecureString -String $Node.TargetPassword -AsPlainText -Force)) + + } + } +} + +<# + .SYNOPSIS + Removes the domain trust. +#> +Configuration MSFT_xADDomainTrust_RemoveDomainTrust_Config +{ + Import-DscResource -ModuleName 'xActiveDirectory' + + node $AllNodes.NodeName + { + xADDomainTrust 'Integration_Test' + { + Ensure = 'Absent' + SourceDomainName = $Node.SourceDomain + TargetDomainName = $Node.TargetDomain + TrustType = 'External' + TrustDirection = 'Bidirectional' + TargetDomainAdministratorCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.TargetUserName, (ConvertTo-SecureString -String $Node.TargetPassword -AsPlainText -Force)) + + } + } +} + +<# + .SYNOPSIS + Creates a forest trust. +#> +Configuration MSFT_xADDomainTrust_CreateForestTrust_Config +{ + Import-DscResource -ModuleName 'xActiveDirectory' + + node $AllNodes.NodeName + { + xADDomainTrust 'Integration_Test' + { + SourceDomainName = $Node.SourceForest + TargetDomainName = $Node.TargetForest + TrustType = 'Forest' + TrustDirection = 'Outbound' + TargetDomainAdministratorCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.TargetUserName, (ConvertTo-SecureString -String $Node.TargetPassword -AsPlainText -Force)) + + } + } +} + +<# + .SYNOPSIS + Changes trust direction on an existing forest trust. +#> +Configuration MSFT_xADDomainTrust_ChangeForestTrustDirection_Config +{ + Import-DscResource -ModuleName 'xActiveDirectory' + + node $AllNodes.NodeName + { + xADDomainTrust 'Integration_Test' + { + SourceDomainName = $Node.SourceForest + TargetDomainName = $Node.TargetForest + TrustType = 'Forest' + TrustDirection = 'Inbound' + TargetDomainAdministratorCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.TargetUserName, (ConvertTo-SecureString -String $Node.TargetPassword -AsPlainText -Force)) + + } + } +} + +<# + .SYNOPSIS + Removes the domain trust. +#> +Configuration MSFT_xADDomainTrust_RemoveForestTrust_Config +{ + Import-DscResource -ModuleName 'xActiveDirectory' + + node $AllNodes.NodeName + { + xADDomainTrust 'Integration_Test' + { + Ensure = 'Absent' + SourceDomainName = $Node.SourceForest + TargetDomainName = $Node.TargetForest + TrustType = 'Forest' + TrustDirection = 'Bidirectional' + TargetDomainAdministratorCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.TargetUserName, (ConvertTo-SecureString -String $Node.TargetPassword -AsPlainText -Force)) + + } + } +} From df9e01e8854894b10dc15b30a20b9063872908fd Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Thu, 11 Jul 2019 13:16:13 +0200 Subject: [PATCH 06/16] Fix review comments at r1 --- .../MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof | 6 +++--- .../en-US/about_xADDomainTrust.help.txt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof index 5055df7b1..4c7a3837e 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.schema.mof @@ -1,10 +1,10 @@ [ClassVersion("1.0.1.0"), FriendlyName("xADDomainTrust")] class MSFT_xADDomainTrust : OMI_BaseResource { - [Write, Description("Specifies whether the computer account is present or absent. Valid values are 'Present' and 'Absent'. The default is 'Present'."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Specifies whether the computer account is present or absent. Default value is 'Present'."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Required, Description("Specifies the credentials to authenticate to the target domain."), EmbeddedInstance("MSFT_Credential")] String TargetDomainAdministratorCredential; [Key, Description("Specifies the name of the Active Directory domain that is being trusted.")] String TargetDomainName; - [Required, Description("Specifies the type of trust. Valid values are 'External' or 'Forest'. 'External' means the context Domain, while 'Forest' means the context 'Forest'."), ValueMap{"External","Forest"}, Values{"External","Forest"}] String TrustType; - [Required, Description("Specifies the direction of the trust. Valid values are 'Bidirectional', 'Inbound', and 'Outbound'."), ValueMap{"Bidirectional","Inbound","Outbound"}, Values{"Bidirectional","Inbound","Outbound"}] String TrustDirection; + [Required, Description("Specifies the type of trust. The value 'External' means the context Domain, while the value 'Forest' means the context 'Forest'."), ValueMap{"External","Forest"}, Values{"External","Forest"}] String TrustType; + [Required, Description("Specifies the direction of the trust."), ValueMap{"Bidirectional","Inbound","Outbound"}, Values{"Bidirectional","Inbound","Outbound"}] String TrustDirection; [Key, Description("Specifies the name of the Active Directory domain that is requesting the trust.")] String SourceDomainName; }; diff --git a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt index 30c553d60..188cdd31b 100644 --- a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt +++ b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt @@ -2,7 +2,7 @@ xADDomainTrust .DESCRIPTION - The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains, that makes it possible for users in one domain to be authenticated by a domain controller in the other domain. + The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. That makes it possible for users in one domain to be authenticated by a domain controller in the other domain. ## Requirements @@ -11,7 +11,7 @@ .PARAMETER Ensure Write - String Allowed values: Present, Absent - Specifies whether the computer account is present or absent. Valid values are 'Present' and 'Absent'. The default is 'Present'. + Specifies whether the computer account is present or absent. Default value is 'Present'. .PARAMETER TargetDomainAdministratorCredential Required - String @@ -24,12 +24,12 @@ .PARAMETER TrustType Required - String Allowed values: External, Forest - Specifies the type of trust. Valid values are 'External' or 'Forest'. 'External' means the context Domain, while 'Forest' means the context 'Forest'. + Specifies the type of trust. The value 'External' means the context Domain, while the value 'Forest' means the context 'Forest'. .PARAMETER TrustDirection Required - String Allowed values: Bidirectional, Inbound, Outbound - Specifies the direction of the trust. Valid values are 'Bidirectional', 'Inbound', and 'Outbound'. + Specifies the direction of the trust. .PARAMETER SourceDomainName Key - String From 1154258c7819fe654615ec530bfeebc23fbba9de Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 14:35:58 +0200 Subject: [PATCH 07/16] Fix review comments at r2 --- .../MSFT_xADDomainTrust.psm1 | 214 ++++++++++-------- DSCResources/MSFT_xADDomainTrust/README.md | 2 +- .../en-US/MSFT_xADDomainTrust.strings.psd1 | 2 +- .../en-US/about_xADDomainTrust.help.txt | 6 +- .../xActiveDirectory.Common.psm1 | 2 +- .../MSFT_xADDomainTrust.Integration.Tests.ps1 | 12 +- .../MSFT_xADDomainTrust.config.ps1 | 1 + Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 | 117 +++++++--- Tests/Unit/xActiveDirectory.Common.Tests.ps1 | 2 +- 9 files changed, 218 insertions(+), 140 deletions(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index 4a9c2480c..512ba238d 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -18,16 +18,14 @@ $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_xADDomainTrust' Specifies the name of the Active Directory domain that is being trusted. .PARAMETER TargetDomainAdministratorCredential - Specifies the credentials to authenticate to the target domain.. + Specifies the credentials to authenticate to the target domain. .PARAMETER TrustType - Specifies the type of trust. Valid values are 'External' or 'Forest'. - 'External' means the context Domain, while 'Forest' means the context - 'Forest'. + Specifies the type of trust. The value 'External' means the context Domain, + while the value 'Forest' means the context 'Forest'. .PARAMETER TrustDirection - Specifies the direction of the trust. Valid values are 'Bidirectional', - 'Inbound', and 'Outbound'. + Specifies the direction of the trust. #> function Get-TargetResource { @@ -67,41 +65,20 @@ function Get-TargetResource TargetDomainAdministratorCredential = $cimCredentialInstance } - $directoryContextType = ConvertTo-DirectoryContextType -TrustType $TrustType - - # Create the target object. - $newADDirectoryContextParameters = @{ - DirectoryContextType = $directoryContextType - Name = $TargetDomainName - Credential = $TargetDomainAdministratorCredential - } - - $targetDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters - - # Create the source object. - $newADDirectoryContextParameters = @{ - DirectoryContextType = $directoryContextType - Name = $SourceDomainName + $getTrustTargetAndSourceObject = @{ + SourceDomainName = $SourceDomainName + TargetDomainName = $TargetDomainName + TargetDomainAdministratorCredential = $TargetDomainAdministratorCredential + TrustType = $TrustType } - $sourceDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters - - if ($directoryContextType -eq 'Domain') - { - $trustSource = Get-ActiveDirectoryDomain -DirectoryContext $sourceDirectoryContext - $trustTarget = Get-ActiveDirectoryDomain -DirectoryContext $targetDirectoryContext - } - else - { - $trustSource = Get-ActiveDirectoryForest -DirectoryContext $sourceDirectoryContext - $trustTarget = Get-ActiveDirectoryForest -DirectoryContext $targetDirectoryContext - } + $trustSource, $trustTarget = Get-TrustTargetAndSourceObject @getTrustTargetAndSourceObject try { # Find trust between source & destination. Write-Verbose -Message ( - $script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName, $directoryContextType + $script:localizedData.CheckingTrustMessage -f $SourceDomainName, $TargetDomainName, $directoryContextTyp ) $trust = $trustSource.GetTrustRelationship($trustTarget) @@ -138,20 +115,18 @@ function Get-TargetResource Specifies the name of the Active Directory domain that is being trusted. .PARAMETER TargetDomainAdministratorCredential - Specifies the credentials to authenticate to the target domain.. + Specifies the credentials to authenticate to the target domain. .PARAMETER TrustType - Specifies the type of trust. Valid values are 'External' or 'Forest'. - 'External' means the context Domain, while 'Forest' means the context - 'Forest'. + Specifies the type of trust. The value 'External' means the context Domain, + while the value 'Forest' means the context 'Forest'. .PARAMETER TrustDirection - Specifies the direction of the trust. Valid values are 'Bidirectional', - 'Inbound', and 'Outbound'. + Specifies the direction of the trust. .PARAMETER Ensure - Specifies whether the computer account is present or absent. Valid values - are 'Present' and 'Absent'. The default is 'Present'. + Specifies whether the computer account is present or absent. Default + value is 'Present'. #> function Set-TargetResource { @@ -186,43 +161,22 @@ function Set-TargetResource $Ensure = 'Present' ) - $directoryContextType = ConvertTo-DirectoryContextType -TrustType $TrustType - - # Create the target object. - $newADDirectoryContextParameters = @{ - DirectoryContextType = $directoryContextType - Name = $TargetDomainName - Credential = $TargetDomainAdministratorCredential - } - - $targetDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters - - # Create the source object. - $newADDirectoryContextParameters = @{ - DirectoryContextType = $directoryContextType - Name = $SourceDomainName + $getTrustTargetAndSourceObject = @{ + SourceDomainName = $SourceDomainName + TargetDomainName = $TargetDomainName + TargetDomainAdministratorCredential = $TargetDomainAdministratorCredential + TrustType = $TrustType } - $sourceDirectoryContext = Get-ADDirectoryContext @newADDirectoryContextParameters - - if ($directoryContextType -eq 'Domain') - { - $trustSource = Get-ActiveDirectoryDomain -DirectoryContext $sourceDirectoryContext - $trustTarget = Get-ActiveDirectoryDomain -DirectoryContext $targetDirectoryContext - } - else - { - $trustSource = Get-ActiveDirectoryForest -DirectoryContext $sourceDirectoryContext - $trustTarget = Get-ActiveDirectoryForest -DirectoryContext $targetDirectoryContext - } + $trustSource, $trustTarget = Get-TrustTargetAndSourceObject @getTrustTargetAndSourceObject $compareTargetResourceStateResult = Compare-TargetResourceState @PSBoundParameters # Get all properties that are not in desired state. $propertiesNotInDesiredState = $compareTargetResourceStateResult | - Where-Object -FilterScript { - -not $_.InDesiredState - } + Where-Object -FilterScript { + -not $_.InDesiredState + } if ($propertiesNotInDesiredState.Where({ $_.ParameterName -eq 'Ensure' })) { @@ -264,6 +218,7 @@ function Set-TargetResource # Check properties. $trustTypeProperty = $propertiesNotInDesiredState.Where({ $_.ParameterName -eq 'TrustType' }) + if ($trustTypeProperty) { Write-Verbose -Message ( @@ -292,7 +247,7 @@ function Set-TargetResource <# In case the trust direction property should be wrong, there - are no need to update that property twice since it was set + is no need to update that property twice since it was set to the correct value when the trust was recreated. #> if (-not $trustRecreated) @@ -330,20 +285,18 @@ function Set-TargetResource Specifies the name of the Active Directory domain that is being trusted. .PARAMETER TargetDomainAdministratorCredential - Specifies the credentials to authenticate to the target domain.. + Specifies the credentials to authenticate to the target domain. .PARAMETER TrustType - Specifies the type of trust. Valid values are 'External' or 'Forest'. - 'External' means the context Domain, while 'Forest' means the context - 'Forest'. + Specifies the type of trust. The value 'External' means the context Domain, + while the value 'Forest' means the context 'Forest'. .PARAMETER TrustDirection - Specifies the direction of the trust. Valid values are 'Bidirectional', - 'Inbound', and 'Outbound'. + Specifies the direction of the trust. .PARAMETER Ensure - Specifies whether the computer account is present or absent. Valid values - are 'Present' and 'Absent'. The default is 'Present'. + Specifies whether the computer account is present or absent. Default + value is 'Present'. #> function Test-TargetResource { @@ -418,20 +371,18 @@ function Test-TargetResource Specifies the name of the Active Directory domain that is being trusted. .PARAMETER TargetDomainAdministratorCredential - Specifies the credentials to authenticate to the target domain.. + Specifies the credentials to authenticate to the target domain. .PARAMETER TrustType - Specifies the type of trust. Valid values are 'External' or 'Forest'. - 'External' means the context Domain, while 'Forest' means the context - 'Forest'. + Specifies the type of trust. The value 'External' means the context Domain, + while the value 'Forest' means the context 'Forest'. .PARAMETER TrustDirection - Specifies the direction of the trust. Valid values are 'Bidirectional', - 'Inbound', and 'Outbound'. + Specifies the direction of the trust. .PARAMETER Ensure - Specifies whether the computer account is present or absent. Valid values - are 'Present' and 'Absent'. The default is 'Present'. + Specifies whether the computer account is present or absent. Default + value is 'Present'. #> function Compare-TargetResourceState { @@ -498,20 +449,20 @@ function Compare-TargetResourceState <# If the user did not specify Ensure property, then it is not part of - the $PSBoundParameters, but it still need to be compared. + the $PSBoundParameters, but it still needs to be compared. Copy the hashtable $PSBoundParameters and add 'Ensure' property to make sure it is part of the DesiredValues. #> $desiredValues = @{ } + $PSBoundParameters $desiredValues['Ensure'] = $Ensure - $compareTargetResourceStateParameters = @{ + $compareResourcePropertyStateParameters = @{ CurrentValues = $getTargetResourceResult DesiredValues = $desiredValues Properties = $propertiesToEvaluate } - return Compare-ResourcePropertyState @compareTargetResourceStateParameters + return Compare-ResourcePropertyState @compareResourcePropertyStateParameters } <# @@ -525,7 +476,7 @@ function Compare-TargetResourceState this parameter. .NOTES - This is a wrapper for enable unit testing of this resource. + This is a wrapper to enable unit testing of this resource. see issue https://github.com/PowerShell/xActiveDirectory/issues/324 for more information. #> @@ -554,7 +505,7 @@ function Get-ActiveDirectoryDomain this parameter. .NOTES - This is a wrapper for enable unit testing of this resource. + This is a wrapper to enable unit testing of this resource. see issue https://github.com/PowerShell/xActiveDirectory/issues/324 for more information. #> @@ -638,4 +589,79 @@ function ConvertFrom-DirectoryContextType return $trustType } +<# + .SYNOPSIS + Compares the properties in the current state with the properties of the + desired state and returns a hashtable with the comaprison result. + + .PARAMETER SourceDomainName + Specifies the name of the Active Directory domain that is requesting the + trust. + + .PARAMETER TargetDomainName + Specifies the name of the Active Directory domain that is being trusted. + + .PARAMETER TargetDomainAdministratorCredential + Specifies the credentials to authenticate to the target domain. + + .PARAMETER TrustType + Specifies the type of trust. The value 'External' means the context Domain, + while the value 'Forest' means the context 'Forest'. +#> +function Get-TrustTargetAndSourceObject +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SourceDomainName, + + [Parameter(Mandatory = $true)] + [System.String] + $TargetDomainName, + + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $TargetDomainAdministratorCredential, + + [Parameter(Mandatory = $true)] + [ValidateSet('External', 'Forest')] + [System.String] + $TrustType + ) + + $directoryContextType = ConvertTo-DirectoryContextType -TrustType $TrustType + + # Create the target object. + $getADDirectoryContextParameters = @{ + DirectoryContextType = $directoryContextType + Name = $TargetDomainName + Credential = $TargetDomainAdministratorCredential + } + + $targetDirectoryContext = Get-ADDirectoryContext @getADDirectoryContextParameters + + # Create the source object. + $getADDirectoryContextParameters = @{ + DirectoryContextType = $directoryContextType + Name = $SourceDomainName + } + + $sourceDirectoryContext = Get-ADDirectoryContext @getADDirectoryContextParameters + + if ($directoryContextType -eq 'Domain') + { + $trustSource = Get-ActiveDirectoryDomain -DirectoryContext $sourceDirectoryContext + $trustTarget = Get-ActiveDirectoryDomain -DirectoryContext $targetDirectoryContext + } + else + { + $trustSource = Get-ActiveDirectoryForest -DirectoryContext $sourceDirectoryContext + $trustTarget = Get-ActiveDirectoryForest -DirectoryContext $targetDirectoryContext + } + + return $trustSource, $trustTarget +} + Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xADDomainTrust/README.md b/DSCResources/MSFT_xADDomainTrust/README.md index 260b0db36..744487b31 100644 --- a/DSCResources/MSFT_xADDomainTrust/README.md +++ b/DSCResources/MSFT_xADDomainTrust/README.md @@ -1,6 +1,6 @@ # Description -The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. That makes it possible for users in one domain to be authenticated by a domain controller in the other domain. +The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. To understand more about trusts in Active Directory, please see the article [Forest Design Models](https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/plan/forest-design-models) for more information. ## Requirements diff --git a/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 b/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 index 779f9fd86..95360d27c 100644 --- a/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 +++ b/DSCResources/MSFT_xADDomainTrust/en-US/MSFT_xADDomainTrust.strings.psd1 @@ -1,6 +1,6 @@ # culture="en-US" ConvertFrom-StringData @' -CheckingTrustMessage = Determining if the trust between the '{0}' and the '{1}' with the context type '{2}' exists. (ADDT0001) +CheckingTrustMessage = Determining if the trust between domains '{0}' and '{1}' with the context type '{2}' exists. (ADDT0001) RemovedTrust = Trust between between domains '{0}' and '{1}' with the context type '{2}' has been removed. (ADDT0002) AddedTrust = Created the trust between domains '{0}' and '{1}' with the context type '{2}' and direction '{3}'. (ADDT0003) SetTrustDirection = The trust direction has been changed to '{0}'. (ADDT0004) diff --git a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt index 188cdd31b..0de88f669 100644 --- a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt +++ b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. That makes it possible for users in one domain to be authenticated by a domain controller in the other domain. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Ensure Write - String Allowed values: Present, Absent diff --git a/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 b/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 index bb87d25af..fe59db8d2 100644 --- a/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 +++ b/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 @@ -1881,7 +1881,7 @@ function Add-TypeAssembly 'ApplicationPartition', 'ConfigurationSet' or 'DirectoryServer'. .PARAMETER Name - An optional parameter for the target of the directory context. + An optional parameter for the target of the directory context. For the correct format for this parameter depending on context type, see the article https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectory.directorycontext?view=netframework-4.8 #> diff --git a/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 b/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 index f6e52a493..9652e98ce 100644 --- a/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 +++ b/Tests/Integration/MSFT_xADDomainTrust.Integration.Tests.ps1 @@ -81,7 +81,7 @@ try } It 'Should return $true when Test-DscConfiguration is run' { - Test-DscConfiguration -Verbose | Should -Be 'True' + Test-DscConfiguration -Verbose | Should -BeTrue } } @@ -132,7 +132,7 @@ try } It 'Should return $true when Test-DscConfiguration is run' { - Test-DscConfiguration -Verbose | Should -Be 'True' + Test-DscConfiguration -Verbose | Should -BeTrue } } @@ -183,7 +183,7 @@ try } It 'Should return $true when Test-DscConfiguration is run' { - Test-DscConfiguration -Verbose | Should -Be 'True' + Test-DscConfiguration -Verbose | Should -BeTrue } } @@ -234,7 +234,7 @@ try } It 'Should return $true when Test-DscConfiguration is run' { - Test-DscConfiguration -Verbose | Should -Be 'True' + Test-DscConfiguration -Verbose | Should -BeTrue } } @@ -285,7 +285,7 @@ try } It 'Should return $true when Test-DscConfiguration is run' { - Test-DscConfiguration -Verbose | Should -Be 'True' + Test-DscConfiguration -Verbose | Should -BeTrue } } @@ -336,7 +336,7 @@ try } It 'Should return $true when Test-DscConfiguration is run' { - Test-DscConfiguration -Verbose | Should -Be 'True' + Test-DscConfiguration -Verbose | Should -BeTrue } } } diff --git a/Tests/Integration/MSFT_xADDomainTrust.config.ps1 b/Tests/Integration/MSFT_xADDomainTrust.config.ps1 index 8bc536d22..ae248df21 100644 --- a/Tests/Integration/MSFT_xADDomainTrust.config.ps1 +++ b/Tests/Integration/MSFT_xADDomainTrust.config.ps1 @@ -17,6 +17,7 @@ #> $configFile = [System.IO.Path]::ChangeExtension($MyInvocation.MyCommand.Path, 'json') + if (Test-Path -Path $configFile) { <# diff --git a/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 b/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 index ce8977633..14aaab9dc 100644 --- a/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 +++ b/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 @@ -50,11 +50,6 @@ try Describe 'MSFT_xADDomainTrust\Get-TargetResource' -Tag 'Get' { BeforeAll { - Mock -CommandName Get-ADDirectoryContext -MockWith { - # This should work on any client, domain joined or not. - return [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new('Domain') - } - $mockDefaultParameters = @{ SourceDomainName = $mockSourceDomainName TargetDomainName = $mockTargetDomainName @@ -68,8 +63,8 @@ try Context 'When the domain trust is present in Active Directory' { Context 'When the called with the TrustType ''External''' { BeforeAll { - Mock -CommandName Get-ActiveDirectoryDomain -MockWith { - return New-Object -TypeName Object | + Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { $script:getTrustRelationshipMethodCallCount += 1 @@ -78,6 +73,10 @@ try TrustDirection = 'Outbound' } } -PassThru -Force + + $mockTrustTarget = New-Object -TypeName Object + + return $mockTrustSource, $mockTrustTarget } } @@ -91,7 +90,7 @@ try AfterEach { $script:getTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } It 'Should return the state as present' { @@ -115,8 +114,8 @@ try Context 'When the called with the TrustType ''Forest''' { BeforeAll { - Mock -CommandName Get-ActiveDirectoryForest -MockWith { - return New-Object -TypeName Object | + Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { $script:getTrustRelationshipMethodCallCount += 1 @@ -125,6 +124,10 @@ try TrustDirection = 'Outbound' } } -PassThru -Force + + $mockTrustTarget = New-Object -TypeName Object + + return $mockTrustSource, $mockTrustTarget } } @@ -138,7 +141,7 @@ try AfterEach { $script:getTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } It 'Should return the state as present' { @@ -163,13 +166,17 @@ try Context 'When the domain trust is absent from Active Directory' { BeforeAll { - Mock -CommandName Get-ActiveDirectoryForest -MockWith { - return New-Object -TypeName Object | + Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { - $script:GetTrustRelationshipMethodCallCount += 1 + $script:getTrustRelationshipMethodCallCount += 1 throw } -PassThru -Force + + $mockTrustTarget = New-Object -TypeName Object + + return $mockTrustSource, $mockTrustTarget } } @@ -183,7 +190,7 @@ try AfterEach { $script:getTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } It 'Should return the state as absent' { @@ -559,13 +566,8 @@ try Describe 'MSFT_xADDomainTrust\Set-TargetResource' -Tag 'Set' { BeforeAll { - Mock -CommandName Get-ADDirectoryContext -MockWith { - # This should work on any client, domain joined or not. - return [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new('Domain') - } - - $mockGetActiveDirectoryDomainOrForest = { - return New-Object -TypeName Object | + Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'CreateTrustRelationship' -Value { $script:createTrustRelationshipMethodCallCount += 1 } -PassThru | @@ -575,12 +577,13 @@ try Add-Member -MemberType ScriptMethod -Name 'UpdateTrustRelationship' -Value { $script:updateTrustRelationshipMethodCallCount += 1 } -PassThru -Force - } - Mock -CommandName Get-ActiveDirectoryDomain -MockWith $mockGetActiveDirectoryDomainOrForest - Mock -CommandName Get-ActiveDirectoryForest -MockWith $mockGetActiveDirectoryDomainOrForest + $mockTrustTarget = New-Object -TypeName Object - $mockDefaultParameters = @{ + return $mockTrustSource, $mockTrustTarget + } + + $mockDefaultParameters = @{ SourceDomainName = $mockSourceDomainName TargetDomainName = $mockTargetDomainName TargetDomainAdministratorCredential = $mockCredential @@ -627,7 +630,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } @@ -667,7 +670,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } } @@ -702,7 +705,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } } @@ -745,7 +748,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } @@ -786,7 +789,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 1 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } @@ -834,7 +837,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 1 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } @@ -881,7 +884,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It } } } @@ -930,6 +933,54 @@ try $convertFromDirectoryContextTypeResult | Should -Be $TrustTypeValue } } + + Describe 'MSFT_xADDomainTrust\Get-TrustTargetAndSourceObject' -Tag 'Helper' { + BeforeAll { + Mock -CommandName Get-ADDirectoryContext -MockWith { + # This should work on any client, domain joined or not. + return [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new('Domain') + } + + Mock -CommandName Get-ActiveDirectoryDomain + Mock -CommandName Get-ActiveDirectoryForest + + $testCases = @( + @{ + TrustType = 'External' + }, + @{ + TrustType = 'Forest' + } + ) + } + + It 'Should not throw and call the correct mocks when called with the trust type value ''''' -TestCases $testCases { + param + ( + [Parameter()] + $TrustType + ) + + $testParameters = @{ + SourceDomainName = $mockSourceDomainName + TargetDomainName = $mockTargetDomainName + TargetDomainAdministratorCredential = $mockCredential + TrustType = $TrustType + Verbose = $true + } + + { Get-TrustTargetAndSourceObject @testParameters } | Should -Not -Throw + + if ($TrustType -eq 'External') + { + Assert-MockCalled -CommandName Get-ActiveDirectoryDomain -Exactly -Times 2 -Scope It + } + else + { + Assert-MockCalled -CommandName Get-ActiveDirectoryForest -Exactly -Times 2 -Scope It + } + } + } } } finally diff --git a/Tests/Unit/xActiveDirectory.Common.Tests.ps1 b/Tests/Unit/xActiveDirectory.Common.Tests.ps1 index 5384fec1c..6d82bb66e 100644 --- a/Tests/Unit/xActiveDirectory.Common.Tests.ps1 +++ b/Tests/Unit/xActiveDirectory.Common.Tests.ps1 @@ -2134,7 +2134,7 @@ InModuleScope 'xActiveDirectory.Common' { } } - Describe 'xActiveDirectory.CommonNew-CimCredentialInstance' { + Describe 'xActiveDirectory.Common\New-CimCredentialInstance' { Context 'When creating a new MSFT_Credential CIM instance credential object' { BeforeAll { $mockAdministratorUser = 'admin@contoso.com' From b1a9edef201bc852b4f97b23127174d10acb67dd Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 14:40:13 +0200 Subject: [PATCH 08/16] Update synopsis on newvhelper function --- .../MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index 512ba238d..a7a3cdf72 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -361,7 +361,7 @@ function Test-TargetResource <# .SYNOPSIS Compares the properties in the current state with the properties of the - desired state and returns a hashtable with the comaprison result. + desired state and returns a hashtable with the comparison result. .PARAMETER SourceDomainName Specifies the name of the Active Directory domain that is requesting the @@ -591,8 +591,11 @@ function ConvertFrom-DirectoryContextType <# .SYNOPSIS - Compares the properties in the current state with the properties of the - desired state and returns a hashtable with the comaprison result. + Returns two objects where the first object is for the source domain and + the second object is for the target domain. The type returned is either + System.DirectoryServices.ActiveDirectory.Domain or + System.DirectoryServices.ActiveDirectory.Forest for both objects + (always returns the same type for both objects). .PARAMETER SourceDomainName Specifies the name of the Active Directory domain that is requesting the From f5102026181368c238b7c56404d441cee34d4295 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 14:45:01 +0200 Subject: [PATCH 09/16] Remove missed blank row --- DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index a7a3cdf72..63ba49697 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -193,7 +193,6 @@ function Set-TargetResource $TrustDirection ) ) - } else { From c7b0f1b7eea6bd98ef5cad2eec4bf1aa4d1c6f67 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 15:32:32 +0200 Subject: [PATCH 10/16] Fix whitespace in all *.help.txt --- .../MSFT_xADComputer/en-US/about_xADComputer.help.txt | 8 ++++---- .../MSFT_xADDomain/en-US/about_xADDomain.help.txt | 6 +++--- .../en-US/about_xADDomainController.help.txt | 8 ++++---- .../en-US/about_xADDomainDefaultPasswordPolicy.help.txt | 6 +++--- .../en-US/about_xADDomainTrust.help.txt | 2 +- .../en-US/about_xADForestProperties.help.txt | 6 +++--- DSCResources/MSFT_xADGroup/en-US/about_xADGroup.help.txt | 6 +++--- .../MSFT_xADKDSKey/en-US/about_xADKDSKey.help.txt | 6 +++--- .../en-US/about_xADManagedServiceAccount.help.txt | 6 +++--- .../en-US/about_xADObjectEnabledState.help.txt | 8 ++++---- .../en-US/about_xADObjectPermissionEntry.help.txt | 6 +++--- .../en-US/about_xADOrganizationalUnit.help.txt | 6 +++--- .../MSFT_xADRecycleBin/en-US/about_xADRecycleBin.help.txt | 6 +++--- .../en-US/about_xADReplicationSite.help.txt | 6 +++--- .../en-US/about_xADReplicationSiteLink.help.txt | 6 +++--- .../en-US/about_xADReplicationSubnet.help.txt | 6 +++--- .../en-US/about_xADServicePrincipalName.help.txt | 6 +++--- DSCResources/MSFT_xADUser/en-US/about_xADUser.help.txt | 6 +++--- .../en-US/about_xWaitForADDomain.help.txt | 6 +++--- 19 files changed, 58 insertions(+), 58 deletions(-) diff --git a/DSCResources/MSFT_xADComputer/en-US/about_xADComputer.help.txt b/DSCResources/MSFT_xADComputer/en-US/about_xADComputer.help.txt index 2b62f1fba..04e838474 100644 --- a/DSCResources/MSFT_xADComputer/en-US/about_xADComputer.help.txt +++ b/DSCResources/MSFT_xADComputer/en-US/about_xADComputer.help.txt @@ -6,17 +6,17 @@ This resource can be used to provision a computer account before the computer is added to the domain. These pre-created computer objects can be used with offline domain join, unsecure domain Join and RODC domain join scenarios. - + >**Note:** An Offline Domain Join (ODJ) request file will only be created >when a computer account is first created in the domain. Setting an Offline >Domain Join (ODJ) Request file path for a configuration that updates a >computer account that already exists, or restore it from the recycle bin >will not cause the Offline Domain Join (ODJ) request file to be created. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER ComputerName Key - String Specifies the name of the Active Directory computer account to manage. You can identify a computer by its distinguished name, GUID, security identifier (SID) or Security Accounts Manager (SAM) account name. diff --git a/DSCResources/MSFT_xADDomain/en-US/about_xADDomain.help.txt b/DSCResources/MSFT_xADDomain/en-US/about_xADDomain.help.txt index 3a2ee02ca..704cc5962 100644 --- a/DSCResources/MSFT_xADDomain/en-US/about_xADDomain.help.txt +++ b/DSCResources/MSFT_xADDomain/en-US/about_xADDomain.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADDomain resource creates a new domain in a new forest or a child domain in an existing forest. While it is possible to set the forest functional level and the domain functional level during deployment with this resource the common restrictions apply. For more information see [TechNet](https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/active-directory-functional-levels). - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER DomainName Key - String The fully qualified domain name (FQDN) of the new domain. diff --git a/DSCResources/MSFT_xADDomainController/en-US/about_xADDomainController.help.txt b/DSCResources/MSFT_xADDomainController/en-US/about_xADDomainController.help.txt index 5f2714fe3..4b5f4a8f9 100644 --- a/DSCResources/MSFT_xADDomainController/en-US/about_xADDomainController.help.txt +++ b/DSCResources/MSFT_xADDomainController/en-US/about_xADDomainController.help.txt @@ -4,7 +4,7 @@ .DESCRIPTION The xADDomainController DSC resource will install and configure domain controllers in Active Directory. - + >**Note:** If the account used for the parameter `DomainAdministratorCredential` >cannot connect to another domain controller, for example using a credential >without the domain name, then the cmdlet `Install-ADDSDomainController` will @@ -12,11 +12,11 @@ >information from another domain controller. >Make sure to use a correct domain account with the correct permission as >the account for the parameter `DomainAdministratorCredential`. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER DomainName Key - String The fully qualified domain name (FQDN) of the domain the Domain Controller will be joining. diff --git a/DSCResources/MSFT_xADDomainDefaultPasswordPolicy/en-US/about_xADDomainDefaultPasswordPolicy.help.txt b/DSCResources/MSFT_xADDomainDefaultPasswordPolicy/en-US/about_xADDomainDefaultPasswordPolicy.help.txt index fcbd513a1..4c110cc33 100644 --- a/DSCResources/MSFT_xADDomainDefaultPasswordPolicy/en-US/about_xADDomainDefaultPasswordPolicy.help.txt +++ b/DSCResources/MSFT_xADDomainDefaultPasswordPolicy/en-US/about_xADDomainDefaultPasswordPolicy.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADDomainDefaultPasswordPolicy DSC resource will manage an Active Directory domain's default password policy. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER DomainName Key - String Name of the domain to which the password policy will be applied. diff --git a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt index 0de88f669..8353b6a53 100644 --- a/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt +++ b/DSCResources/MSFT_xADDomainTrust/en-US/about_xADDomainTrust.help.txt @@ -2,7 +2,7 @@ xADDomainTrust .DESCRIPTION - The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. That makes it possible for users in one domain to be authenticated by a domain controller in the other domain. + The xADDomainTrust DSC resource will manage Domain Trusts within Active Directory. A trust is a relationship, which you establish between domains or forests. To understand more about trusts in Active Directory, please see the article [Forest Design Models](https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/plan/forest-design-models) for more information. ## Requirements diff --git a/DSCResources/MSFT_xADForestProperties/en-US/about_xADForestProperties.help.txt b/DSCResources/MSFT_xADForestProperties/en-US/about_xADForestProperties.help.txt index bea4b35f8..44390a3c9 100644 --- a/DSCResources/MSFT_xADForestProperties/en-US/about_xADForestProperties.help.txt +++ b/DSCResources/MSFT_xADForestProperties/en-US/about_xADForestProperties.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADForestProperties DSC resource will manage User Principal Name (UPN) suffixes and Service Principal Name (SPN) suffixes in a forest. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Credential Write - String Specifies the user account credentials to use to perform this task. diff --git a/DSCResources/MSFT_xADGroup/en-US/about_xADGroup.help.txt b/DSCResources/MSFT_xADGroup/en-US/about_xADGroup.help.txt index 1ea60eb6e..a3bf01c89 100644 --- a/DSCResources/MSFT_xADGroup/en-US/about_xADGroup.help.txt +++ b/DSCResources/MSFT_xADGroup/en-US/about_xADGroup.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADGroup DSC resource will manage groups within Active Directory. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER GroupName Key - String Name of the Active Directory group. diff --git a/DSCResources/MSFT_xADKDSKey/en-US/about_xADKDSKey.help.txt b/DSCResources/MSFT_xADKDSKey/en-US/about_xADKDSKey.help.txt index 4c887ef16..4dd5721f3 100644 --- a/DSCResources/MSFT_xADKDSKey/en-US/about_xADKDSKey.help.txt +++ b/DSCResources/MSFT_xADKDSKey/en-US/about_xADKDSKey.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADKDSKey DSC resource will manage KDS Root Keys within Active Directory. The KDS root keys are used to begin generating Group Managed Service Account (gMSA) passwords. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER EffectiveTime Key - String Specifies the Effective time when a KDS root key can be used. There is a 10 hour minimum from creation date to allow active directory to properly replicate across all domain controllers. For this reason, the date must be set in the future for creation. While this parameter accepts a string, it will be converted into a DateTime object. This will also try to take into account cultural settings. Example: '05/01/1999 13:00 using default or 'en-US' culture would be May 1st, but using 'de-DE' culture would be 5th of January. The culture is automatically pulled from the operating system and this can be checked using 'Get-Culture'. diff --git a/DSCResources/MSFT_xADManagedServiceAccount/en-US/about_xADManagedServiceAccount.help.txt b/DSCResources/MSFT_xADManagedServiceAccount/en-US/about_xADManagedServiceAccount.help.txt index 663494974..a451495cb 100644 --- a/DSCResources/MSFT_xADManagedServiceAccount/en-US/about_xADManagedServiceAccount.help.txt +++ b/DSCResources/MSFT_xADManagedServiceAccount/en-US/about_xADManagedServiceAccount.help.txt @@ -4,12 +4,12 @@ .DESCRIPTION The xADManagedServiceAccount DSC resource will manage Single and Group Managed Service Accounts (MSAs) within Active Directory. A Managed Service Account is a managed domain account that provides automatic password management, simplified service principal name (SPN) management and the ability to delegate management to other administrators. A Single Managed Service Account can only be used on a single computer, whereas a Group Managed Service Account can be shared across multiple computers. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. * Group Managed Service Accounts need at least one Windows Server 2012 Domain Controller. - + .PARAMETER ServiceAccountName Key - String Specifies the Security Account Manager (SAM) account name of the managed service account (ldapDisplayName 'sAMAccountName'). To be compatible with older operating systems, create a SAM account name that is 20 characters or less. Once created, the user's SamAccountName and CN cannot be changed. diff --git a/DSCResources/MSFT_xADObjectEnabledState/en-US/about_xADObjectEnabledState.help.txt b/DSCResources/MSFT_xADObjectEnabledState/en-US/about_xADObjectEnabledState.help.txt index 5773b0adf..6bf4eb98d 100644 --- a/DSCResources/MSFT_xADObjectEnabledState/en-US/about_xADObjectEnabledState.help.txt +++ b/DSCResources/MSFT_xADObjectEnabledState/en-US/about_xADObjectEnabledState.help.txt @@ -3,7 +3,7 @@ .DESCRIPTION This resource enforces the property `Enabled` on the object class *Computer*. - + >This resource could support other object classes like *msDS-ManagedServiceAccount*, >*msDS-GroupManagedServiceAccount*, and *User*. But these object classes >are not yet supported due to that other resources already enforces the @@ -11,11 +11,11 @@ >then it should be made so that only one resource enforces the enabled >property. This is to prevent a potential "ping-pong" behavior if both >resource would be used in a configuration. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Identity Key - String Specifies the identity of an object that has the object class specified in the parameter ObjectClass. When ObjectClass is set to 'Computer' then this property can be set to either distinguished name, GUID (objectGUID), security identifier (objectSid), or security Accounts Manager account name (sAMAccountName). diff --git a/DSCResources/MSFT_xADObjectPermissionEntry/en-US/about_xADObjectPermissionEntry.help.txt b/DSCResources/MSFT_xADObjectPermissionEntry/en-US/about_xADObjectPermissionEntry.help.txt index dc70cfdf7..412365e51 100644 --- a/DSCResources/MSFT_xADObjectPermissionEntry/en-US/about_xADObjectPermissionEntry.help.txt +++ b/DSCResources/MSFT_xADObjectPermissionEntry/en-US/about_xADObjectPermissionEntry.help.txt @@ -6,11 +6,11 @@ designed to to manage just one entry in the list of permissios (ACL) for one AD object. It will only interact with the one permission and leave all others as they were. The resource can be used multiple times to add multiple entries into one ACL. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Ensure Write - String Allowed values: Present, Absent diff --git a/DSCResources/MSFT_xADOrganizationalUnit/en-US/about_xADOrganizationalUnit.help.txt b/DSCResources/MSFT_xADOrganizationalUnit/en-US/about_xADOrganizationalUnit.help.txt index f419680f9..d0919de37 100644 --- a/DSCResources/MSFT_xADOrganizationalUnit/en-US/about_xADOrganizationalUnit.help.txt +++ b/DSCResources/MSFT_xADOrganizationalUnit/en-US/about_xADOrganizationalUnit.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADOrganizational Unit DSC resource will manage Organizational Units (OUs) within Active Directory. An OU is a subdivision within an Active Directory into which you can place users, groups, computers, and other organizational units. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Name Key - String The name of Organization Unit (OU). diff --git a/DSCResources/MSFT_xADRecycleBin/en-US/about_xADRecycleBin.help.txt b/DSCResources/MSFT_xADRecycleBin/en-US/about_xADRecycleBin.help.txt index 11afb88bd..506cb98ed 100644 --- a/DSCResources/MSFT_xADRecycleBin/en-US/about_xADRecycleBin.help.txt +++ b/DSCResources/MSFT_xADRecycleBin/en-US/about_xADRecycleBin.help.txt @@ -6,11 +6,11 @@ This resource first verifies that the forest mode is Windows Server 2008 R2 or greater. If the forest mode is insufficient, then the resource will exit with an error message. The change is executed against the Domain Naming Master FSMO of the forest. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER ForestFQDN Key - String The fully qualified domain name (FQDN) of the forest in which to change the Recycle Bin feature. diff --git a/DSCResources/MSFT_xADReplicationSite/en-US/about_xADReplicationSite.help.txt b/DSCResources/MSFT_xADReplicationSite/en-US/about_xADReplicationSite.help.txt index 5edd66a7d..11bf6efd7 100644 --- a/DSCResources/MSFT_xADReplicationSite/en-US/about_xADReplicationSite.help.txt +++ b/DSCResources/MSFT_xADReplicationSite/en-US/about_xADReplicationSite.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADReplicationSite DSC resource will manage Replication Sites within Active Directory. Sites are used in Active Directory to either enable clients to discover network resources (published shares, domain controllers) close to the physical location of a client computer or to reduce network traffic over wide area network (WAN) links. Sites can also be used to optimize replication between domain controllers. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Ensure Write - String Allowed values: Present, Absent diff --git a/DSCResources/MSFT_xADReplicationSiteLink/en-US/about_xADReplicationSiteLink.help.txt b/DSCResources/MSFT_xADReplicationSiteLink/en-US/about_xADReplicationSiteLink.help.txt index fe47d6965..711c939a6 100644 --- a/DSCResources/MSFT_xADReplicationSiteLink/en-US/about_xADReplicationSiteLink.help.txt +++ b/DSCResources/MSFT_xADReplicationSiteLink/en-US/about_xADReplicationSiteLink.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADReplicationSiteLink DSC resource will manage Replication Site Links within Active Directory. A site link connects two or more sites. Site links reflect the administrative policy for how sites are to be interconnected and the methods used to transfer replication traffic. You must connect sites with site links so that domain controllers at each site can replicate Active Directory changes. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Name Key - String Specifies the name of the site link. diff --git a/DSCResources/MSFT_xADReplicationSubnet/en-US/about_xADReplicationSubnet.help.txt b/DSCResources/MSFT_xADReplicationSubnet/en-US/about_xADReplicationSubnet.help.txt index ab3121313..8fc5dbf05 100644 --- a/DSCResources/MSFT_xADReplicationSubnet/en-US/about_xADReplicationSubnet.help.txt +++ b/DSCResources/MSFT_xADReplicationSubnet/en-US/about_xADReplicationSubnet.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADReplicationSubnet DSC resource will manage replication subnets. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Ensure Write - String Allowed values: Present, Absent diff --git a/DSCResources/MSFT_xADServicePrincipalName/en-US/about_xADServicePrincipalName.help.txt b/DSCResources/MSFT_xADServicePrincipalName/en-US/about_xADServicePrincipalName.help.txt index dde03cb89..fb092c723 100644 --- a/DSCResources/MSFT_xADServicePrincipalName/en-US/about_xADServicePrincipalName.help.txt +++ b/DSCResources/MSFT_xADServicePrincipalName/en-US/about_xADServicePrincipalName.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADServicePrincipalName DSC resource will manage service principal names. A service principal name (SPN) is a unique identifier of a service instance. SPNs are used by Kerberos authentication to associate a service instance with a service logon account. This allows a client application to request that the service authenticate an account even if the client does not have the account name. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER Ensure Write - String Allowed values: Present, Absent diff --git a/DSCResources/MSFT_xADUser/en-US/about_xADUser.help.txt b/DSCResources/MSFT_xADUser/en-US/about_xADUser.help.txt index 3bf8b18f6..0f093235b 100644 --- a/DSCResources/MSFT_xADUser/en-US/about_xADUser.help.txt +++ b/DSCResources/MSFT_xADUser/en-US/about_xADUser.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xADUser DSC resource will manage Users within Active Directory. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER DomainName Key - String Name of the domain where the user account is located (only used if password is managed). diff --git a/DSCResources/MSFT_xWaitForADDomain/en-US/about_xWaitForADDomain.help.txt b/DSCResources/MSFT_xWaitForADDomain/en-US/about_xWaitForADDomain.help.txt index c21d99c71..a23231bc3 100644 --- a/DSCResources/MSFT_xWaitForADDomain/en-US/about_xWaitForADDomain.help.txt +++ b/DSCResources/MSFT_xWaitForADDomain/en-US/about_xWaitForADDomain.help.txt @@ -3,11 +3,11 @@ .DESCRIPTION The xWaitForADDomain resource is used to wait for Active Directory to become available. - + ## Requirements - + * Target machine must be running Windows Server 2008 R2 or later. - + .PARAMETER DomainName Key - String The name of the Active Directory domain to wait for. From caf6bbfd74f6ac9c12ab08158d6d7c27be1246b5 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 15:35:08 +0200 Subject: [PATCH 11/16] Fix comment in Add-TypeAssembly --- Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 b/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 index fe59db8d2..ab44aebc1 100644 --- a/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 +++ b/Modules/xActiveDirectory.Common/xActiveDirectory.Common.psm1 @@ -1850,7 +1850,7 @@ function Add-TypeAssembly { Write-Verbose -Message ($script:localizedData.TypeAlreadyExistInSession -f $TypeName) -Verbose - # The type already exist so no need to load the type again. + # The type already exists so no need to load the type again. return } else From f93ddef047a423996e151d0b33a120b91f944382 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 16:33:45 +0200 Subject: [PATCH 12/16] Fix output types in helper functions --- DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index 63ba49697..ca47f85cf 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -532,6 +532,8 @@ function Get-ActiveDirectoryForest #> function ConvertTo-DirectoryContextType { + [CmdletBinding()] + [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] @@ -565,6 +567,8 @@ function ConvertTo-DirectoryContextType #> function ConvertFrom-DirectoryContextType { + [CmdletBinding()] + [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] @@ -613,6 +617,9 @@ function ConvertFrom-DirectoryContextType function Get-TrustTargetAndSourceObject { [CmdletBinding()] + [OutputType( + [System.DirectoryServices.ActiveDirectory.Domain], + [System.DirectoryServices.ActiveDirectory.Forest])] param ( [Parameter(Mandatory = $true)] From b3fa8928073426ae8403cdc9c02e2fda66b06f8d Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 16:57:52 +0200 Subject: [PATCH 13/16] Override PSSA rule --- DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index ca47f85cf..9de1443f9 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -616,6 +616,7 @@ function ConvertFrom-DirectoryContextType #> function Get-TrustTargetAndSourceObject { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '', Justification = 'PSScriptAnalyzer does not handle multiple output types.')] [CmdletBinding()] [OutputType( [System.DirectoryServices.ActiveDirectory.Domain], From d698c97063fcc563410bef7081db1e04be433391 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 16:58:19 +0200 Subject: [PATCH 14/16] Fix double-quotes --- Tests/Integration/MSFT_xADDomainTrust.config.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/MSFT_xADDomainTrust.config.ps1 b/Tests/Integration/MSFT_xADDomainTrust.config.ps1 index ae248df21..305eb166e 100644 --- a/Tests/Integration/MSFT_xADDomainTrust.config.ps1 +++ b/Tests/Integration/MSFT_xADDomainTrust.config.ps1 @@ -40,7 +40,7 @@ else SourceForest = 'contoso.com' TargetForest = 'lab.local' - TargetUserName = "LAB\Administrator" + TargetUserName = 'LAB\Administrator' TargetPassword = 'P@ssw0rd1' } ) From 9ac0ad762a9befcce0fa983777d6eb1e7f2f387d Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 12 Jul 2019 18:01:01 +0200 Subject: [PATCH 15/16] Fix to the coreect type --- DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index 9de1443f9..ea1575f5d 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -616,11 +616,8 @@ function ConvertFrom-DirectoryContextType #> function Get-TrustTargetAndSourceObject { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '', Justification = 'PSScriptAnalyzer does not handle multiple output types.')] [CmdletBinding()] - [OutputType( - [System.DirectoryServices.ActiveDirectory.Domain], - [System.DirectoryServices.ActiveDirectory.Forest])] + [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true)] From 6c48b56d8c533816016c55105ab444f173e80593 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Sat, 13 Jul 2019 07:46:28 +0200 Subject: [PATCH 16/16] Fix review comments at r3 --- .../MSFT_xADDomainTrust.psm1 | 16 ++++++---- Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 | 32 +++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 index ea1575f5d..0bc70b70b 100644 --- a/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 +++ b/DSCResources/MSFT_xADDomainTrust/MSFT_xADDomainTrust.psm1 @@ -72,7 +72,7 @@ function Get-TargetResource TrustType = $TrustType } - $trustSource, $trustTarget = Get-TrustTargetAndSourceObject @getTrustTargetAndSourceObject + $trustSource, $trustTarget = Get-TrustSourceAndTargetObject @getTrustTargetAndSourceObject try { @@ -168,7 +168,7 @@ function Set-TargetResource TrustType = $TrustType } - $trustSource, $trustTarget = Get-TrustTargetAndSourceObject @getTrustTargetAndSourceObject + $trustSource, $trustTarget = Get-TrustSourceAndTargetObject @getTrustTargetAndSourceObject $compareTargetResourceStateResult = Compare-TargetResourceState @PSBoundParameters @@ -595,10 +595,7 @@ function ConvertFrom-DirectoryContextType <# .SYNOPSIS Returns two objects where the first object is for the source domain and - the second object is for the target domain. The type returned is either - System.DirectoryServices.ActiveDirectory.Domain or - System.DirectoryServices.ActiveDirectory.Forest for both objects - (always returns the same type for both objects). + the second object is for the target domain. .PARAMETER SourceDomainName Specifies the name of the Active Directory domain that is requesting the @@ -613,8 +610,13 @@ function ConvertFrom-DirectoryContextType .PARAMETER TrustType Specifies the type of trust. The value 'External' means the context Domain, while the value 'Forest' means the context 'Forest'. + + .OUTPUTS + For both objects the type returned is either of the type + System.DirectoryServices.ActiveDirectory.Domain or of the type + System.DirectoryServices.ActiveDirectory.Forest. #> -function Get-TrustTargetAndSourceObject +function Get-TrustSourceAndTargetObject { [CmdletBinding()] [OutputType([System.Object[]])] diff --git a/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 b/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 index 14aaab9dc..198089363 100644 --- a/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 +++ b/Tests/Unit/MSFT_xADDomainTrust.Tests.ps1 @@ -63,7 +63,7 @@ try Context 'When the domain trust is present in Active Directory' { Context 'When the called with the TrustType ''External''' { BeforeAll { - Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + Mock -CommandName Get-TrustSourceAndTargetObject -MockWith { $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { $script:getTrustRelationshipMethodCallCount += 1 @@ -90,7 +90,7 @@ try AfterEach { $script:getTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } It 'Should return the state as present' { @@ -114,7 +114,7 @@ try Context 'When the called with the TrustType ''Forest''' { BeforeAll { - Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + Mock -CommandName Get-TrustSourceAndTargetObject -MockWith { $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { $script:getTrustRelationshipMethodCallCount += 1 @@ -141,7 +141,7 @@ try AfterEach { $script:getTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } It 'Should return the state as present' { @@ -166,7 +166,7 @@ try Context 'When the domain trust is absent from Active Directory' { BeforeAll { - Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + Mock -CommandName Get-TrustSourceAndTargetObject -MockWith { $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'GetTrustRelationship' -Value { $script:getTrustRelationshipMethodCallCount += 1 @@ -190,7 +190,7 @@ try AfterEach { $script:getTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } It 'Should return the state as absent' { @@ -566,7 +566,7 @@ try Describe 'MSFT_xADDomainTrust\Set-TargetResource' -Tag 'Set' { BeforeAll { - Mock -CommandName Get-TrustTargetAndSourceObject -MockWith { + Mock -CommandName Get-TrustSourceAndTargetObject -MockWith { $mockTrustSource = New-Object -TypeName Object | Add-Member -MemberType ScriptMethod -Name 'CreateTrustRelationship' -Value { $script:createTrustRelationshipMethodCallCount += 1 @@ -630,7 +630,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } @@ -670,7 +670,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } } @@ -705,7 +705,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } } @@ -748,7 +748,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } @@ -789,7 +789,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 1 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } @@ -837,7 +837,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 1 $script:updateTrustRelationshipMethodCallCount | Should -Be 0 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } @@ -884,7 +884,7 @@ try $script:deleteTrustRelationshipMethodCallCount | Should -Be 0 $script:updateTrustRelationshipMethodCallCount | Should -Be 1 - Assert-MockCalled -CommandName Get-TrustTargetAndSourceObject -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Get-TrustSourceAndTargetObject -Exactly -Times 1 -Scope It } } } @@ -934,7 +934,7 @@ try } } - Describe 'MSFT_xADDomainTrust\Get-TrustTargetAndSourceObject' -Tag 'Helper' { + Describe 'MSFT_xADDomainTrust\Get-TrustSourceAndTargetObject' -Tag 'Helper' { BeforeAll { Mock -CommandName Get-ADDirectoryContext -MockWith { # This should work on any client, domain joined or not. @@ -969,7 +969,7 @@ try Verbose = $true } - { Get-TrustTargetAndSourceObject @testParameters } | Should -Not -Throw + { Get-TrustSourceAndTargetObject @testParameters } | Should -Not -Throw if ($TrustType -eq 'External') {