In my last post I described how to create a DC, in Azure, using DSC and ARM Templates. In this post, we will discuss how to automate the creation of a local – on premises – Acitve Directory Domain Services (ADDS) Domain Controller (DC) using DSC.
Overview
DSC has two modes: push mode and pull mode.
In push mode, you will author the configuration. You will then stage the configuration by creating MOF files. And finally, you will manually push the desired configuration onto the target server or node. The target server can be the local server or a remote server.
On the other hand, in DSC PULL mode, you author the configuration and stage it onto a designated Pull server. The target nodes contact the central pull server at regular intervals to obtain their desired configuration.
In our scenario, we will be using DSC in push mode. We will author the configuration and push it onto the local Windows server (not remotely).
Details
Prerequisites
On the target Windows Server (Windows Server 2008 R2 SP1 and Windows Server 2012 or 2012 R2):
- Download and install Windows Management Framework (WMF). This WMF 5.0 is currently available and is the recommended version.
- Copy the script below to the target server
- Open the script below in Powershell ISE as administrator
- Install the required Powershell modules using install-module: xActiveDirectory, xComputerManagement, xNetworking and xStorage.
Run the script
Run the script in Powershell ISE. The first command creates the .mof files which contain the desired configuration. The second command actually applies the configuration to the local server. After about half an hour and one reboot, you will have a fully functional Domain Controller with a new user (domain admin).
# Configure all of the settings we want to apply for this configuration $ConfigData = @{ AllNodes = @( @{ NodeName = 'localhost' MachineName = 'spfarm-ad' IPAddress = '10.0.0.4' InterfaceAlias = 'Ethernet' DefaultGateway = '10.0.0.1' PrefixLength = '24' AddressFamily = 'IPv4' DNSAddress = '127.0.0.1', '10.0.0.4' PSDscAllowPlainTextPassword = $true PSDscAllowDomainUser = $true } ) } Configuration BuildADDC { param ( [Parameter(Mandatory)] [String]$FQDomainName, [Parameter(Mandatory)] [PSCredential]$DomainAdminstratorCreds, [Parameter(Mandatory)] [PSCredential]$AdmintratorUserCreds, [Int]$RetryCount=5, [Int]$RetryIntervalSec=30 ) Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName xActiveDirectory, ` xComputerManagement, ` xNetworking, xStorage Node $AllNodes.NodeName { LocalConfigurationManager { ActionAfterReboot = 'ContinueConfiguration' ConfigurationMode = 'ApplyOnly' RebootNodeIfNeeded = $true } # Change Server Name xComputer SetName { Name = $Node.MachineName } # Networking xDhcpClient DisabledDhcpClient { State = 'Disabled' InterfaceAlias = $Node.InterfaceAlias AddressFamily = $Node.AddressFamily } xIPAddress NewIPAddress { IPAddress = $Node.IPAddress InterfaceAlias = $Node.InterfaceAlias PrefixLength = $Node.PrefixLength AddressFamily = $Node.AddressFamily } xDefaultGatewayAddress SetDefaultGateway { Address = $Node.DefaultGateway InterfaceAlias = $Node.InterfaceAlias AddressFamily = $Node.AddressFamily DependsOn = '[xIPAddress]NewIPAddress' } xDNSServerAddress SetDNS { Address = $Node.DNSAddress InterfaceAlias = $Node.InterfaceAlias AddressFamily = $Node.AddressFamily } # Install the Windows Feature for AD DS WindowsFeature ADDSInstall { Ensure = 'Present' Name = 'AD-Domain-Services' } # Make sure the Active Directory GUI Management tools are installed WindowsFeature ADDSTools { Ensure = 'Present' Name = 'RSAT-ADDS' } # Create the ADDS DC xADDomain FirstDC { DomainName = $FQDomainName DomainAdministratorCredential = $DomainAdminstratorCreds SafemodeAdministratorPassword = $DomainAdminstratorCreds DependsOn = '[xComputer]SetName','[xDefaultGatewayAddress]SetDefaultGateway','[WindowsFeature]ADDSInstall' } $domain = $FQDomainName.split('.')[0] xWaitForADDomain DscForestWait { DomainName = $domain DomainUserCredential = $DomainAdminstratorCreds RetryCount = $RetryCount RetryIntervalSec = $RetryIntervalSec DependsOn = '[xADDomain]FirstDC' } # xADRecycleBin RecycleBin { EnterpriseAdministratorCredential = $DomainAdminstratorCreds ForestFQDN = $domain DependsOn = '[xADDomain]FirstDC' } # Create an admin user so that the default Administrator account is not used xADUser FirstUser { DomainAdministratorCredential = $DomainAdminstratorCreds DomainName = $domain UserName = $AdmintratorUserCreds.UserName Password = $AdmintratorUserCreds Ensure = 'Present' DependsOn = '[xADDomain]FirstDC' } xADGroup AddToDomainAdmins { GroupName = 'Domain Admins' MembersToInclude = $AdmintratorUserCreds.UserName Ensure = 'Present' DependsOn = '[xADUser]FirstUser' } } } # Build MOF (Managed Object Format) files based on the configuration defined above # (in folder under current dir) # Local Admin is assigned BuildADDC -ConfigurationData $ConfigData ` -FQDomainName 'spdomain.local' ` -DomainAdminstratorCreds (get-credential -Message "Enter Admin Credentials" -UserName "Administrator" ) ` -AdmintratorUserCreds (get-credential -Message "Enter New Admin User Credentials" -UserName "admin1" ) # We now enforce the configuration using the command syntax below Start-DscConfiguration -Wait -Force -Path .\BuildADDC -Verbose -Debug
Lessons Learned
Since the Powershell xActiveDirectory module is being updated all the time, a DSC script that worked a year ago needs to be updated to work with WMF 5.0 (in the last quarter of 2016).
WMF 5.0 is included in the latest version of Windows 10 and included on Windows Server 2016.
Issues and Solutions
With some of the xActiveDirectory resources, the use of the fully qualified domain name (FQDN) produced an error: “Could not find mandatory property DomainName. Add this property and try again.”
Solution: use the first part of the domain name