dsccommunity / CertificateDsc

DSC resources to simplify administration of certificates on a Windows Server.
https://dsccommunity.org
MIT License
122 stars 69 forks source link

Add support to export Cert as Base64 with CredentialExport #267

Open ghost opened 2 years ago

ghost commented 2 years ago

Problem description

I would like to have the ability to export a credential with DSC in base64 format. I can do this with the GUI on windows cert store but not with the DSC code.

Thanks

image

Verbose logs

No logs

DSC configuration

#This produces a cert in the DER encoding.  I would like the option for Base64
CertificateExport RootCertPem {
      Type         = 'CERT'
      FriendlyName = 'Root CA'
      Subject      = '%DN%'
      Path         = "C:\rootCert.cer"
    }

Suggested solution

N/A

Operating system the target node is running

OsName               : Microsoft Windows Server 2019 Datacenter
OsOperatingSystemSKU : DatacenterServerEdition
OsArchitecture       : 64-bit
WindowsVersion       : 1809
WindowsBuildLabEx    : 17763.1.amd64fre.rs5_release.180914-1434
OsLanguage           : en-US
OsMuiLanguages       : {en-US}

PowerShell version and build the target node is running

Name                           Value
----                           -----
PSVersion                      5.1.17763.2867
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17763.2867
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

CertificateDsc version

Name           Version Path
----           ------- ----
CertificateDsc 5.1.0   C:\Program Files\WindowsPowerShell\Modules\CertificateDsc\5.1.0\CertificateDsc.psd1
PlagueHO commented 2 years ago

Thanks for raising this @tkennedy-cf. This isn't currently supported because we use the Export-Certificate cmdlet internally - which doesn't support Base-64 encoded .CER (e.g. PEM file).

That said, it should be possible to take the .CER exported and encode it to Base-64 and wrap it.

For the Set-TargetResource:

        if ($Type -eq 'PEM')
        {
            $certificateBase64EncodedContent = [System.Convert]::ToBase64String($certs[0].Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert), [System.Base64FormattingOptions]::InsertLineBreaks)

           $pemContent = @'
-----BEGIN CERTIFICATE-----
$certificateBase64EncodedContent 
-----END CERTIFICATE-----
'@

            $setContentParameters = @{
                Path = $Path
                Force    = $true
            }
            $pemContent | Set-Content @setContentParameters
        }

I'd recommend a new function is created in CertificateDsc.Common that is Export-CertificatePem which takes similar parameters to Export-Certificate, so that it can accept the exportCertificateParameters. This will simplify the code and make testing easier. We'd mostly need to add unit tests to cover the new Export-CertificatePem function.

Updating Test-TargetResource is a lot easier:

                if ($Type -in @('Cert', 'P7B', 'SST', 'PEM'))
                {
                    $exportedCertificate.Import($Path)
                }

This is because the [System.Security.Cryptography.X509Certificates.X509Certificate2Collection]::Import() method will import a PEM file just fine.

So, theoretically this is a reasonably easy enhancement if anyone wants to take a crack at it and submit a PR.

Otherwise, I may have time sometime this weekend or next.

ghost commented 2 years ago

Sounds good, the enhancement would be greatly appreciated! As a work around I used certutil to do this in a Script resource

# Encode cert in base64
$retval = certutil -encode $OrgFile "$OrgFile-Base64.cer"
$certbase64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes("$OrgFile-Base64.cer"))