Managing Certificates in DSC

I created and posted a function and DSC resource to help people manage certificate rotation in DSC so it stays automated.  It was initially built to work with some of my other functions but I’ve “generalized it” for regular consumption.  All parts are posted in the PowerShell Gallery so you can download them using a simple Install-module cmdlet from PowerShellGet.  You can get started right away with these tools by grabbing them with a simple:

install-module DSCHelperfunctions

install-module cLCMCertManager

The use-case is pretty simple:  a lot of people out there have PKI deployed now, with certificate templates and GPOs in place to auto-enroll and renew certificates.  What’s more, DSC requires the use of certificates in order to encrypt password information in the mof files being pulled.  While it’s easy enough to configure your LCM for the appropriate thumbprint, rotating that certificate as it expires is a bit trickier, requiring you to keep your Configuration meta data up-to-date.  So I aimed to fix that.

Conceptual Overview

The way things work is actually fairly strait forward:  Microsoft already provides a decent method for distributing certificates and keeping them up-to-date through the CA/PKI infrastructure, so I won’t go through it here.  A DSC Resource is defined for every node that goes through the following process every configuration cycle:

  1. Checks the thumbprint currently assigned to the Local Configuration Manager.
  2. Checks the computer’s local certificate store, filtering the matches against criteria specified in the configuration, and then picking the certificate with the longest expiration date.
  3. If the two thumbprints don’t match, the resource copies a new public key .cer file to a defined location (UNC path), and names the file after the node (BIOS name, FQDN, and GUID are all configurable)

For the machine building the mof, the DSCHelperfunctions module adds a new function that is capable of taking in the configurationdata hash table, reading said UNC path then returning an updated hash table that contains thumbprint and certificate file locations.  By running the configurationdata through this function BEFORE doing any mof generation, the mof and meta files created will always be based on the best possible certificate/thumbprint.

Setting up the Environment

The first thing that needs to be done is a repository needs to be setup to hold the certificate files. This can be any SMB share that the various nodes will be able to resolve and write to. Using one of my previous works as leverage, I actually created a function to build that too, but you don’t need to use it. Still, if you’re feeling particularly lazy, you can run this on your Pull Server:

Install-DSCHelperStores

 

 

 

This will create two folders if they don’t exist: “NodesCertificates” and “Management”. In the management folder it will create sample password file as well. This is literally just a simple export of my previous “DSC-Manager” toolset, slimmed down to be more practical for every-day use. The created “NodeCertificates” folder will automatically have a share created called “certstore”, and domain computers will be given write permissions. That’s pretty much all you have to do to get things working: have an smb share computers can write to.

Setting up the Configuration

There are actually two types of MOF files that can be generated when you perform a configuration: a meta.mof and the general mof. The meta.mof is a special configuration class that only contains information on configuration the LCM on the node. This is basically what will be leveraged to reconfigure the nodes as new thumbprints are made available by the LCMCertManager Resource.

So below is a (extremely) simple configuration with configurationdata, complete with leveraged resources.

Configuration Sample
{
  Import-DSCResource -ModuleName xNetworking, cLCMCertManager
  Node $AllNodes.NodeName {

    #LCM Update rules
    LocalConfigurationManager {
      CertificateId = $Node.Thumbprint
      RebootNodeIfNeeded = $true
      AllowModuleOverwrite = $true
      RefreshMode = “Pull”
      RefreshFrequencyMins = 30
      ConfigurationModeFrequencyMins = 30
      ConfigurationMode = “ApplyAndAutoCorrect”
      DownloadManagerCustomData = @{ServerURL = “https://dsc.contoso.com:8080/PSDSCPullServer.svc”}
    }

    #This is for the Cert update rules
    cLCMCertUpdate CertUpdateBase {
      OutPath = “\\DSC-01\CertStore”
      OutputName = “Computer”
      TemplateName = “Lab Computer”
    }

    xDNSServerAddress DNSBase {
      Address = $Node.DNSServerAddresses
      InterfaceAlias = “Ethernet”
      AddressFamily = “IPV4”
      }
    }
  }

$Nodes = @{
  AllNodes = @(
    @{
      NodeName = “Server01”
      DNSServerAddresses = @(‘192.168.1.100′,’192.168.1.101’)
    }
  );
}

#Build Configuration
$Nodes = Update-ConfigurationDataCertificates -ConfigurationData $Nodes
Sample-ConfigurationData $Nodes

What the above is, is a simple DNS update configuration with two extra resources added. With the inclusion of the LocalConfigurationManager resource, settings will get passed to the local LCM. Notice the inclusion of the $node.thumbprint variable that ISN’T defined in the $Nodes hashtable. This is added automatically by the Update-ConfigurationDataCertificates function, in addition to the certificate path. The nice part here is that with a simple task sequence or possibly a more complicated script management tool, you can run this configuration semi-regularly. Every time the configuration runs it will:

  1. Pull in a certificate with a matching file name to the nodename.
  2. Push said certificate’s thumbprint into the meta.mof.
  3. If passwords or other information needs to be encrypted in the “Regular” mof, it will be encrypted by the certificate.

So now, as long as the rate at which this script runs is more frequent than the certificate renewal cycle of the nodes …. You have a self-maintaining certificate model. Assuming you have certificates that expire annually, with a renewal period of 10 months. That means:

  1. Every 30 minutes (for the next 10 months), the cLCMCertUpdate resource will find the current cert to be the best match (thumbprints in LCM match thumbprint in query), and everything reports back good.
  2. At month 11, a new certificate is auto-enrolled by the Server. The current LCM and downloaded mof will continue to function, BUT cLCMCertUpdate will see the mismatch (there are two valid certificate now, and the newer on has a later expiration date), and copy a new public key over the SMB share, over-writing the old one. Every 30 minutes it will now check the LCM thumbprint (fail), then check the thumbprint in the certstore share (pass).
  3. At some interval (let’s assuming weekly), the new configuration will get generated and placed on the pull server. This will update the LCM configuration with the new thumbprint and the server will return to normal functionality in step 1. As any new mof gets generated at the same time as the meta … the new configuration will get signed with the new certificate at the same time … so no errors will generate.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s