Deploy Active Directory and Certificate Services in Azure Using Infrastructure-as-Code — Part 2

save money azure heroimg

In part two of this series on deploying Active Directory and a member server running certificate services in Microsoft Azure, I’ll show you how to add a PowerShell Desired State Configuration (DSC) resource to the project.

 

 

In part one, I explained how I created the JSON template that provisions the resources in Azure. I combined two templates from Microsoft’s Quickstart gallery and walked you through how the resources are provisioned. By the end of the first part, I’d covered the deployment of two domain controllers and a member server. But I still need to install and configure AD Certificate Services (ADCS) on the member server.

Add a Resource

Active Directory is configured on the two domain controllers using PowerShell DSC. DSC is Microsoft’s management platform based on PowerShell. It allows DevOps and system administrators to manage IT and development infrastructure using code. DSC uses a declarative model that lets you state how you’d like servers to be configured without having to worry about the ‘mechanics’. For more information on working with PowerShell DSC, see How Do I Create a Desired State Configuration? on Petri.

The first step is to add a PowerShell DSC resource to the third VM. Remember that this VM is a member of our domain.

  • Make sure that the azuredeploy.json file is open in the central pane.
  • Locate the VM in the JSON Outline panel on the left, right-click and select Add New Resource from the menu.
  • In the Add Resource dialogue, give the new resource a name. I called it provisionvm.
  • Select a VM from the Virtual machine drop-down menu. In this example, the VM resource is called [dnsLabelPrefix].
  • Click Add.
Add a PowerShell DSC resource to a project in Visual Studio (Image Credit: Russell Smith)
Add a PowerShell DSC Resource to a Project in Visual Studio (Image Credit: Russell Smith)

The azuredeploy.json template will be updated and the code that was added highlighted in the center panel. We need to make sure that the PowerShell DSC code will run only after the VM has been joined to the domain. In this case, I want to install certificate services as an enterprise root certification authority (CA), i.e. a CA that is integrated with Active Directory, so we need to wait until the server is not only provisioned but also joined to the domain. Let’s modify the dependsOn parameter to make sure the PowerShell DSC resource isn’t provisioned until after the domain join operation. By default, dependsOn for the resource looks like this:

          "dependsOn": [
            "[resourceId('Microsoft.Compute/virtualMachines', parameters('PKI'))]"

But we need to change it to this:

          "dependsOn": [
            "[resourceId('Microsoft.Compute/virtualMachines', parameters('PKI'))]",
            "[concat('Microsoft.Compute/virtualMachines/', parameters('PKI'),'/extensions/joindomain')]"

There are two more parameters that we need to modify. modulesUrl should be set to a variable name:

"modulesUrl": "[variables('pkiTemplateUri')]",

pkiTemplateUri is defined in the list of variables at the top of the azuredeploy.json and is set to the following path:

"pkiTemplateUri": "[concat(parameters('_artifactsLocation'),'/windows-powershell-dsc/DSC/provisionvm.ps1.zip', parameters('_artifactsLocationSasToken'))]",

Finally, configurationFunction should be set as follows:

"configurationFunction": "[variables('pkiConfigurationFunction')]",

And the pkiConfigurationFunction variable set like this:

"pkiConfigurationFunction": "provisionvm.ps1\\rootca",

Where provisionvm.ps1 is the name of the PowerShell DSC source code and rootca is the configuration name in the file that we want to call. Note that in the final version of the project, I changed the name of provisionvm.ps1 to PKI.ps1.

PowerShell DSC

Now let’s create the PowerShell DSC code that will deploy ADCS on the virtual machine. I wrote the code that follows and it is based on examples by Microsoft that show how to install Windows features and use the xAdcsDeployment resource. When you add a PowerShell DSC resource to the project, VS automatically creates a PowerShell file for you. You’ll be able to see it in Solution Explorer in the DSC folder and it will have the same name as you gave the resource that was added in the previous steps. There’s some sample code in the file that VS creates. You can safely delete it or use it as the basis for your own code.

Configure Active Directory Certificate Services Using PowerShell DSC (Image Credit: Russell Smith)
Configure Active Directory Certificate Services Using PowerShell DSC (Image Credit: Russell Smith)

The first step is to import two required DSC resources, xAdcsDeployment and PSDesiredStateConfiguration, using the Import-DscResource cmdlet. Then the ADCS bits are installed on the server. Because DSC uses a declarative syntax, we specify just that the component should be ‘Present’ and PowerShell will work out the rest. The same method is used to install the ADCS management tools. Finally, the xAdcsDeployment resource is used to configure ADCS once it is installed.

Configuration rootca
{
   param
   (
        [Parameter(Mandatory)]
        [String]$DomainName,

        [Parameter(Mandatory)]
        [System.Management.Automation.PSCredential]$Admincreds

    )

     Import-DscResource -ModuleName xAdcsDeployment, PSDesiredStateConfiguration

     Node localhost
     {

        # Install the ADCS Certificate Authority
        WindowsFeature ADCSCA {
            Name = 'ADCS-Cert-Authority'
            Ensure = 'Present'
        }
        
        # Configure the CA as Standalone Root CA
        xADCSCertificationAuthority ConfigCA
        {
            Ensure = 'Present'
            # Credential = $LocalAdminCredential
            CAType = 'EnterpriseRootCA'
            CACommonName = $Node.CACommonName
            CADistinguishedNameSuffix = $Node.CADistinguishedNameSuffix
            ValidityPeriod = 'Years'
            ValidityPeriodUnits = 20
            CryptoProviderName = 'RSA#Microsoft Software Key Storage Provider'
            HashAlgorithmName = 'SHA256'
            KeyLength = 4096
            DependsOn = '[WindowsFeature]ADCSCA' 
        }

            WindowsFeature RSAT-ADCS 
        { 
            Ensure = 'Present' 
            Name = 'RSAT-ADCS' 
            DependsOn = '[WindowsFeature]ADCSCA' 
        } 
        WindowsFeature RSAT-ADCS-Mgmt 
        { 
            Ensure = 'Present' 
            Name = 'RSAT-ADCS-Mgmt' 
            DependsOn = '[WindowsFeature]ADCSCA' 
        } 
     }
  }

The configuration is called rootca. You can choose any name you like. Notice that the code block that installs ADCS is called ADCSCA. Again, you can choose whatever name you want. In the code, you can see that DSC uses a parameter called DependsOn. This allows us to say that we won’t configure the CA until the ADCS server role is installed on the server.

 

 

 

And that’s it! But the real problems are only just about to start. Getting VS to successfully provision the resources in Azure is the hard part. See you in part three.