Skip to content

Commit

Permalink
ADDomainController: Support for supplying DelegatedAdministratorAccou…
Browse files Browse the repository at this point in the history
…ntName (#709)

- ADDomainController
  - Added support for specifying an RODC delegated administrator account using DelegatedAdministratorAccountName.
  - Do not allow use of AllowPasswordReplicationAccountName or DenyPasswordReplicationAccountName
    unless ReadOnlyReplica is also set.
  • Loading branch information
Borgquite authored May 17, 2024
1 parent 9544987 commit 8b4a7cd
Show file tree
Hide file tree
Showing 9 changed files with 446 additions and 18 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md)

## [Unreleased]

### Added

- ADDomainController
- Added support for specifying an RODC delegated administrator account using DelegatedAdministratorAccountName.

### Changed

- ADDomainController
- Do not allow use of AllowPasswordReplicationAccountName or DenyPasswordReplicationAccountName
unless ReadOnlyReplica is also set.
- ADServicePrincipalName
- Add check to Set function to cover if `Invoke-DscResource -Method Set` is run and no changes are required.
([issue #520](https://github.com/dsccommunity/ActiveDirectoryDsc/issues/520))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ function Get-TargetResource
Write-Verbose -Message ($script:localizedData.IsDomainController -f
$domainControllerObject.Name, $domainControllerObject.Domain)

# If this is a read-only domain controller, retrieve any user or group that is a delegated administrator via the ManagedBy attribute
$delegateAdministratorAccountName = $null
if ($domainControllerObject.IsReadOnly)
{
$domainControllerComputerObject = $domainControllerObject.ComputerObjectDN | Get-ADComputer -Properties ManagedBy -Credential $Credential
if ($domainControllerComputerObject.ManagedBy)
{
$domainControllerManagedByObject = $domainControllerComputerObject.ManagedBy | Get-ADObject -Properties objectSid -Credential $Credential

$delegateAdministratorAccountName = Resolve-SamAccountName -ObjectSid $domainControllerManagedByObject.objectSid
}
}

$allowedPasswordReplicationAccountName = (
Get-ADDomainControllerPasswordReplicationPolicy -Allowed -Identity $domainControllerObject |
ForEach-Object -MemberName sAMAccountName)
Expand All @@ -89,6 +102,7 @@ function Get-TargetResource
AllowPasswordReplicationAccountName = @($allowedPasswordReplicationAccountName)
Credential = $Credential
DatabasePath = $serviceNTDS.'DSA Working Directory'
DelegatedAdministratorAccountName = $delegateAdministratorAccountName
DenyPasswordReplicationAccountName = @($deniedPasswordReplicationAccountName)
DomainName = $domainControllerObject.Domain
Ensure = $true
Expand All @@ -111,6 +125,7 @@ function Get-TargetResource
AllowPasswordReplicationAccountName = $null
Credential = $Credential
DatabasePath = $null
DelegatedAdministratorAccountName = $null
DenyPasswordReplicationAccountName = $null
DomainName = $DomainName
Ensure = $false
Expand Down Expand Up @@ -166,6 +181,9 @@ function Get-TargetResource
.PARAMETER ReadOnlyReplica
Specifies if the domain controller should be provisioned as read-only domain controller
.PARAMETER DelegatedAdministratorAccountName
Specifies the user or group that is the delegated administrator of this read-only domain controller.
.PARAMETER AllowPasswordReplicationAccountName
Provides a list of the users, computers, and groups to add to the password replication allowed list.
Expand Down Expand Up @@ -252,6 +270,10 @@ function Set-TargetResource
[System.Boolean]
$ReadOnlyReplica,

[Parameter()]
[System.String]
$DelegatedAdministratorAccountName,

[Parameter()]
[System.String[]]
$AllowPasswordReplicationAccountName,
Expand All @@ -278,6 +300,30 @@ function Set-TargetResource

$targetResource = Get-TargetResource @getTargetResourceParameters

if ($PSBoundParameters.ContainsKey('DelegatedAdministratorAccountName'))
{
if (-not $PSBoundParameters.ContainsKey('ReadOnlyReplica') -or $ReadOnlyReplica -ne $true)
{
New-InvalidOperationException -Message $script:localizedData.DelegatedAdministratorAccountNameNotRODC
}
}

if ($PSBoundParameters.ContainsKey('AllowPasswordReplicationAccountName'))
{
if (-not $PSBoundParameters.ContainsKey('ReadOnlyReplica') -or $ReadOnlyReplica -ne $true)
{
New-InvalidOperationException -Message $script:localizedData.AllowPasswordReplicationAccountNameNotRODC
}
}

if ($PSBoundParameters.ContainsKey('DenyPasswordReplicationAccountName'))
{
if (-not $PSBoundParameters.ContainsKey('ReadOnlyReplica') -or $ReadOnlyReplica -ne $true)
{
New-InvalidOperationException -Message $script:localizedData.DenyPasswordReplicationAccountNameNotRODC
}
}

if ($targetResource.Ensure -eq $false)
{
Write-Verbose -Message ($script:localizedData.Promoting -f $env:COMPUTERNAME, $DomainName)
Expand All @@ -301,6 +347,12 @@ function Set-TargetResource
$installADDSDomainControllerParameters.Add('ReadOnlyReplica', $true)
}

if ($PSBoundParameters.ContainsKey('DelegatedAdministratorAccountName'))
{
$installADDSDomainControllerParameters.Add('DelegatedAdministratorAccountName',
$DelegatedAdministratorAccountName)
}

if ($PSBoundParameters.ContainsKey('AllowPasswordReplicationAccountName'))
{
$installADDSDomainControllerParameters.Add('AllowPasswordReplicationAccountName',
Expand Down Expand Up @@ -401,6 +453,21 @@ function Set-TargetResource
Move-ADDirectoryServer -Identity $env:COMPUTERNAME -Site $SiteName -Credential $Credential
}

if ($PSBoundParameters.ContainsKey('DelegatedAdministratorAccountName') -and
$targetResource.DelegatedAdministratorAccountName -ne $DelegatedAdministratorAccountName)
{
# If this is a read-only domain controller, set the delegated administrator via the ManagedBy attribute
if ($domainControllerObject.IsReadOnly)
{
Write-Verbose -Message ($script:localizedData.UpdatingDelegatedAdministratorAccountName -f
$targetResource.DelegatedAdministratorAccountName, $DelegatedAdministratorAccountName)

$delegateAdministratorAccountSecurityIdentifier = Resolve-SecurityIdentifier -SamAccountName $DelegatedAdministratorAccountName

Set-ADComputer -Identity $domainControllerObject.ComputerObjectDN -ManagedBy $delegateAdministratorAccountSecurityIdentifier -Credential $Credential
}
}

if ($PSBoundParameters.ContainsKey('AllowPasswordReplicationAccountName'))
{
$testMembersParameters = @{
Expand Down Expand Up @@ -580,6 +647,9 @@ function Set-TargetResource
.PARAMETER ReadOnlyReplica
Specifies if the domain controller should be provisioned as read-only domain controller
.PARAMETER DelegatedAdministratorAccountName
Specifies the user or group that is the delegated administrator of this read-only domain controller.
.PARAMETER AllowPasswordReplicationAccountName
Provides a list of the users, computers, and groups to add to the password replication allowed list.
Expand Down Expand Up @@ -658,6 +728,10 @@ function Test-TargetResource
[System.Boolean]
$ReadOnlyReplica,

[Parameter()]
[System.String]
$DelegatedAdministratorAccountName,

[Parameter()]
[System.String[]]
$AllowPasswordReplicationAccountName,
Expand All @@ -678,6 +752,30 @@ function Test-TargetResource

Write-Verbose -Message ($script:localizedData.TestingConfiguration -f $env:COMPUTERNAME, $DomainName)

if ($PSBoundParameters.ContainsKey('DelegatedAdministratorAccountName'))
{
if (-not $PSBoundParameters.ContainsKey('ReadOnlyReplica') -or $ReadOnlyReplica -ne $true)
{
New-InvalidOperationException -Message $script:localizedData.DelegatedAdministratorAccountNameNotRODC
}
}

if ($PSBoundParameters.ContainsKey('AllowPasswordReplicationAccountName'))
{
if (-not $PSBoundParameters.ContainsKey('ReadOnlyReplica') -or $ReadOnlyReplica -ne $true)
{
New-InvalidOperationException -Message $script:localizedData.AllowPasswordReplicationAccountNameNotRODC
}
}

if ($PSBoundParameters.ContainsKey('DenyPasswordReplicationAccountName'))
{
if (-not $PSBoundParameters.ContainsKey('ReadOnlyReplica') -or $ReadOnlyReplica -ne $true)
{
New-InvalidOperationException -Message $script:localizedData.DenyPasswordReplicationAccountNameNotRODC
}
}

if ($PSBoundParameters.ContainsKey('ReadOnlyReplica') -and $ReadOnlyReplica -eq $true)
{
if (-not $PSBoundParameters.ContainsKey('SiteName'))
Expand Down Expand Up @@ -737,6 +835,17 @@ function Test-TargetResource
$testTargetResourceReturnValue = $false
}

# If this is a read-only domain controller, check the delegated administrator
if ($existingResource.ReadOnlyReplica)
{
if ($PSBoundParameters.ContainsKey('DelegatedAdministratorAccountName') -and $existingResource.DelegatedAdministratorAccountName -ne $DelegatedAdministratorAccountName)
{
Write-Verbose -Message ($script:localizedData.DelegatedAdministratorAccountNameMismatch -f $existingResource.DelegatedAdministratorAccountName, $DelegatedAdministratorAccountName)

$testTargetResourceReturnValue = $false
}
}

if ($PSBoundParameters.ContainsKey('AllowPasswordReplicationAccountName') -and
$null -ne $existingResource.AllowPasswordReplicationAccountName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class MSFT_ADDomainController : OMI_BaseResource
[Write, Description("Specifies if the domain controller will be a Global Catalog (GC).")] Boolean IsGlobalCatalog;
[Read, Description("Returns the state of the Domain Controller.")] String Ensure;
[Write, Description("Indicates that the cmdlet installs the domain controller as an Read-Only Domain Controller (RODC) for an existing domain.")] Boolean ReadOnlyReplica;
[Write, Description("Specifies the user or group that is the delegated administrator of this Read-Only Domain Controller (RODC).")] String DelegatedAdministratorAccountName;
[Write, Description("Specifies an array of names of user accounts, group accounts, and computer accounts whose passwords can be replicated to this Read-Only Domain Controller (RODC).")] String AllowPasswordReplicationAccountName[];
[Write, Description("Specifies the names of user accounts, group accounts, and computer accounts whose passwords are not to be replicated to this Read-Only Domain Controller (RODC).")] String DenyPasswordReplicationAccountName[];
[Write, Description("Specifies one or more Flexible Single Master Operation (FSMO) roles to move to this domain controller. The current owner must be online and responding for the move to be allowed."), ValueMap{"DomainNamingMaster", "SchemaMaster", "InfrastructureMaster", "PDCEmulator", "RIDMaster"}, Values{"DomainNamingMaster", "SchemaMaster", "InfrastructureMaster", "PDCEmulator", "RIDMaster"}] String FlexibleSingleMasterOperationRole[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ ConvertFrom-StringData @'
CannotConvertToRODC = Cannot convert a existing domain controller to a Read-Only Domain Controller (RODC). (ADDC0023)
NotOwnerOfFlexibleSingleMasterOperationRole = The domain controller was expected to be the owner of the Flexible Single Master Operation (FSMO) role '{0}', but it is not. (ADDC0024)
MovingFlexibleSingleMasterOperationRole = The Flexible Single Master Operation (FSMO) role '{0}' is being moved from domain controller '{1}' to this domain controller. (ADDC0025)
DelegatedAdministratorAccountNameMismatch = There is a mismatch in DelegatedAdministratorAccountName. Got {0}, expected was {1}. (ADDC0026)
UpdatingDelegatedAdministratorAccountName = Updating the DelegatedAdministratorAccountName from the name {0} to the name {1}. (ADDC0027)
DelegatedAdministratorAccountNameNotRODC = You have specified 'DelegatedAdministratorAccountName', but this is not a Read-Only Domain Controller (RODC). (ADDC0028)
AllowPasswordReplicationAccountNameNotRODC = You have specified 'AllowPasswordReplicationAccountName', but this is not a Read-Only Domain Controller (RODC). (ADDC0029)
DenyPasswordReplicationAccountNameNotRODC = You have specified 'DenyPasswordReplicationAccountName', but this is not a Read-Only Domain Controller (RODC). (ADDC0030)
'@
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
Write - Boolean
Indicates that the cmdlet installs the domain controller as an Read-Only Domain Controller (RODC) for an existing domain.

.PARAMETER DelegatedAdministratorAccountName
Write - String
Specifies the user or group that is the delegated administrator of this Read-Only Domain Controller (RODC).

.PARAMETER AllowPasswordReplicationAccountName
Write - StringArray
Specifies an array of names of user accounts, group accounts, and computer accounts whose passwords can be replicated to this Read-Only Domain Controller (RODC).
Expand Down Expand Up @@ -331,6 +335,7 @@ Configuration ADDomainController_AddReadOnlyDomainController_Config
SafeModeAdministratorPassword = $SafeModePassword
ReadOnlyReplica = $true
SiteName = 'Default-First-Site-Name'
DelegatedAdministratorAccountName = 'contoso\adm.pvdi'
AllowPasswordReplicationAccountName = @('pvdi.test1', 'pvdi.test')
DenyPasswordReplicationAccountName = @('SVC_PVS', 'TA2SCVMM')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Configuration ADDomainController_AddReadOnlyDomainController_Config
SafeModeAdministratorPassword = $SafeModePassword
ReadOnlyReplica = $true
SiteName = 'Default-First-Site-Name'
DelegatedAdministratorAccountName = 'contoso\adm.pvdi'
AllowPasswordReplicationAccountName = @('pvdi.test1', 'pvdi.test')
DenyPasswordReplicationAccountName = @('SVC_PVS', 'TA2SCVMM')

Expand Down
Loading

0 comments on commit 8b4a7cd

Please sign in to comment.