diff --git a/CHANGELOG.md b/CHANGELOG.md index 9663bf03c..2e0e65603 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md) ### Added +- ADManagedServiceAccount + - Added support for setting a common name to a Managed Service Account for a longer more friendly name than + the SAM account name which has a 15 character limit. + ([issue #644](https://github.com/dsccommunity/ActiveDirectoryDsc/issues/644)). - ADGroup - Added support for managing AD group membership of Foreign Security Principals. This involved completely refactoring group membership management to utilize the `Set-ADGroup` cmdlet and referencing SID values. diff --git a/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.psm1 b/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.psm1 index 04f587169..dc00e98c8 100644 --- a/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.psm1 +++ b/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.psm1 @@ -16,9 +16,8 @@ $script:errorCodeKdsRootKeyNotFound = -2146893811 Returns the current state of an Active Directory managed service account. .PARAMETER ServiceAccountName - 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. + Specifies the Security Account Manager (SAM) account name of the managed service account (ldapDisplayName + 'sAMAccountName'). .PARAMETER AccountType The type of managed service account. Standalone will create a Standalone Managed Service Account (sMSA) and @@ -89,6 +88,7 @@ function Get-TargetResource try { $adServiceAccount = Get-ADServiceAccount @adServiceAccountParameters -Properties @( + 'CN' 'DistinguishedName' 'Description' 'DisplayName' @@ -152,6 +152,7 @@ function Get-TargetResource ServiceAccountName = $ServiceAccountName AccountType = $existingAccountType Path = Get-ADObjectParentDN -DN $adServiceAccount.DistinguishedName + CommonName = $adServiceAccount.CN Description = $adServiceAccount.Description DisplayName = $adServiceAccount.DisplayName DistinguishedName = $adServiceAccount.DistinguishedName @@ -169,6 +170,7 @@ function Get-TargetResource ServiceAccountName = $ServiceAccountName AccountType = $AccountType Path = $null + CommonName = $null Description = $null DisplayName = $null DistinguishedName = $null @@ -189,13 +191,17 @@ function Get-TargetResource .PARAMETER ServiceAccountName 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. + 'sAMAccountName'). To be compatible with older operating systems, create a SAM account name that is 15 + characters or less. Once created, the user's SamAccountName cannot be changed. .PARAMETER AccountType The type of managed service account. Standalone will create a Standalone Managed Service Account (sMSA) and Group will create a Group Managed Service Account (gMSA). + .PARAMETER CommonName + Specifies the common name assigned to the managed service account (ldapDisplayName 'cn'). If not specified the + default value will be the same value provided in parameter ServiceAccountName. + .PARAMETER Credential Specifies the user account credentials to use to perform this task. This is only required if not executing the task on a domain controller or using the DomainController parameter. @@ -254,6 +260,11 @@ function Test-TargetResource [System.String] $AccountType, + [Parameter()] + [ValidateNotNull()] + [System.String] + $CommonName, + [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] @@ -376,13 +387,17 @@ function Test-TargetResource .PARAMETER ServiceAccountName 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. + 'sAMAccountName'). To be compatible with older operating systems, create a SAM account name that is 15 + characters or less. Once created, the user's SamAccountName cannot be changed. .PARAMETER AccountType The type of managed service account. Standalone will create a Standalone Managed Service Account (sMSA) and Group will create a Group Managed Service Account (gMSA). + .PARAMETER CommonName + Specifies the common name assigned to the managed service account (ldapDisplayName 'cn'). If not specified the + default value will be the same value provided in parameter ServiceAccountName. + .PARAMETER Credential Specifies the user account credentials to use to perform this task. This is only required if not executing the task on a domain controller or using the DomainController parameter. @@ -449,6 +464,11 @@ function Set-TargetResource [System.String] $AccountType, + [Parameter()] + [ValidateNotNull()] + [System.String] + $CommonName, + [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] @@ -551,6 +571,7 @@ function Set-TargetResource $setServiceAccountParameters = $adServiceAccountParameters.Clone() $setAdServiceAccountRequired = $false $moveAdServiceAccountRequired = $false + $renameAdServiceAccountRequired = $false foreach ($property in $propertiesNotInDesiredState) { @@ -559,6 +580,11 @@ function Set-TargetResource # The path has changed, so the account needs moving, but not until after any other changes $moveAdServiceAccountRequired = $true } + elseif ($property.ParameterName -eq 'CommonName') + { + # Need to set different CN using Rename-ADObject + $renameAdServiceAccountRequired = $true + } else { $setAdServiceAccountRequired = $true @@ -573,7 +599,7 @@ function Set-TargetResource } else { - $SetServiceAccountParameters.Add($property.ParameterName, $property.Expected) + $setServiceAccountParameters.Add($property.ParameterName, $property.Expected) } } } @@ -609,6 +635,17 @@ function Set-TargetResource New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ } } + + if ($renameAdServiceAccountRequired) + { + # Cannot update the CN property directly. Must use Rename-ADObject + $renameAdObjectParameters = Get-ADCommonParameters @PSBoundParameters + + # Using the SamAccountName for identity with Rename-ADObject does not work, use the DN instead + $renameAdObjectParameters['Identity'] = $getTargetResourceResult.DistinguishedName + + Rename-ADObject @renameAdObjectParameters -NewName $CommonName + } } } } @@ -643,7 +680,13 @@ function Set-TargetResource Write-Verbose -Message ($script:localizedData.AddingManagedServiceAccountMessage -f $AccountType, $ServiceAccountName, $messagePath) - $newAdServiceAccountParameters = Get-ADCommonParameters @parameters -UseNameParameter + $newAdServiceAccountParameters = Get-ADCommonParameters @parameters -UseNameParameter -PreferCommonName + + if ($parameters.ContainsKey('CommonName')) + { + # We have to specify the SamAccountName to prefent errors when the common name is longer than 15 characters + $newAdServiceAccountParameters.SamAccountName = $ServiceAccountName + } if ($parameters.ContainsKey('Description')) { diff --git a/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.schema.mof b/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.schema.mof index 31ffe063e..ef1909e05 100644 --- a/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.schema.mof +++ b/source/DSCResources/MSFT_ADManagedServiceAccount/MSFT_ADManagedServiceAccount.schema.mof @@ -1,9 +1,10 @@ [ClassVersion("1.0.1.0"), FriendlyName("ADManagedServiceAccount")] class MSFT_ADManagedServiceAccount : OMI_BaseResource { - [Key, Description("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.")] String ServiceAccountName; + [Key, Description("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 15 characters or less. Once created, the user's SamAccountName cannot be changed.")] String ServiceAccountName; [Required, Description("The type of managed service account. Standalone will create a Standalone Managed Service Account (sMSA) and Group will create a Group Managed Service Account (gMSA)."), ValueMap{"Group","Standalone"}, Values{"Group","Standalone"}] String AccountType; [Write, Description("Specifies the user account credentials to use to perform this task. This is only required if not executing the task on a domain controller or using the parameter DomainController."), EmbeddedInstance("MSFT_Credential")] String Credential; + [Write, Description("Specifies the common name assigned to the managed service account (ldapDisplayName 'cn'). If not specified the default value will be the same value provided in parameter ServiceAccountName.")] String CommonName; [Write, Description("Specifies the description of the account (ldapDisplayName 'description').")] String Description; [Write, Description("Specifies the display name of the account (ldapDisplayName 'displayName').")] String DisplayName; [Write, Description("Specifies the Active Directory Domain Controller instance to use to perform the task. This is only required if not executing the task on a domain controller.")] String DomainController; diff --git a/tests/Integration/MSFT_ADManagedServiceAccount.Integration.Tests.ps1 b/tests/Integration/MSFT_ADManagedServiceAccount.Integration.Tests.ps1 index 369339059..67f64a576 100644 --- a/tests/Integration/MSFT_ADManagedServiceAccount.Integration.Tests.ps1 +++ b/tests/Integration/MSFT_ADManagedServiceAccount.Integration.Tests.ps1 @@ -83,6 +83,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount1.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount1.AccountType $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount1.Name $resourceCurrentState.Description | Should -BeNullOrEmpty $resourceCurrentState.DisplayName | Should -BeNullOrEmpty $resourceCurrentState.Enabled | Should -Be $true @@ -124,6 +125,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount2.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount2.AccountType $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount2.Name $resourceCurrentState.Description | Should -BeNullOrEmpty $resourceCurrentState.DisplayName | Should -BeNullOrEmpty $resourceCurrentState.Enabled | Should -Be $true @@ -165,6 +167,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount3.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount3.AccountType $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount3.Name $resourceCurrentState.Description | Should -BeNullOrEmpty $resourceCurrentState.DisplayName | Should -BeNullOrEmpty $resourceCurrentState.Enabled | Should -Be $true @@ -180,6 +183,48 @@ try } } + $configurationName = "$($script:dscResourceName)_CreateServiceAccount4_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + & $configurationName @configurationParameters + 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.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount4.Name + $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount4.AccountType + $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount4.CommonName + $resourceCurrentState.Description | Should -BeNullOrEmpty + $resourceCurrentState.DisplayName | Should -BeNullOrEmpty + $resourceCurrentState.Enabled | Should -Be $true + $resourceCurrentState.ManagedPasswordPrincipals | Should -BeNullOrEmpty + $resourceCurrentState.MembershipAttribute | Should -Be 'SamAccountName' + $resourceCurrentState.KerberosEncryptionType | Should -Be $DefaultKerberosEncryptionType + $resourceCurrentState.DistinguishedName | Should -Be ('CN={0},{1}' -f $ConfigurationData.ManagedServiceAccount4.CommonName, ` + $DefaultManagedServiceAccountPath) + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + $configurationName = "$($script:dscResourceName)_RemoveServiceAccount1_Config" Context ('When using configuration {0}' -f $configurationName) { @@ -206,6 +251,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount1.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount1.AccountType $resourceCurrentState.Path | Should -BeNullOrEmpty + $resourceCurrentState.CommonName | Should -BeNullOrEmpty $resourceCurrentState.Description | Should -BeNullOrEmpty $resourceCurrentState.DisplayName | Should -BeNullOrEmpty $resourceCurrentState.Enabled | Should -BeFalse @@ -246,6 +292,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount2.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount2.AccountType $resourceCurrentState.Path | Should -Be $ConfigurationData.ManagedServiceAccount2.Path + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount2.Name $resourceCurrentState.Description | Should -Be $ConfigurationData.ManagedServiceAccount2.Description $resourceCurrentState.DisplayName | Should -Be $ConfigurationData.ManagedServiceAccount2.DisplayName $resourceCurrentState.Enabled | Should -Be $true @@ -287,6 +334,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount3.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount3.AccountType $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount3.Name $resourceCurrentState.Description | Should -BeNullOrEmpty $resourceCurrentState.DisplayName | Should -BeNullOrEmpty $resourceCurrentState.Enabled | Should -Be $true @@ -328,6 +376,7 @@ try $resourceCurrentState.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount3.Name $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount3.AccountType $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount3.Name $resourceCurrentState.Description | Should -BeNullOrEmpty $resourceCurrentState.DisplayName | Should -BeNullOrEmpty $resourceCurrentState.Enabled | Should -Be $true @@ -343,6 +392,48 @@ try } } + $configurationName = "$($script:dscResourceName)_RenameServiceAccount4_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + & $configurationName @configurationParameters + 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.ServiceAccountName | Should -Be $ConfigurationData.ManagedServiceAccount4.Name + $resourceCurrentState.AccountType | Should -Be $ConfigurationData.ManagedServiceAccount4.AccountType + $resourceCurrentState.Path | Should -Be $DefaultManagedServiceAccountPath + $resourceCurrentState.CommonName | Should -Be $ConfigurationData.ManagedServiceAccount4.Name + $resourceCurrentState.Description | Should -BeNullOrEmpty + $resourceCurrentState.DisplayName | Should -BeNullOrEmpty + $resourceCurrentState.Enabled | Should -Be $true + $resourceCurrentState.ManagedPasswordPrincipals | Should -BeNullOrEmpty + $resourceCurrentState.MembershipAttribute | Should -Be 'SamAccountName' + $resourceCurrentState.KerberosEncryptionType | Should -Be $DefaultKerberosEncryptionType + $resourceCurrentState.DistinguishedName | Should -Be ('CN={0},{1}' -f ` + $ConfigurationData.ManagedServiceAccount4.Name, $DefaultManagedServiceAccountPath) + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + $configurationName = "$($script:dscResourceName)_Initialise_Config" Context ('When using configuration {0}' -f $configurationName) { diff --git a/tests/Integration/MSFT_ADManagedServiceAccount.config.ps1 b/tests/Integration/MSFT_ADManagedServiceAccount.config.ps1 index f817ccd8f..77e4ad680 100644 --- a/tests/Integration/MSFT_ADManagedServiceAccount.config.ps1 +++ b/tests/Integration/MSFT_ADManagedServiceAccount.config.ps1 @@ -47,6 +47,12 @@ else 'Guest' ) } + + ManagedServiceAccount4 = @{ + Name = 'Dsc-gMSA4' + AccountType = 'Group' + CommonName = 'Dsc-gMSACommonName4' + } } } @@ -80,6 +86,13 @@ Configuration MSFT_ADManagedServiceAccount_Initialise_Config AccountType = $ConfigurationData.ManagedServiceAccount3.AccountType Ensure = 'Absent' } + + ADManagedServiceAccount 'RemoveGroup4' + { + ServiceAccountName = $ConfigurationData.ManagedServiceAccount4.Name + AccountType = $ConfigurationData.ManagedServiceAccount4.AccountType + Ensure = 'Absent' + } } } @@ -139,7 +152,26 @@ Configuration MSFT_ADManagedServiceAccount_CreateServiceAccount3_Config <# .SYNOPSIS - Remove a group. + Add a Third Group ManagedServiceAccount using default values. +#> +Configuration MSFT_ADManagedServiceAccount_CreateServiceAccount4_Config +{ + Import-DscResource -ModuleName 'ActiveDirectoryDsc' + + node $AllNodes.NodeName + { + ADManagedServiceAccount 'Integration_Test' + { + ServiceAccountName = $ConfigurationData.ManagedServiceAccount4.Name + AccountType = $ConfigurationData.ManagedServiceAccount4.AccountType + CommonName = $ConfigurationData.ManagedServiceAccount4.CommonName + } + } +} + +<# + .SYNOPSIS + Remove a ManagedServiceAccount. #> Configuration MSFT_ADManagedServiceAccount_RemoveServiceAccount1_Config { @@ -156,10 +188,9 @@ Configuration MSFT_ADManagedServiceAccount_RemoveServiceAccount1_Config } } - <# .SYNOPSIS - Update an existing group. + Update an existing ManagedServiceAccount. #> Configuration MSFT_ADManagedServiceAccount_UpdateServiceAccount2_Config { @@ -181,7 +212,7 @@ Configuration MSFT_ADManagedServiceAccount_UpdateServiceAccount2_Config <# .SYNOPSIS - Enforce members in a group. + Enforce members in a ManagedServiceAccount. #> Configuration MSFT_ADManagedServiceAccount_EnforcePasswordPrincipalsServiceAccount3_Config { @@ -200,7 +231,7 @@ Configuration MSFT_ADManagedServiceAccount_EnforcePasswordPrincipalsServiceAccou <# .SYNOPSIS - Enforce no members in a group. + Enforce no members in a ManagedServiceAccount. #> Configuration MSFT_ADManagedServiceAccount_ClearPasswordPrincipalsServiceAccount3_Config { @@ -216,3 +247,22 @@ Configuration MSFT_ADManagedServiceAccount_ClearPasswordPrincipalsServiceAccount } } } + +<# + .SYNOPSIS + Rename the common name of a ManagedServiceAccount. +#> +Configuration MSFT_ADManagedServiceAccount_RenameServiceAccount4_Config +{ + Import-DscResource -ModuleName 'ActiveDirectoryDsc' + + node $AllNodes.NodeName + { + ADManagedServiceAccount 'Integration_Test' + { + ServiceAccountName = $ConfigurationData.ManagedServiceAccount4.Name + AccountType = $ConfigurationData.ManagedServiceAccount4.AccountType + CommonName = $ConfigurationData.ManagedServiceAccount4.Name + } + } +} diff --git a/tests/Unit/MSFT_ADManagedServiceAccount.Tests.ps1 b/tests/Unit/MSFT_ADManagedServiceAccount.Tests.ps1 index 5d3057fee..2caadb07d 100644 --- a/tests/Unit/MSFT_ADManagedServiceAccount.Tests.ps1 +++ b/tests/Unit/MSFT_ADManagedServiceAccount.Tests.ps1 @@ -71,7 +71,8 @@ try $mockAdServiceAccountStandalone = @{ ServiceAccountName = 'TestSMSA' AccountType = 'Standalone' - DistinguishedName = "CN=TestSMSA,$mockDefaultMsaPath" + CommonName = 'TestSMSACN' + DistinguishedName = "CN=TestSMSACN,$mockDefaultMsaPath" Description = 'Dummy StandAlone service account for unit testing' DisplayName = 'TestSMSA' Enabled = $true @@ -84,6 +85,7 @@ try $mockAdServiceAccountStandaloneAbsent = @{ ServiceAccountName = $mockAdServiceAccountStandalone.ServiceAccountName AccountType = $mockAdServiceAccountStandalone.AccountType + CommonName = $null DistinguishedName = $null Description = $null DisplayName = $null @@ -95,6 +97,7 @@ try } $mockAdServiceAccountChanged = @{ + CommonName = 'Changed commonName' Description = 'Changed description' DisplayName = 'Changed displayname' KerberosEncryptionType = 'AES128', 'AES256' @@ -104,7 +107,8 @@ try $mockAdServiceAccountGroup = @{ ServiceAccountName = 'TestGMSA' AccountType = 'Group' - DistinguishedName = "CN=TestGMSA,$mockDefaultMsaPath" + CommonName = 'TestGMSACN' + DistinguishedName = "CN=TestGMSACN,$mockDefaultMsaPath" Description = 'Dummy group service account for unit testing' DisplayName = 'TestGMSA' Enabled = $true @@ -117,6 +121,7 @@ try $mockAdServiceAccountGroupAbsent = @{ ServiceAccountName = $mockAdServiceAccountGroup.ServiceAccountName AccountType = $mockAdServiceAccountGroup.AccountType + CommonName = $null DistinguishedName = $null Description = $null DisplayName = $null @@ -128,6 +133,7 @@ try } $mockGetAdServiceAccountResultsStandAlone = @{ + CN = $mockAdServiceAccountStandAlone.CommonName Description = $mockAdServiceAccountStandalone.Description DisplayName = $mockAdServiceAccountStandalone.DisplayName DistinguishedName = $mockAdServiceAccountStandalone.DistinguishedName @@ -142,6 +148,7 @@ try } $mockGetAdServiceAccountResultsGroup = @{ + CN = $mockAdServiceAccountGroup.CommonName Description = $mockAdServiceAccountGroup.Description DisplayName = $mockAdServiceAccountGroup.DisplayName DistinguishedName = $mockAdServiceAccountGroup.DistinguishedName @@ -160,6 +167,7 @@ try ServiceAccountName = $mockGetAdServiceAccountResultsStandAlone.Name DistinguishedName = $mockGetAdServiceAccountResultsStandAlone.DistinguishedName Path = $mockDefaultMsaPath + CommonName = $mockGetAdServiceAccountResultsStandAlone.CN Description = $mockGetAdServiceAccountResultsStandAlone.Description DisplayName = $mockGetAdServiceAccountResultsStandAlone.DisplayName AccountType = 'Standalone' @@ -176,6 +184,7 @@ try ServiceAccountName = $mockGetAdServiceAccountResultsGroup.Name DistinguishedName = $mockGetAdServiceAccountResultsGroup.DistinguishedName Path = $mockDefaultMsaPath + CommonName = $mockGetAdServiceAccountResultsGroup.CN Description = $mockGetAdServiceAccountResultsGroup.Description DisplayName = $mockGetAdServiceAccountResultsGroup.DisplayName AccountType = 'Group' @@ -192,6 +201,7 @@ try ServiceAccountName = $mockGetAdServiceAccountResultsStandAlone.Name DistinguishedName = $null Path = $null + CN = $null Description = $null DisplayName = $null AccountType = $null @@ -222,7 +232,7 @@ try Context 'When the resource is Present' { - Context 'When the Resouce is a StandAlone account' { + Context 'When the Resource is a StandAlone account' { Mock -CommandName Get-ADServiceAccount ` -MockWith { $mockGetAdServiceAccountResultsStandAlone } @@ -257,7 +267,7 @@ try } } - Context 'When the Resouce is a Group account' { + Context 'When the Resource is a Group account' { Mock -CommandName Get-ADServiceAccount ` -MockWith { $mockGetAdServiceAccountResultsGroup } @@ -351,7 +361,7 @@ try Context 'When the resource is Absent' { - Context 'When the Resouce is a StandAlone account' { + Context 'When the Resource is a StandAlone account' { Mock -CommandName Get-AdServiceAccount ` -MockWith { throw New-Object Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException } @@ -377,7 +387,7 @@ try } } - Context 'When the Resouce is a Group account' { + Context 'When the Resource is a Group account' { Mock -CommandName Get-AdServiceAccount ` -MockWith { throw New-Object Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException } @@ -411,6 +421,7 @@ try $testTargetResourceParametersStandalone = @{ ServiceAccountName = $mockAdServiceAccountStandalone.ServiceAccountName AccountType = $mockAdServiceAccountStandalone.AccountType + CommonName = $mockAdServiceAccountStandalone.CommonName Description = $mockAdServiceAccountStandalone.Description DisplayName = $mockAdServiceAccountStandalone.DisplayName KerberosEncryptionType = $mockAdServiceAccountStandalone.KerberosEncryptionType @@ -532,6 +543,7 @@ try Mock -CommandName New-ADServiceAccount Mock -CommandName Remove-ADServiceAccount Mock -CommandName Move-ADObject + Mock -CommandName Rename-ADObject Mock -CommandName Set-ADServiceAccount Mock -CommandName Get-DomainName -MockWith { $mockDomainName } Mock -CommandName Get-ADDomain -MockWith { $mockGetAdDomainResults } @@ -541,6 +553,7 @@ try ServiceAccountName = $mockAdServiceAccountStandAlone.ServiceAccountName AccountType = $mockAdServiceAccountStandAlone.AccountType Path = $mockDefaultMsaPath + CommonName = $mockAdServiceAccountStandalone.CommonName Description = $mockAdServiceAccountStandalone.Description Ensure = $mockAdServiceAccountStandAlone.Ensure DisplayName = $mockAdServiceAccountStandAlone.DisplayName @@ -555,6 +568,7 @@ try MembershipAttribute = $mockAdServiceAccountGroup.MembershipAttribute AccountType = $mockAdServiceAccountGroup.AccountType Path = $mockDefaultMsaPath + CommonName = $mockAdServiceAccountGroup.CommonName Description = $mockAdServiceAccountGroup.Description Ensure = $mockAdServiceAccountGroup.Ensure ManagedPasswordPrincipals = $mockAdServiceAccountGroup.ManagedPasswordPrincipals @@ -585,6 +599,12 @@ try -Scope It -Exactly -Times 1 Assert-MockCalled -CommandName New-ADServiceAccount -Scope It -Exactly -Times 0 Assert-MockCalled -CommandName Remove-ADServiceAccount -Scope It -Exactly -Times 0 + if ($property -eq 'CommonName') { + Assert-MockCalled -CommandName Rename-ADObject -Scope It -Exactly -Times 1 + } + else { + Assert-MockCalled -CommandName Rename-ADObject -Scope It -Exactly -Times 0 + } Assert-MockCalled -CommandName Move-ADObject -Scope It -Exactly -Times 0 Assert-MockCalled -CommandName Set-ADServiceAccount ` -ParameterFilter { ` @@ -621,13 +641,14 @@ try -Exactly -Times 1 Assert-MockCalled -CommandName New-ADServiceAccount ` -ParameterFilter { ` - $Name -eq $setTargetResourceParametersChangedAccountType.ServiceAccountName } ` + $Name -eq $setTargetResourceParametersChangedAccountType.CommonName } ` -Exactly -Times 1 Assert-MockCalled -CommandName Remove-ADServiceAccount ` -ParameterFilter { ` $Identity -eq $setTargetResourceParametersChangedAccountType.ServiceAccountName } ` -Exactly -Times 1 Assert-MockCalled -CommandName Get-DomainName -Exactly -Times 1 + Assert-MockCalled -CommandName Rename-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Move-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Set-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Get-ADDomain -Exactly -Times 0 @@ -659,6 +680,7 @@ try -Exactly -Times 1 Assert-MockCalled -CommandName New-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Remove-ADServiceAccount -Exactly -Times 0 + Assert-MockCalled -CommandName Rename-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Move-ADObject ` -ParameterFilter { $Identity -eq $mockGetTargetResourceResultsStandAlone.DistinguishedName } ` -Exactly -Times 1 @@ -696,9 +718,10 @@ try $ServiceAccountName -eq $setTargetResourceParametersStandAlone.ServiceAccountName } ` -Exactly -Times 1 Assert-MockCalled -CommandName New-ADServiceAccount ` - -ParameterFilter { $Name -eq $setTargetResourceParametersStandAlone.ServiceAccountName } ` + -ParameterFilter { $Name -eq $setTargetResourceParametersStandAlone.CommonName } ` -Exactly -Times 1 Assert-MockCalled -CommandName Remove-ADServiceAccount -Exactly -Times 0 + Assert-MockCalled -CommandName Rename-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Move-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Set-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Get-DomainName -Exactly -Times 0 @@ -755,10 +778,11 @@ try $ServiceAccountName -eq $setTargetResourceParametersGroup.ServiceAccountName } ` -Exactly -Times 1 Assert-MockCalled -CommandName New-ADServiceAccount ` - -ParameterFilter { $Name -eq $setTargetResourceParametersGroup.ServiceAccountName } ` + -ParameterFilter { $Name -eq $setTargetResourceParametersGroup.CommonName } ` -Exactly -Times 1 Assert-MockCalled -CommandName Get-DomainName -Exactly -Times 1 Assert-MockCalled -CommandName Remove-ADServiceAccount -Exactly -Times 0 + Assert-MockCalled -CommandName Rename-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Move-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Set-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Get-ADDomain -Exactly -Times 0 @@ -813,6 +837,7 @@ try -ParameterFilter { $Identity -eq $setTargetResourceParametersStandAloneAbsent.ServiceAccountName } ` -Exactly -Times 1 + Assert-MockCalled -CommandName Rename-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Move-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Set-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Get-DomainName -Exactly -Times 0 @@ -845,6 +870,7 @@ try -Exactly -Times 1 Assert-MockCalled -CommandName New-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Remove-ADServiceAccount -Exactly -Times 0 + Assert-MockCalled -CommandName Rename-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Move-ADObject -Exactly -Times 0 Assert-MockCalled -CommandName Set-ADServiceAccount -Exactly -Times 0 Assert-MockCalled -CommandName Get-DomainName -Exactly -Times 0