Collecting CA Certificates for DSC Configuration

4 minute read

The Goal

Microsoft PFE Ashely McGlone recommends that each node managed by DSC (Desired State Configuration) have unique certificate for protecting credentials.

Mof Credential Security Chart

Starting in WMF 5.0 .MOF are encrypted at rest on the Node. But that is not the case for the file on the pull server. So I’m going on the assumption that this is still a best practice.

The problem with that is getting the certificates either from the node or from a CA (Certificate Authority) to the DSC development workstation or CI/CD (Continuous Integration/Continuous Deployment) server. I’m going to cover one method.

Pre-requisites

For this I’m going to be using PowerShell Automated Lab Environment and it’s Configuration called “devops-powershell-fundamentals”

This will generate the following:

  1. DC1 - Domain Controller and Certificate Authority
  2. S1, S2 - Member servers
  3. N1 - Nano server (not used)
  4. Cli1 - Windows 10 workstation
  5. NAT virtual switch and static IP’s
  6. Certificate Template called “DSC Template”
  7. Auto-Enrollment GPO

Once that is up and running we can connect to cli1 via PowerShell Direct

Demo

I’m going to start with installing PKITools from the PowerShell Gallery (and selecting Yes to install NuGet and allow use of untrusted rpo, this is new lab after all)

Install-Module PKITools
Get-Command -Module PkiTools

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Get-ADCertificateTemplate                          1.6        PkiTools
Function        Get-CaLocationString                               1.6        PkiTools
Function        Get-CertificatAuthority                            1.6        PkiTools
Function        Get-CertificateTemplateOID                         1.6        PkiTools
Function        Get-IssuedCertificate                              1.6        PkiTools

The one I want to focus on is Get-IssuedCertificate. As part of a DSC build process I want to collect the public certificates for each node. Pulling the certificate from each node is one option, but not practical in large network, and may not even be be possible due to lack of connectivity. Thankfully all the public certificates also reside on the Certificate Authority that issues them.

In our lab there is only one domain and one CA (also the DC. no not do that in production) So the code will be simple.

First lets look at the parameters.

SYNTAX
    Get-IssuedCertificate [[-ExpireInDays] <Int32>] [[-CAlocation] <String[]>] [[-Properties] <String[]>]
    [[-CertificateTemplateOid] <String>] [[-CommonName] <String>] [[-Credential] <PSCredential>] [<CommonParameters>]

No parameters are required. lets see what it does

[hv01]: [Cli1]: PS C:\> Get-IssuedCertificate


