diff --git a/.assets/scripts/modules_update.ps1 b/.assets/scripts/modules_update.ps1 index b04c87df..d02df262 100644 --- a/.assets/scripts/modules_update.ps1 +++ b/.assets/scripts/modules_update.ps1 @@ -40,6 +40,7 @@ begin { 'do-common' = @{ SetupUtils = @{ certs = @( + 'ConvertFrom-PEM' 'ConvertTo-PEM' 'Get-Certificate' ) diff --git a/modules/SetupUtils/Functions/certs.ps1 b/modules/SetupUtils/Functions/certs.ps1 index 905be7e4..c8fbbc66 100644 --- a/modules/SetupUtils/Functions/certs.ps1 +++ b/modules/SetupUtils/Functions/certs.ps1 @@ -1,3 +1,56 @@ +function ConvertFrom-PEM { + [CmdletBinding()] + [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2[]])] + param ( + [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FromString')] + [string]$InputObject, + + [Parameter(Mandatory, Position = 0, ParameterSetName = 'FromPath')] + [ValidateScript({ Test-Path $_ -PathType 'Leaf' }, ErrorMessage = "'{0}' is not a valid file path.")] + [string]$Path + ) + + begin { + # list to store input certificate strings + $pemTxt = [System.Collections.Generic.List[string]]::new() + # hashset for storing parsed pem certificates + $pemSplit = [System.Collections.Generic.HashSet[string]]::new() + # list to store decoded certificates + $x509Certs = [System.Collections.Generic.List[Security.Cryptography.X509Certificates.X509Certificate2]]::new() + } + + process { + switch ($PsCmdlet.ParameterSetName) { + FromPath { + # read certificate file + Resolve-Path $Path | ForEach-Object { + $pemTxt.Add([IO.File]::ReadAllText($_)) + } + continue + } + FromString { + $InputObject.ForEach({ $pemTxt.Add($_) }) + continue + } + } + } + + end { + # parse certificate string + [regex]::Matches( + [string]::Join("`n", $pemTxt).Replace("`r`n", "`n"), + '(?<=-{5}BEGIN[\w ]+CERTIFICATE-{5}\n)[\S\n]+(?=\n-{5}END[\w ]+CERTIFICATE-{5})' + ).Value.ForEach({ $pemSplit.Add($_) | Out-Null }) + # convert PEM encoded certificates to X509 certificate objects + foreach ($pem in $pemSplit) { + $decCrt = [Security.Cryptography.X509Certificates.X509Certificate2]::new([Convert]::FromBase64String($pem)) + $x509Certs.Add($decCrt) + } + + return $x509Certs + } +} + function ConvertTo-PEM { [CmdletBinding()] [OutputType([System.Collections.Generic.List[string]])] diff --git a/modules/SetupUtils/SetupUtils.psd1 b/modules/SetupUtils/SetupUtils.psd1 index b8ce486b..9a2258a2 100644 --- a/modules/SetupUtils/SetupUtils.psd1 +++ b/modules/SetupUtils/SetupUtils.psd1 @@ -12,7 +12,7 @@ RootModule = 'SetupUtils.psm1' # Version number of this module. - ModuleVersion = '0.3.1' + ModuleVersion = '0.4.0' # Supported PSEditions CompatiblePSEditions = @('Core') @@ -71,6 +71,7 @@ # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @( # certs + 'ConvertFrom-PEM' 'ConvertTo-PEM' 'Get-Certificate' # common diff --git a/modules/SetupUtils/SetupUtils.psm1 b/modules/SetupUtils/SetupUtils.psm1 index bece98b6..3da63c1c 100644 --- a/modules/SetupUtils/SetupUtils.psm1 +++ b/modules/SetupUtils/SetupUtils.psm1 @@ -7,6 +7,7 @@ $ErrorActionPreference = 'Stop' $exportModuleMemberParams = @{ Function = @( # certs + 'ConvertFrom-PEM' 'ConvertTo-PEM' 'Get-Certificate' # common