Skip to content

Commit 9504c08

Browse files
authored
xCluster: Make DomainAdministratorCredential optional (#249)
- xCluster - Made DomainAdministratorCredential optional (issue #164).
1 parent dae1e20 commit 9504c08

File tree

5 files changed

+110
-12
lines changed

5 files changed

+110
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md)
8787
- xCluster
8888
- Added script file information to the example `1-CreateFirstNodeOfAFailoverCluster.ps1`.
8989
- Fixed Describe-block descriptions ([issue #234](https://github.com/dsccommunity/xFailOverCluster/issues/234)).
90+
- Made DomainAdministratorCredential optional ([issue #164](https://github.com/dsccommunity/xFailOverCluster/issues/164))
9091

9192
### Removed
9293

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,15 @@ the target node ($env:COMPUTERNAME) to the cluster.
6666
for cluster communication. To remove networks assigned an IP address through DHCP
6767
use the resource xClusterNetwork to change the role of the network. This parameter
6868
is only used during the creation of the cluster and is not monitored after.
69-
* **`[String]` DomainAdministratorCredential** _(Required)_: Credential used to
70-
create the failover cluster in Active Directory.
69+
* **`[PSCredential]` DomainAdministratorCredential** _(Write)_: Credential used to
70+
create the failover cluster in Active Directory. If this is not specified then
71+
the cluster computer object must have been prestaged as per the
72+
[documentation](https://docs.microsoft.com/en-us/windows-server/failover-clustering/prestage-cluster-adds).
73+
* If `PsDscRunAsCredential` is used, then that account must have been granted
74+
Full Control over the Cluster Name Object in Active Directory.
75+
* Otherwise the Computer Account must have been granted Full Control
76+
over the Cluster Name Object in Active Directory.
77+
7178

7279
#### Examples for xCluster
7380

source/DSCResources/MSFT_xCluster/MSFT_xCluster.psm1

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function Get-TargetResource
4343
[System.String[]]
4444
$IgnoreNetwork,
4545

46-
[Parameter(Mandatory = $true)]
46+
[Parameter()]
4747
[System.Management.Automation.PSCredential]
4848
$DomainAdministratorCredential
4949
)
@@ -56,10 +56,13 @@ function Get-TargetResource
5656
$errorMessage = $script:localizedData.TargetNodeDomainMissing
5757
New-InvalidOperationException -Message $errorMessage
5858
}
59-
59+
$context = $null
6060
try
6161
{
62-
($oldToken, $context, $newToken) = Set-ImpersonateAs -Credential $DomainAdministratorCredential
62+
if ($PSBoundParameters.ContainsKey('DomainAdministratorCredential'))
63+
{
64+
($oldToken, $context, $newToken) = Set-ImpersonateAs -Credential $DomainAdministratorCredential
65+
}
6366

6467
$cluster = Get-Cluster -Name $Name -Domain $computerInformation.Domain
6568
if ($null -eq $cluster)
@@ -87,6 +90,7 @@ function Get-TargetResource
8790
IgnoreNetwork = $IgnoreNetwork
8891
DomainAdministratorCredential = $DomainAdministratorCredential
8992
}
93+
9094
}
9195

9296
<#
@@ -136,7 +140,7 @@ function Set-TargetResource
136140
[System.String[]]
137141
$IgnoreNetwork,
138142

139-
[Parameter(Mandatory = $true)]
143+
[Parameter()]
140144
[System.Management.Automation.PSCredential]
141145
$DomainAdministratorCredential
142146
)
@@ -168,7 +172,11 @@ function Set-TargetResource
168172

169173
try
170174
{
171-
($oldToken, $context, $newToken) = Set-ImpersonateAs -Credential $DomainAdministratorCredential
175+
$context = $null
176+
if ($PSBoundParameters.ContainsKey('DomainAdministratorCredential'))
177+
{
178+
($oldToken, $context, $newToken) = Set-ImpersonateAs -Credential $DomainAdministratorCredential
179+
}
172180

173181
if ($bCreate)
174182
{
@@ -302,7 +310,7 @@ function Test-TargetResource
302310
[System.String[]]
303311
$IgnoreNetwork,
304312

305-
[Parameter(Mandatory = $true)]
313+
[Parameter()]
306314
[System.Management.Automation.PSCredential]
307315
$DomainAdministratorCredential
308316
)
@@ -320,7 +328,11 @@ function Test-TargetResource
320328

321329
try
322330
{
323-
($oldToken, $context, $newToken) = Set-ImpersonateAs -Credential $DomainAdministratorCredential
331+
$context = $null
332+
if ($PSBoundParameters.ContainsKey('DomainAdministratorCredential'))
333+
{
334+
($oldToken, $context, $newToken) = Set-ImpersonateAs -Credential $DomainAdministratorCredential
335+
}
324336

325337
$cluster = Get-Cluster -Name $Name -Domain $ComputerInfo.Domain
326338

source/DSCResources/MSFT_xCluster/MSFT_xCluster.schema.mof

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ class MSFT_xCluster : OMI_BaseResource
55
{
66
[Key, Description("Name of the Cluster")] String Name;
77
[Write, Description("StaticIPAddress of the Cluster")] String StaticIPAddress;
8-
[Required, EmbeddedInstance("MSFT_Credential"), Description("Credential to create the cluster")] String DomainAdministratorCredential;
8+
[Write, EmbeddedInstance("MSFT_Credential"), Description("Credential to create the cluster")] String DomainAdministratorCredential;
99
[Write, Description("One or more networks to ignore when creating the cluster. Only networks using Static IP can be ignored, networks that are assigned an IP address through DHCP cannot be ignored, and are added for cluster communication. To remove networks assigned an IP address through DHCP use the resource xClusterNetwork to change the role of the network. This parameter is only used during the creation of the cluster and is not monitored after.")] String IgnoreNetwork[];
1010
};

tests/Unit/MSFT_xCluster.Tests.ps1

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,25 @@ foreach ($moduleVersion in @('2012', '2016'))
228228
}
229229
}
230230

231+
Context 'When no DomainAdministratorCredential is provided' {
232+
233+
$withNoDomainAdministratorCredential = $mockDefaultParameters.Clone()
234+
$withNoDomainAdministratorCredential.Remove('DomainAdministratorCredential')
235+
236+
It 'Should not call Set-ImpersonateAs' {
237+
Mock -CommandName Set-ImpersonateAs -MockWith {Return 0}
238+
239+
$getTargetResourceResult = Get-TargetResource @withNoDomainAdministratorCredential
240+
241+
Assert-MockCalled -CommandName Set-ImpersonateAs -Exactly -Times 0 -Scope It
242+
}
243+
It 'Should return empty DomainAdministratorCredential in the hash' {
244+
245+
$getTargetResourceResult = Get-TargetResource @withNoDomainAdministratorCredential
246+
$getTargetResourceResult.DomainAdministratorCredential | Should -BeNullOrEmpty
247+
}
248+
}
249+
231250
Assert-VerifiableMock
232251
}
233252
}
@@ -344,6 +363,21 @@ foreach ($moduleVersion in @('2012', '2016'))
344363
Assert-MockCalled -CommandName Add-ClusterNode -Exactly -Times 0 -Scope It
345364
}
346365
}
366+
367+
Context 'When no DomainAdministratorCredential is provided' {
368+
It 'Should not call Set-ImpersonateAs' {
369+
$withNoDomainAdministratorCredential = $mockDefaultParameters.Clone()
370+
$withNoDomainAdministratorCredential.Remove('DomainAdministratorCredential')
371+
Mock -CommandName Set-ImpersonateAs -MockWith {Return 0}
372+
373+
{Set-TargetResource @withNoDomainAdministratorCredential} | Should Not Throw
374+
375+
Assert-MockCalled -CommandName Set-ImpersonateAs -Exactly -Times 0 -Scope It
376+
Assert-MockCalled -CommandName New-Cluster -Exactly -Times 1 -Scope It
377+
Assert-MockCalled -CommandName Remove-ClusterNode -Exactly -Times 0 -Scope It
378+
Assert-MockCalled -CommandName Add-ClusterNode -Exactly -Times 0 -Scope It
379+
}
380+
}
347381
}
348382