Issued Common Name          :
Certificate Expiration Date : 4/18/2018 3:40:05 AM
Certificate Effective Date  : 4/18/2017 3:40:05 AM
Certificate Template        : 1.3.6.1.4.1.311.21.8.8376484.9891361.12404633.14452813.1016466.111.1.29
Issued Request ID           : 2
Certificate Hash            : f2 4e db 00 12 19 68 79 98 0b 6a 95 47 6d 7a c6 a7 40 e7 63
Request Disposition Message : Issued
Requester Name              : COMPANY\DC1$
Binary Certificate          : -----BEGIN CERTIFICATE-----
                              MIIF6jCCBNKgAwIBAgITUQAAAAL5xXyLo72OVAAAAAAAAjANBgkqhkiG9w0BAQsF
                              ADBZMRAwDgYDVQQKEwdDb21wYW55MRAwDgYDVQQIEwdBcml6b25hMRAwDgYDVQQH
                              EwdQaG9lbml4MQswCQYDVQQGEwJVUzEUMBIGA1UEAxMLQ29tcGFueS5QcmkwHhcN
                              MTcwNDE4MDM0MDA1WhcNMTgwNDE4MDM0MDA1WjAAMIIBIjANBgkqhkiG9w0BAQEF
                              AAOCAQ8AMIIBCgKCAQEAxjtOVDCixBoUEOWG1WKwPqw0DY77upmE0E4Bfc6CV94g
                              X5ewYtagk7f8KvfigDaoq20qCNzFfaBprseL/0JoKPBY05Ws9O98pfAP639MGP6U
                              MCbgXZ8ILhtoWZCqHi+S8UVyu7D2meyyl54IgeoVcb0MBISWoGyyJ5tzAWYX1XQL
                              /0tnQ4YoWRcJulW7Qvn0kUhk6ooe9Mot4gCD0jPE/QjJ/loJDHO+aCRxsMwEil87
                              KqGKfEcS54dV+g6wRhgxlrfi8b1NDwhKcpgglSzhtmBEUY72m1S5AxuL7V90ZxNU
                              NQ/CBboy98NKri8RbmyvypAQ47MMyadVVmPLsAgGJwIDAQABo4IDAjCCAv4wNgYJ
                              KwYBBAGCNxUHBCkwJwYfKwYBBAGCNxUIg/+hJITb3CGF9Y8ZhvKQTb6FEm8BHQIB
                              cwIBADAUBgNVHSUEDTALBgkrBgEEAYI3FRMwDgYDVR0PAQH/BAQDAgWgMBwGCSsG
                              AQQBgjcVCgQPMA0wCwYJKwYBBAGCNxUTMHgGCSqGSIb3DQEJDwRrMGkwDgYIKoZI
                              hvcNAwICAgCAMA4GCCqGSIb3DQMEAgIAgDALBglghkgBZQMEASowCwYJYIZIAWUD
                              BAEtMAsGCWCGSAFlAwQBAjALBglghkgBZQMEAQUwBwYFKw4DAgcwCgYIKoZIhvcN
                              AwcwHQYDVR0OBBYEFOB1zbkBT8m9NW7DRh7xW13OjSmLMB8GA1UdIwQYMBaAFA+9
                              p4ww6yyPs/vD4ugUNRM24pWIMIHFBgNVHR8Egb0wgbowgbeggbSggbGGga5sZGFw
                              Oi8vL0NOPUNvbXBhbnkuUHJpLENOPURDMSxDTj1DRFAsQ049UHVibGljJTIwS2V5
                              JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1Db21w
                              YW55LERDPVByaT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0
                              Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwgb0GCCsGAQUFBwEBBIGwMIGtMIGq
                              BggrBgEFBQcwAoaBnWxkYXA6Ly8vQ049Q29tcGFueS5QcmksQ049QUlBLENOPVB1
                              YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRp
                              b24sREM9Q29tcGFueSxEQz1Qcmk/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENs
                              YXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwPgYDVR0RAQH/BDQwMqAfBgkrBgEE
                              AYI3GQGgEgQQezARELeYdUOiN2P2QTxNl4IPREMxLkNvbXBhbnkuUHJpMA0GCSqG
                              SIb3DQEBCwUAA4IBAQBCV12I9eIaFLRFsgzbhMizfufvtCOI/EKAOsEYCxI9HFKJ
                              H2HfC0lh7eEZABFQKPNx8XgCHCm5skzdR5oHLbtTwrnky2YJkFnuNOgTF/tuunoU
                              p3+X0Kk3YH88wrv+YPE37PtqF/fJnZvEUzPfxRiaiOFaTisEIXfAxTvVYVBSwK9H
                              oSgH5GTEblvlmiw6LD7JZYqrmYFCPQdB/mj+aOPjyeFClneGH2u8sxKCZHiJ/RWX
                              wQJn8DO5ACctnLC8mH70HR5vVRJ0yFX6vrpnRyJEBSpawAYFK1vPf7Wks+gLSw4q
                              g7ASEJG/MJK0oJpBosOKKGr+jMnEx6BTs1NJ3d0l
                              -----END CERTIFICATE-----

PSComputerName              : DC1.Company.Pri
RunspaceId                  : 146e5d7a-b85a-4540-9360-fea7413a9978

Issued Common Name          :
Certificate Expiration Date : 4/18/2018 3:40:07 AM
Certificate Effective Date  : 4/18/2017 3:40:07 AM
Certificate Template        : 1.3.6.1.4.1.311.21.8.8376484.9891361.12404633.14452813.1016466.111.1.28

