DSCResources/MSFT_xADDomainController/MSFT_xADDomainController.psm1
# # xADDomainController: DSC resource to install a domain controller in Active # Directory. # ## Import the common AD functions $adCommonFunctions = Join-Path ` -Path (Split-Path -Path $PSScriptRoot -Parent) ` -ChildPath '\MSFT_xADCommon\MSFT_xADCommon.psm1' Import-Module -Name $adCommonFunctions <# .SYNOPSIS Returns the current state of the certificate that may need to be requested. .PARAMETER DomainName Provide the FQDN of the domain the Domain Controller is being added to. .PARAMETER DomainAdministrationCredential Provide the Domain Admin credentials to be able to promote a new Domain Controller. This is a PSCredential. .PARAMETER SafemodeAdministratorPassword Provide a password that will be used to set the DSRM password. This is a PSCredential. .PARAMETER DatabasePath Provide the path where the NTDS.dit will be created and stored. .PARAMETER LogPath Provide the path where the logs for the NTDS will be created and stored. .PARAMETER SysvolPath Provide the path where the Sysvol will be created and stored. .PARAMETER SiteName Provide the name of the site you want the Domain Controller to be added to. #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $DomainName, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $DomainAdministratorCredential, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $SafemodeAdministratorPassword, [Parameter()] [System.String] $DatabasePath, [Parameter()] [System.String] $LogPath, [Parameter()] [System.String] $SysvolPath, [Parameter()] [System.String] $SiteName ) $returnValue = @{ DomainName = $DomainName Ensure = $false } try { Write-Verbose -Message "Resolving '$($DomainName)' ..." $domain = Get-ADDomain -Identity $DomainName -Credential $DomainAdministratorCredential if ($null -ne $domain) { Write-Verbose -Message "Domain '$($DomainName)' is present. Looking for DCs ..." try { $dc = Get-ADDomainController -Identity $env:COMPUTERNAME -Credential $DomainAdministratorCredential Write-Verbose -Message "Found domain controller '$($dc.Name)' in domain '$($dc.Domain)'." if ($dc.Domain -eq $DomainName) { Write-Verbose -Message "Current node '$($dc.Name)' is already a domain controller for domain '$($dc.Domain)'." $serviceNTDS = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' $serviceNETLOGON = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters' $returnValue.Ensure = $true $returnValue.DatabasePath = $serviceNTDS.'DSA Working Directory' $returnValue.LogPath = $serviceNTDS.'Database log files path' $returnValue.SysvolPath = $serviceNETLOGON.SysVol -replace '\\sysvol$', '' $returnValue.SiteName = $dc.Site } } catch { if ($error[0]) {Write-Verbose $error[0].Exception} Write-Verbose -Message "Current node does not host a domain controller." } } } catch [System.Management.Automation.CommandNotFoundException] { if ($error[0]) {Write-Verbose $error[0].Exception} Write-Verbose -Message "Current node is not running AD WS, and hence is not a domain controller." } $returnValue } <# .SYNOPSIS Returns the current state of the certificate that may need to be requested. .PARAMETER DomainName Provide the FQDN of the domain the Domain Controller is being added to. .PARAMETER DomainAdministrationCredential Provide the Domain Admin credentials to be able to promote a new Domain Controller. This is a PSCredential. .PARAMETER SafemodeAdministratorPassword Provide a password that will be used to set the DSRM password. This is a PSCredential. .PARAMETER DatabasePath Provide the path where the NTDS.dit will be created and stored. .PARAMETER LogPath Provide the path where the logs for the NTDS will be created and stored. .PARAMETER SysvolPath Provide the path where the Sysvol will be created and stored. .PARAMETER SiteName Provide the name of the site you want the Domain Controller to be added to. .PARAMETER InstallationMediaPath Provide the path for the IFM folder that was created with ntdsutil. This should not be on a share but locally to the Domain Controller being promoted. #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $DomainName, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $DomainAdministratorCredential, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $SafemodeAdministratorPassword, [Parameter()] [System.String] $DatabasePath, [Parameter()] [System.String] $LogPath, [Parameter()] [System.String] $SysvolPath, [Parameter()] [System.String] $SiteName, [Parameter()] [System.String] $InstallationMediaPath ) # Debug can pause Install-ADDSDomainController, so we remove it. $parameters = $PSBoundParameters.Remove("Debug") $parameters = $PSBoundParameters.Remove('InstallationMediaPath') $targetResource = Get-TargetResource @PSBoundParameters if ($targetResource.Ensure -eq $false) { ## Node is not a domain controllr so we promote it Write-Verbose -Message "Checking if domain '$($DomainName)' is present ..." $domain = $null; try { $domain = Get-ADDomain -Identity $DomainName -Credential $DomainAdministratorCredential } catch { if ($error[0]) {Write-Verbose $error[0].Exception} throw (New-Object -TypeName System.InvalidOperationException -ArgumentList "Domain '$($DomainName)' could not be found.") } Write-Verbose -Message "Verified that domain '$($DomainName)' is present, continuing ..." $params = @{ DomainName = $DomainName SafeModeAdministratorPassword = $SafemodeAdministratorPassword.Password Credential = $DomainAdministratorCredential NoRebootOnCompletion = $true Force = $true } if ($DatabasePath -ne $null) { $params.Add("DatabasePath", $DatabasePath) } if ($LogPath -ne $null) { $params.Add("LogPath", $LogPath) } if ($SysvolPath -ne $null) { $params.Add("SysvolPath", $SysvolPath) } if ($SiteName -ne $null -and $SiteName -ne "") { $params.Add("SiteName", $SiteName) } if (-not [string]::IsNullOrWhiteSpace($InstallationMediaPath)) { $params.Add("InstallationMediaPath", $InstallationMediaPath) } Install-ADDSDomainController @params Write-Verbose -Message "Node is now a domain controller for '$($DomainName)'." # Signal to the LCM to reboot the node to compensate for the one we # suppressed from Install-ADDSDomainController $global:DSCMachineStatus = 1 } elseif ($targetResource.Ensure) { ## Node is a domain controller. We check if other properties are in desired state if ($PSBoundParameters["SiteName"] -and $targetResource.SiteName -ne $SiteName) { ## DC is not in correct site. Move it. Write-Verbose "Moving Domain Controller from '$($targetResource.SiteName)' to '$SiteName'" Move-ADDirectoryServer -Identity $env:COMPUTERNAME -Site $SiteName -Credential $DomainAdministratorCredential } } } <# .SYNOPSIS Returns the current state of the certificate that may need to be requested. .PARAMETER DomainName Provide the FQDN of the domain the Domain Controller is being added to. .PARAMETER DomainAdministrationCredential Provide the Domain Admin credentials to be able to promote a new Domain Controller. This is a PSCredential. .PARAMETER SafemodeAdministratorPassword Provide a password that will be used to set the DSRM password. This is a PSCredential. .PARAMETER DatabasePath Provide the path where the NTDS.dit will be created and stored. .PARAMETER LogPath Provide the path where the logs for the NTDS will be created and stored. .PARAMETER SysvolPath Provide the path where the Sysvol will be created and stored. .PARAMETER SiteName Provide the name of the site you want the Domain Controller to be added to. .PARAMETER InstallationMediaPath Provide the path for the IFM folder that was created with ntdsutil. This should not be on a share but locally to the Domain Controller being promoted. #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $DomainName, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $DomainAdministratorCredential, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $SafemodeAdministratorPassword, [Parameter()] [System.String] $DatabasePath, [Parameter()] [System.String] $LogPath, [Parameter()] [System.String] $SysvolPath, [Parameter()] [System.String] $SiteName, [Parameter()] [System.String] $InstallationMediaPath ) if ($PSBoundParameters.SiteName) { if (-not (Test-ADReplicationSite -SiteName $SiteName -DomainName $DomainName -Credential $DomainAdministratorCredential)) { throw (New-Object -TypeName System.InvalidOperationException -ArgumentList "Site '$($SiteName)' could not be found.") } } $isCompliant = $true try { $parameters = $PSBoundParameters.Remove("Debug") $parameters = $PSBoundParameters.Remove('InstallationMediaPath') $existingResource = Get-TargetResource @PSBoundParameters $isCompliant = $existingResource.Ensure if ([System.String]::IsNullOrEmpty($SiteName)) { #If SiteName is not specified confgiuration is compliant } elseif ($existingResource.SiteName -ne $SiteName) { Write-Verbose "Domain Controller Site is not in a desired state. Expected '$SiteName', actual '$($existingResource.SiteName)'" $isCompliant = $false } } catch { if ($error[0]) {Write-Verbose $error[0].Exception} Write-Verbose -Message "Domain '$($DomainName)' is NOT present on the current node." $isCompliant = $false } $isCompliant } Export-ModuleMember -Function *-TargetResource |