349383
Context 'When Get-Cluster throws an error' {
@@ -379,16 +413,32 @@ foreach ($moduleVersion in @('2012', '2016'))
379413
}
380414

381415
Context 'When the cluster exist but the node is not part of the cluster' {
382-
It 'Should call Add-ClusterNode cmdlet' {
416+
BeforeAll {
383417
Mock -CommandName Get-ClusterNode
384418
Mock -CommandName Get-Cluster -MockWith $mockGetCluster -ParameterFilter $mockGetCluster_ParameterFilter
385-
419+
}
420+
It 'Should call Add-ClusterNode cmdlet' {
386421
{ Set-TargetResource @mockDefaultParameters } | Should -Not -Throw
387422

388423
Assert-MockCalled -CommandName New-Cluster -Exactly -Times 0 -Scope It
389424
Assert-MockCalled -CommandName Remove-ClusterNode -Exactly -Times 0 -Scope It
390425
Assert-MockCalled -CommandName Add-ClusterNode -Exactly -Times 1 -Scope It
391426
}
427+
428+
Context 'When no DomainAdministratorCredential is provided' {
429+
It 'Should not call Set-ImpersonateAs' {
430+
$withNoDomainAdministratorCredential = $mockDefaultParameters.Clone()
431+
$withNoDomainAdministratorCredential.Remove('DomainAdministratorCredential')
432+
Mock -CommandName Set-ImpersonateAs -MockWith {Return 0}
433+
434+
{Set-TargetResource @withNoDomainAdministratorCredential} | Should Not Throw
435+
436+
Assert-MockCalled -CommandName Set-ImpersonateAs -Exactly -Times 0 -Scope It
437+
Assert-MockCalled -CommandName New-Cluster -Exactly -Times 0 -Scope It
438+
Assert-MockCalled -CommandName Remove-ClusterNode -Exactly -Times 0 -Scope It
439+
Assert-MockCalled -CommandName Add-ClusterNode -Exactly -Times 1 -Scope It
440+
}
441+
}
392442
}
393443

394444
Context 'When the cluster exist and the node is down' {
@@ -447,6 +497,18 @@ foreach ($moduleVersion in @('2012', '2016'))
447497

448498
Assert-VerifiableMock
449499
}
500+
501+
Context 'When no DomainAdministratorCredential is provided' {
502+
It 'Should not call Set-ImpersonateAs' {
503+
$withNoDomainAdministratorCredential = $mockDefaultParameters.Clone()
504+
$withNoDomainAdministratorCredential.Remove('DomainAdministratorCredential')
505+
Mock -CommandName Set-ImpersonateAs -MockWith {Return 0}
506+
507+
{Set-TargetResource @withNoDomainAdministratorCredential} | Should Not Throw
508+
509+
Assert-MockCalled -CommandName Set-ImpersonateAs -Exactly -Times 0 -Scope It
510+
}
511+
}
450512
}
451513
}
452514

