Functions/Set-CertFile.ps1
function Set-CertFile { <# .SYNOPSIS Persists a given certificate to file .DESCRIPTION Compares the current cert and overwrites if different based on thumbprint. Certificate is PFX or PEM format obtained from Get-Cert. If PfxPassword is specified, the file is considered to be PFX. Otherwise, it is considered to be PEM format. .OUTPUTS $True if cert was written to file. $False if cert was not written to file. .EXAMPLE Set-CertFile -Certificate $pfxCert -CertFile some.mysite.com.pfx -PfxPassword "!234SECRETbc123" Stores the PFX certificate in specified file. .EXAMPLE Set-CertFile -Certificate $pemCert -CertFile some.mysite.com.pem Stores the PEM formatted certificate in specified file. #> [OutputType([bool])] param ( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [string] $Certificate, [Parameter(Mandatory = $true)] [string] $CertFile, [Parameter(Mandatory = $false)] [string] $PfxPassword ) # Certificate is base64 encoded PFX or PEM $isPem = $Certificate.StartsWith("-----BEGIN") if ($isPem) { if (-Not "PemCertImporter" -as [type]) { $source = @" using System; using System.Security.Cryptography.X509Certificates; public class PemCertImporter { public static X509Certificate2Collection GetCertFromPem(string pem) { pem = pem.Replace("-----END CERTIFICATE-----", ""); var parts = pem.Split(new[] { "-----BEGIN CERTIFICATE-----" }, StringSplitOptions.RemoveEmptyEntries); var result = new X509Certificate2Collection(); foreach (var part in parts) { var cleaned = part.Trim(); if (string.IsNullOrWhiteSpace(cleaned)) { continue; } result.Import(Convert.FromBase64String(cleaned)); } return result; } } "@ Add-Type -TypeDefinition $source } $xCert = [PemCertImporter]::GetCertFromPem($Certificate) } else { $bytes = [Convert]::FromBase64String($Certificate) # Load the certificate to compare thumbprints $xCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection $xCert.Import($bytes, $PfxPassword, "DefaultKeySet") } # Since .NET components are being used, change it so things like WriteAllBytes works correctly [Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath $updateCert = $True if (Test-Path $CertFile) { Write-Host "Comparing to existing certificate" # Compare thumbprint if ($isPem) { $currentPemContents = Get-Content $CertFile $currentCert = [PemCertImporter]::GetCertFromPem($currentPemContents) } else { $currentCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection $currentCert.Import($CertFile, $PfxPassword, "DefaultKeySet") } $updateCert = @(Compare-Object $currentCert.Thumbprint $xCert.Thumbprint).length -ne 0 } if ($updateCert) { if ($isPem) { [IO.File]::WriteAllText($CertFile, $Certificate) } else { $bytes = [Convert]::FromBase64String($Certificate) [IO.File]::WriteAllBytes($CertFile, $bytes) } Write-Host "Certificate updated" } else { Write-Host "Cert not changed" } return $updateCert } |