forked from OCram85/PSCredentialStore
PowerShell 6 Core Support (#35)
## About This pull request reflects all changes done in the `linuxsupport` branch. ## Content - Enable PowerShell 6 Core support - Use PFX Certificate for encryption ( fixes #32 ) - Updates CI / CD pipeline ( fixes #31 ) - uses portable libressl ( fixes #34 ) - adds `-PassThru` switch for returning current `VIServer` session in `Connect-To` ( fixes #34 ) - adds git lfs for embedded libressl files - restructured internal functions into `Private` dir - added certificate related functions - adds travis build pipeline for tests
This commit is contained in:
100
src/Certificate/New-CRTAttribute.ps1
Normal file
100
src/Certificate/New-CRTAttribute.ps1
Normal file
@ -0,0 +1,100 @@
|
||||
function New-CRTAttribute {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create required data for a certificate signing request.
|
||||
|
||||
.DESCRIPTION
|
||||
Defines the certificate related properties for an upcoming New-PfxCertificate execution.
|
||||
|
||||
.PARAMETER Country
|
||||
Provide a two letter country code.
|
||||
|
||||
.PARAMETER State
|
||||
Certificate state value.
|
||||
|
||||
.PARAMETER City
|
||||
Certificate city value.
|
||||
|
||||
.PARAMETER Organization
|
||||
Certificate organization value.
|
||||
|
||||
.PARAMETER OrganizationalUnitName
|
||||
Certificate OrganizationalUnitName value.
|
||||
|
||||
.PARAMETER CommonName
|
||||
The certificate common name.
|
||||
|
||||
.PARAMETER CSRSubject
|
||||
you can provide the needed certificate properties with in one hashtable. This hashtable has to contain the
|
||||
following keys: 'Country', 'State', 'City', 'Organization', 'OrganizationalUnitName', 'CommonName'.
|
||||
|
||||
.INPUTS
|
||||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
['PSCredentialStore.Certificate.CSRDetails']
|
||||
|
||||
.EXAMPLE
|
||||
New-CRTAttribute -CSRSubject @{Country = 'DE'; State = 'BW'; City = 'Karlsruhe'; Organization = 'AwesomeIT'; OrganizationalUnitName = '';CommonName = 'MyPrivateCert'}
|
||||
|
||||
.NOTES
|
||||
File Name : New-CSRDetails.ps1
|
||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||
Requires :
|
||||
|
||||
.LINK
|
||||
https://github.com/OCram85/PSCredentialStore
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[OutputType('PSCredentialStore.Certificate.Attribute')]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateLength(2, 2)]
|
||||
[ValidateNotNull()]
|
||||
[string]$Country,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNull()]
|
||||
[string]$State,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNull()]
|
||||
[string]$City,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNull()]
|
||||
[string]$Organization,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNull()]
|
||||
[string]$OrganizationalUnitName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNull()]
|
||||
[string]$CommonName,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNull()]
|
||||
[int]$Days = 365
|
||||
)
|
||||
begin {
|
||||
|
||||
}
|
||||
process {
|
||||
return [PSCustomObject]@{
|
||||
PSTypeName = 'PSCredentialStore.Certificate.Attribute'
|
||||
Subject = [PSCustomObject]@{
|
||||
PSTypeName = 'PSCredentialStore.Certificate.Attribute.Subject'
|
||||
Country = $Country
|
||||
State = $State
|
||||
City = $City
|
||||
Organization = $Organization
|
||||
OrganizationalUnitName = $OrganizationalUnitName
|
||||
CommonName = $CommonName
|
||||
}
|
||||
Days = $Days
|
||||
}
|
||||
}
|
||||
end {
|
||||
}
|
||||
}
|
142
src/Certificate/New-PfxCertificate.ps1
Normal file
142
src/Certificate/New-PfxCertificate.ps1
Normal file
@ -0,0 +1,142 @@
|
||||
function New-PfxCertificate {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates new PFX certificate for the CredentialStore encryption.
|
||||
|
||||
.DESCRIPTION
|
||||
Use this function to create a custom self signed certificate used by the PSCredentialStore module.
|
||||
|
||||
.PARAMETER CRTAttribute
|
||||
Provide certificate related attributes provided by function New-CRTAttribute.
|
||||
|
||||
.PARAMETER KeyName
|
||||
Provide a custom full path and name for the private key. The file extension has to be `*.key`.
|
||||
|
||||
.PARAMETER CertName
|
||||
Provide a custom full path and name for the PFX certificate file. The file extension has to be `*.pfx`
|
||||
|
||||
.INPUTS
|
||||
[PSCredentialStore.Certificate.Attribute]
|
||||
|
||||
.OUTPUTS
|
||||
[None]
|
||||
|
||||
.EXAMPLE
|
||||
New-PfxCertificate -CRTAttribute $CRTAttribute -KeyName './myprivate.key' -CertName './mycert.pfx'
|
||||
|
||||
.NOTES
|
||||
File Name : New-PfxCertificate.ps1
|
||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||
Requires :
|
||||
|
||||
.LINK
|
||||
https://github.com/OCram85/PSCredentialStore
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess = $true)]
|
||||
[OutputType()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[PSTypeName('PSCredentialStore.Certificate.Attribute')]$CRTAttribute,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$KeyName = './private.key',
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$CertName = './certificate.pfx'
|
||||
)
|
||||
|
||||
begin {
|
||||
$ModuleBase = Get-ModuleBase
|
||||
if ($isLinux -or $isMacOS) {
|
||||
try {
|
||||
$openssl = Get-Command -Name 'openssl' -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
$_.Exception.Message | Write-Error
|
||||
$ErrorParams = @{
|
||||
Message = 'Can not find the openssl binary!'
|
||||
ErrorAction = 'Stop'
|
||||
Exception = [System.IO.FileNotFoundException]::new()
|
||||
}
|
||||
Write-Error @ErrorParams
|
||||
}
|
||||
}
|
||||
elseif (($PSVersionTable.PSEdition -eq 'Desktop' -and $PSVersionTable.PSVersion.Major -lt 6) -or ($IsWindows -eq $true)) {
|
||||
$openssl = Join-Path -Path $ModuleBase -ChildPath '/Vendor/libressl255/openssl.exe'
|
||||
}
|
||||
|
||||
$Env:OPENSSL_CONF = Join-Path $ModuleBase -ChildPath '/openssl.conf'
|
||||
}
|
||||
process {
|
||||
$SubjPattern = "/C={0}/ST={1}/L={2}/O={3}/OU={4}/CN={5}"
|
||||
$SubjValues = @(
|
||||
$CRTAttribute.Subject.Country,
|
||||
$CRTAttribute.Subject.State,
|
||||
$CRTAttribute.Subject.City,
|
||||
$CRTAttribute.Subject.Organization,
|
||||
$CRTAttribute.Subject.OrganizationalUnitName,
|
||||
$CRTAttribute.Subject.CommonName
|
||||
)
|
||||
$Subj = $SubjPattern -f $SubjValues
|
||||
|
||||
$PEMCertName = $CertName -replace '.pfx', '.crt'
|
||||
$ExpPattern = '& ''{0}'' req -x509 -sha256 -nodes -days {1} -newkey rsa:2048 -keyout {2} -out {3} -subj "{4}" *>$null'
|
||||
$ExpValues = @(
|
||||
$openssl,
|
||||
$CRTAttribute.Days
|
||||
$KeyName,
|
||||
$PEMCertName,
|
||||
$Subj
|
||||
)
|
||||
$PEMExp = $ExpPattern -f $ExpValues
|
||||
|
||||
Write-Verbose -Message ( 'Expr string is: {0}' -f $PEMExp)
|
||||
|
||||
# Edit the Error action for the openSLL command to make the redirect *>$null work.
|
||||
# There is always a stderr and stdout stream!
|
||||
$EAP = $ErrorActionPreference
|
||||
$ErrorActionPreference = 'Continue'
|
||||
Invoke-Expression -Command $PEMExp
|
||||
$ErrorActionPreference = $EAP
|
||||
|
||||
# manually testing the openssl command results
|
||||
|
||||
if (! (Test-Path -Path $KeyName)) {
|
||||
$ErrorParams = @{
|
||||
Message = 'Could not create the private key ${0}' -f $KeyName
|
||||
ErrorAction = 'Stop'
|
||||
Exception = [System.UnauthorizedAccessException]::new()
|
||||
}
|
||||
Write-Error @ErrorParams
|
||||
}
|
||||
if (! (Test-Path -Path $PEMCertName)) {
|
||||
$ErrorParams = @{
|
||||
Message = 'Could not create the PEM certificate ${0}' -f $PEMCertName
|
||||
ErrorAction = 'Stop'
|
||||
Exception = [System.Exception]::new()
|
||||
}
|
||||
Write-Error @ErrorParams
|
||||
}
|
||||
|
||||
$PfxPattern = '& ''{0}'' pkcs12 -export -out {1} -inkey {2} -in {3} -passout pass:'
|
||||
$PfxValues = @(
|
||||
$openssl,
|
||||
$CertName,
|
||||
$KeyName,
|
||||
($CertName -replace '.pfx', '.crt')
|
||||
)
|
||||
$PfxExp = $PfxPattern -f $PfxValues
|
||||
Write-Verbose -Message ( 'PfxExp string is: {0}' -f $PfxExp)
|
||||
Invoke-Expression -Command $PfxExp
|
||||
|
||||
# Remove private key and crt file. Always ask user
|
||||
Remove-Item -Path $KeyName
|
||||
Remove-Item -Path ($CertName -replace '.pfx', '.crt')
|
||||
}
|
||||
end {
|
||||
Remove-Item Env:\OPENSSL_CONF -Confirm:$False -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
102
src/Certificate/Use-PfxCertificate.ps1
Normal file
102
src/Certificate/Use-PfxCertificate.ps1
Normal file
@ -0,0 +1,102 @@
|
||||
function Use-PfxCertificate {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Links an existing PFX Certifiacte to a CredentialStore.
|
||||
|
||||
.DESCRIPTION
|
||||
Linking a certificate is needed if you plan to use the same CredentialStore in cross platform scenarios.
|
||||
|
||||
.PARAMETER Path
|
||||
Specify the path to the PFX Certificate you want to link for usage.
|
||||
|
||||
.INPUTS
|
||||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
[None]
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
|
||||
.NOTES
|
||||
File Name : Use-PfxCertificate.ps1
|
||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||
Requires :
|
||||
|
||||
.LINK
|
||||
https://github.com/OCram85/PSCredentialStore
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||
[OutputType()]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Path,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$CredentialStore,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[switch]$Shared
|
||||
)
|
||||
begin {}
|
||||
|
||||
process {
|
||||
try {
|
||||
# We need to resolve the path to make sure it has the correct platform specific syntax.
|
||||
# And it should also exist.
|
||||
$validPath = Resolve-Path -Path $Path -ErrorAction Stop
|
||||
$PfxCertificate = Get-PfxCertificate -FilePath $validPath -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
$_.Exception.Error | Write-Error
|
||||
$ErrorParams = @{
|
||||
Message = 'The given PFX certificate does not exist!'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @ErrorParams
|
||||
}
|
||||
|
||||
try {
|
||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||
$StorePath = Get-DefaultCredentialStorePath
|
||||
$CS = Get-CredentialStore
|
||||
}
|
||||
elseif ($PSCmdlet.ParameterSetName -eq "Shared" ) {
|
||||
if (!($PSBoundParameters.ContainsKey('CredentialStore'))) {
|
||||
$StorePath = Get-DefaultCredentialStorePath -Shared
|
||||
$CS = Get-CredentialStore -Shared
|
||||
}
|
||||
else {
|
||||
$StorePath = $CredentialStore
|
||||
$CS = Get-CredentialStore -Shared -Path $CredentialStore
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$_.Exception.Error | Write-Error
|
||||
$ErrorParams = @{
|
||||
Message = 'The given CredentialStore does not exist!'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @ErrorParams
|
||||
}
|
||||
|
||||
# Lets first check if the thumbprint matches
|
||||
if (($CS.Thumbprint -notmatch $PfxCertificate.Thumbprint) -and ($CS.Thumbprint.Length -ne 0)) {
|
||||
Write-Warning @"
|
||||
You are trying to map an unknown certificate.
|
||||
Make sure you used the same AES keys for encrypting!
|
||||
"@
|
||||
}
|
||||
|
||||
$CS.PfxCertificate = $validPath.Path
|
||||
$CS.Thumbprint = $PfxCertificate.Thumbprint
|
||||
$CS | ConvertTo-Json -Depth 5 | Out-File -FilePath $StorePath -Force -Encoding utf8
|
||||
}
|
||||
|
||||
end {}
|
||||
}
|
Reference in New Issue
Block a user