Using PowerShell Desired State Configuration to build the first domain controller in your Active Directory forest

If you're a frequent reader of the blog articles on this site, then you know that I've been working on using Desired State Configuration to build my test lab environment that runs as Hyper-V VM's on my Windows 8.1 computer.

If you would like to know the current state of my test environment, see the previous blog article: Creating a Desired State Configuration Resource for Self Signed Certificates.

The certificate created in last week's blog has been exported and copied to the Windows 8.1 computer that I'm using to author and apply the DSC configuration from. This is a step that I'll need to revisit at some point in the future and take a look at automating it.

1Invoke-Command -ComputerName '192.168.29.108' {
2    Export-Certificate -Cert Cert:\LocalMachine\My\$((Get-ChildItem -Path Cert:\LocalMachine\My |
3    Where-Object Subject -eq 'CN=192.168.29.108').Thumbprint) -FilePath C:\tmp\192.168.29.108.cer
4
5    Get-NetFirewallRule -DisplayGroup 'File and Printer Sharing' |
6    Set-NetFirewallRule -Enabled True
7} -Credential (Get-Credential)

dc-dsc0a.jpg

Today I'll be changing the name of the VM to Test01, changing the IP address from DHCP to a statically assigned one, and turning it into the first domain controller in my test Active Directory forest.

My initialization script contains all the values instead of hard coding them into the actual DSC configuration itself:

 1$ConfigData = @{
 2    AllNodes = @(
 3        @{
 4            NodeName = '192.168.29.108'
 5            MachineName = 'Test01'
 6            DomainName = 'mrtest.local'
 7            IPAddress = '192.168.29.150'
 8            InterfaceAlias = 'Ethernet'
 9            DefaultGateway = '192.168.29.1'
10            SubnetMask = '24'
11            AddressFamily = 'IPv4'
12            DNSAddress = '127.0.0.1', '192.168.29.150'
13            CertificateFile = 'C:\tmp\192.168.29.108.cer'
14            Thumbprint = '6229581CADD8EFCD6988172D379184A0606DB079'
15        }
16    )
17}

A fairly simple DSC configuration is used to accomplish the tasks. As you can see, there are three DSC resources that are being used that don't ship in the box. Those were downloaded in another previous blog article: Automate the installation of DSC Resource Kit Wave 9 resources with PowerShell Desired State Configuration.

 1Configuration BuildTest01 {
 2    param (
 3        [Parameter(Mandatory)]
 4        [pscredential]$safemodeCred,
 5
 6        [Parameter(Mandatory)]
 7        [pscredential]$domainCred,
 8
 9        [pscredential]$Credential
10    )
11
12    Import-DscResource -Module xActiveDirectory, xComputerManagement, xNetworking
13
14    Node $AllNodes.NodeName {
15        LocalConfigurationManager {
16            CertificateID = $Node.Thumbprint
17            RebootNodeIfNeeded = $true
18        }
19        xComputer SetName {
20          Name = $Node.MachineName
21        }
22        xIPAddress SetIP {
23            IPAddress = $Node.IPAddress
24            InterfaceAlias = $Node.InterfaceAlias
25            DefaultGateway = $Node.DefaultGateway
26            SubnetMask = $Node.SubnetMask
27            AddressFamily = $Node.AddressFamily
28        }
29        xDNSServerAddress SetDNS {
30            Address = $Node.DNSAddress
31            InterfaceAlias = $Node.InterfaceAlias
32            AddressFamily = $Node.AddressFamily
33        }
34        WindowsFeature ADDSInstall {
35            Ensure = 'Present'
36            Name = 'AD-Domain-Services'
37        }
38        xADDomain FirstDC {
39            DomainName = $Node.DomainName
40            DomainAdministratorCredential = $domainCred
41            SafemodeAdministratorPassword = $safemodeCred
42            DependsOn = '[xComputer]SetName', '[xIPAddress]SetIP', '[WindowsFeature]ADDSInstall'
43        }
44    }
45}

The configuration is run which loads it into memory like a function, and then it is called with the necessary parameters and their values to create the MOF files:

1BuildTest01 ConfigurationData $ConfigData -Credential (Get-Credential)

dc-dsc1a.jpg

We need to tell the test01 VM what the thumbprint of the certificate is that will be used to encrypt the passwords in the MOF file so it will know which one to use to decrypt them. We'll also change the RebootNodeIfNeeded to tell it to restart if needed. These changes are applied to the DSC LCM (Local Configuration Manager) on test01:

1Set-DscLocalConfigurationManager -Path .\BuildTest01 -Credential (Get-Credential) -Verbose

dc-dsc2a.jpg

Now to apply (push) the actual configuration to test01:

1Start-DscConfiguration -Wait -Path .\BuildTest01 -Credential (Get-Credential) -Verbose -Force

dc-dsc3a.jpg

Notice that in the previous set of results, the computer name was changed and the machine rebooted before making the other configuration changes.

You might be wondering how your interactive session is going to reconnect and apply the remainder of the configuration? especially when you consider that both the computer name and IP address are going to be changed. How's it going to know what to connect back to? It's not. The MOF file was sent to the destination node and it will finish the configuration on its own. You won't see that in your interactive window and you'll need to give the machine a few minutes to change the IP address, and turn itself into a domain controller. Once those steps are complete, the machine will reboot again and it will be a domain controller:

1Invoke-Command -ComputerName Test01 {
2    Get-ADDomainController | Select-Object -Property Name, Domain, IPv4Address
3} -Credential (Get-Credential)

dc-dsc4a.jpg

µ