~~~~~~~~SNIP~~~~~~~~~~~~~

                              BgkrBgEEAYI3UAEwHQYDVR0OBBYEFKYaQhzh28O8Sy4jBG5/63E59OzBMB8GA1Ud
                              IwQYMBaAFA+9p4ww6yyPs/vD4ugUNRM24pWIMIHFBgNVHR8Egb0wgbowgbeggbSg
                              gbGGga5sZGFwOi8vL0NOPUNvbXBhbnkuUHJpLENOPURDMSxDTj1DRFAsQ049UHVi
                              bGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlv
                              bixEQz1Db21wYW55LERDPVByaT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jh
                              c2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwgb0GCCsGAQUFBwEB
                              BIGwMIGtMIGqBggrBgEFBQcwAoaBnWxkYXA6Ly8vQ049Q29tcGFueS5QcmksQ049
                              QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNv
                              bmZpZ3VyYXRpb24sREM9Q29tcGFueSxEQz1Qcmk/Y0FDZXJ0aWZpY2F0ZT9iYXNl
                              P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwGwYDVR0RBBQwEoIQ
                              Q2xpMS5Db21wYW55LlByaTANBgkqhkiG9w0BAQsFAAOCAQEAFt8fD8dq7WdYxldl
                              648SS8KkqEeqUv4cBXt5/GBLBO/Cr7JB1m5K8U3VrjzwMgyU4n01h0xeJxYeHIvA
                              WZ1Fy8BXSzurH3MOcbC0jKuqezzXAJIpVAfkHB0UBKx+OnZes21aGXjb0ZHTv+lv
                              3lx6Wrc051RD+eDDLz0/+kLU6MRgJHTO8qlgRDRjRSqU7dcU1TKFmpij1IzWjvJb
                              GU2qHCfAnhWr8b+lMjvRMXkBxQjRF9kmMdhQxhR+nWN0/056wpr7/bukwGzPBKAU
                              HfFNFXqNT8nc79rB7IW4T6xZteEm0zG/TTNpIjL74/MGDBzFG3MTDE3i6ks9DoF/
                              9XDyDg==
                              -----END CERTIFICATE-----

PSComputerName              : DC1.Company.Pri
RunspaceId                  : 146e5d7a-b85a-4540-9360-fea7413a9978

That got every issued certificate for every CA on the current domain. More then I need. Obviously we need to trim that down to just the DSC certificates. for that we will need to specify -CertificateTemplateOID. Lets look at the help for that parameter.

[hv01]: [Cli1]: PS C:\> help Get-IssuedCertificate -Parameter CertificateTemplateOid

-CertificateTemplateOid <String>
    Filter on Certificate Template OID (use Get-CertificateTemplateOID)

    Required?                    false
    Position?                    4
    Default value
    Accept pipeline input?       false
    Accept wildcard characters?  false

Good it has a function to get the OID lets look at that.

SYNTAX
    Get-CertificateTemplateOID [-Name] <String> [[-Domain] <String>] [-WhatIf] [-Confirm] [<CommonParameters>]

Only the -Name is required. That I know.

[hv01]: [Cli1]: PS C:\> Get-CertificateTemplateOID DSCTemplate
1.3.6.1.4.1.311.21.8.16187918.14945684.15749023.11519519.4925321.197.13392998.8282280

And I though GUIDS were an eye full.

Get-IssuedCertificate also has a -Propterties paramaters lets look at that.

[hv01]: [Cli1]: PS C:\> help Get-IssuedCertificate -Parameter Properties

-Properties <String[]>
    Fields in the Certificate Authority Database to Export

    Required?                    false
    Position?                    3
    Default value                (
                'Issued Common Name',
                'Certificate Expiration Date',
                'Certificate Effective Date',
                'Certificate Template',
                #'Issued Email Address',
                'Issued Request ID',
                'Certificate Hash',
                #'Request Disposition',
                'Request Disposition Message',
                'Requester Name',
            'Binary Certificate' )
    Accept pipeline input?       false
    Accept wildcard characters?  false

For collecting the Certificates I only need the ‘Issued Common Name’ and ‘Binary Certificate’

[hv01]: [Cli1]: PS C:\> $DSCCerts = Get-IssuedCertificate -CertificateTemplateOid (Get-CertificateTemplateOID -Name 'DSC
Template') -Properties 'Issued Common Name', 'Binary Certificate'
[hv01]: [Cli1]: PS C:\>
[hv01]: [Cli1]: PS C:\> $DSCCerts.Count
4

So that got me 4 certs. Now I can step through each one and save them.

[hv01]: [Cli1]: PS C:\> mkdir c:\certs


    Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        4/21/2017   7:12 AM                certs


[hv01]: [Cli1]: PS C:\> foreach ($cert in $DSCCerts)
>> {
>>     set-content -path "c:\certs\$($cert.'Issued Common Name').cer" -Value $cert.'Binary Certificate' -Encoding Ascii
>> }
[hv01]: [Cli1]: PS C:\> dir c:\certs


    Directory: C:\certs


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        4/21/2017   7:12 AM           1982 Cli1.Company.Pri.cer
-a----        4/21/2017   7:12 AM           1978 DC1.Company.Pri.cer
-a----        4/21/2017   7:12 AM           1972 S1.Company.Pri.cer
-a----        4/21/2017   7:12 AM           1972 S2.Company.Pri.cer

Now I have the certificate files for each node I can use for DSC.

Comments

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...