From 934dd8e1ee1252739921c491113cf16b2259b42c Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Tue, 22 Oct 2024 13:55:27 +0200 Subject: [PATCH] fix(ps): add ConvertFrom-PEM to SetupUtils --- .assets/scripts/modules_update.ps1 | 1 + modules/SetupUtils/Functions/certs.ps1 | 53 ++++++++++++++++++++++++++ modules/SetupUtils/SetupUtils.psd1 | 3 +- modules/SetupUtils/SetupUtils.psm1 | 1 + 4 files changed, 57 insertions(+), 1 deletion(-) 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