@@ -471,6 +533,22 @@ foreach ($moduleVersion in @('2012', '2016'))
471533
}
472534
}
473535

536+
Context 'When no DomainAdministratorCredential is provided' {
537+
$mockDynamicDomainName = $mockDomainName
538+
$mockDynamicServerName = $mockServerName
539+
540+
It 'Should not call Set-ImpersonateAs' {
541+
Mock -CommandName Get-Cluster -MockWith $mockGetCluster -ParameterFilter $mockGetCluster_ParameterFilter -Verifiable
542+
543+
$withNoDomainAdministratorCredential = $mockDefaultParameters.Clone()
544+
$withNoDomainAdministratorCredential.Remove('DomainAdministratorCredential')
545+
Mock -CommandName Set-ImpersonateAs -MockWith {Return 0}
546+
547+
$testTargetResourceResult = Test-TargetResource @withNoDomainAdministratorCredential
548+
Assert-MockCalled -CommandName Set-ImpersonateAs -Exactly -Times 0 -Scope It
549+
}
550+
}
551+
474552
Context 'When the system is not in the desired state' {
475553
BeforeEach {
476554
Mock -CommandName Get-CimInstance -MockWith $mockGetCimInstance -ParameterFilter $mockGetCimInstance_ParameterFilter -Verifiable

0 commit comments

Comments
 (0)