Skip to content
This repository was archived by the owner on Jul 6, 2022. It is now read-only.

Commit d92d963

Browse files
authored
Publish preview version (#42)
* adds certificate store location * add additional certificate store tests * add cert store tests for New-CredentialStoreItem * fix test * add error handling for credential store path * add Import-CSCertificate helper function * Import new certificate if param is given * fix extension filter * add linux error message * fix pester test for linux * update cert helper functions * export helper functions * fix cs cert import * simplify cs cret lookup * remove obsolete functions * fix pester test for linux * fix error type for linux * fix var name * fix pester test * disable travis artifact upload * update cert lookup for item functions * debug build error * use cert instance constructor for linux * disable debug output * remove obsolete exports
1 parent 5a68527 commit d92d963

12 files changed

Lines changed: 422 additions & 166 deletions

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ matrix:
2020
fast_finish: true
2121

2222

23-
addons:
24-
artifacts:
25-
#paths: $(ls ./../dist/PowerShellGet.zip | tr "\n" ":")
26-
paths: ./dist/PowerShellGet.zip
23+
#addons:
24+
# artifacts:
25+
# paths: ./dist/PowerShellGet.zip
2726

2827

2928
install:
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
function Get-CSCertificate {
2+
<#
3+
.SYNOPSIS
4+
Returns the certificate object given by thumbprint.
5+
6+
.DESCRIPTION
7+
You can use this function to get a stored certificate. Search for the object by its unique thumbprint.
8+
9+
.PARAMETER Thumbprint
10+
Provide one or more thumprints.
11+
12+
.PARAMETER StoreName
13+
Select the store name in which you want to search the certificates.
14+
15+
.PARAMETER StoreLocation
16+
Select between the both available locations CurrentUser odr LocalMachine.
17+
18+
.INPUTS
19+
[string]
20+
21+
.OUTPUTS
22+
[System.Security.Cryptography.X509Certificates.X509Certificate2[]]
23+
24+
.EXAMPLE
25+
Get-CSCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser'
26+
27+
.NOTES
28+
File Name : Get-CSCertificate.ps1
29+
Author : Marco Blessing - marco.blessing@googlemail.com
30+
Requires :
31+
32+
.LINK
33+
https://github.com/OCram85/PSCredentialStore
34+
#>
35+
[CmdletBinding()]
36+
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])]
37+
param(
38+
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
39+
[ValidateNotNullOrEmpty()]
40+
[string[]]$Thumbprint,
41+
42+
[Parameter(Mandatory = $false)]
43+
[ValidateSet(
44+
'AddressBook',
45+
'AuthRoot',
46+
'CertificateAuthority',
47+
'Disallowed',
48+
'My',
49+
'Root',
50+
'TrustedPeople',
51+
'TrustedPublisher'
52+
)]
53+
[string]$StoreName = 'My',
54+
55+
[Parameter(Mandatory = $false)]
56+
[ValidateSet(
57+
'CurrentUser',
58+
'LocalMachine'
59+
)]
60+
[string]$StoreLocation = 'CurrentUser'
61+
)
62+
63+
begin {
64+
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::New($StoreName, $StoreLocation)
65+
try {
66+
$Store.Open('ReadOnly')
67+
}
68+
catch {
69+
$_.Exception.Message | Write-Error -ErrorAction Stop
70+
}
71+
}
72+
73+
process {
74+
foreach ($Thumb in $Thumbprint) {
75+
Write-Output $Store.Certificates | Where-Object { $_.Thumbprint -eq $Thumb }
76+
}
77+
}
78+
end {
79+
$Store.Close()
80+
}
81+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
function Import-CSCertificate {
2+
<#
3+
.SYNOPSIS
4+
adds a given pfx certificate file to current uerers personal certificate store.
5+
6+
.DESCRIPTION
7+
This function is used to import existing pfx certificate files. The Import-PFXCertificate cmdle from the
8+
PKI module imports the certficate into a deprecated store. Thus you can't read the private key afterwards or
9+
using it for decrypting data.
10+
11+
.PARAMETER Path
12+
Path to an existing *.pfx certificate file.
13+
14+
.PARAMETER StoreName
15+
Additionally you change change the store where you want the certificate into.
16+
17+
.INPUTS
18+
[None]
19+
20+
.OUTPUTS
21+
[None]
22+
23+
.EXAMPLE
24+
Import-CSCertificate -Path (Join-Path -Path $Env:APPDATA -ChildPath '/PSCredentialStore.pfx')
25+
26+
.NOTES
27+
File Name : Import-CSCertificate.ps1
28+
Author : Marco Blessing - marco.blessing@googlemail.com
29+
Requires :
30+
31+
.LINK
32+
https://github.com/OCram85/PSCredentialStore
33+
#>
34+
[CmdletBinding()]
35+
[OutputType()]
36+
param(
37+
[Parameter(Mandatory = $true)]
38+
[ValidateNotNullOrEmpty()]
39+
[string]$Path,
40+
41+
[Parameter(Mandatory = $false)]
42+
[ValidateSet(
43+
'AddressBook',
44+
'AuthRoot',
45+
'CertificateAuthority',
46+
'Disallowed',
47+
'My',
48+
'Root',
49+
'TrustedPeople',
50+
'TrustedPublisher'
51+
)]
52+
[string]$StoreName = 'My',
53+
54+
[Parameter(Mandatory = $false)]
55+
[ValidateSet(
56+
'CurrentUser',
57+
'LocalMachine'
58+
)]
59+
[string]$StoreLocation = 'CurrentUser',
60+
61+
[Parameter(Mandatory = $false)]
62+
[ValidateSet(
63+
'ReadOnly',
64+
'ReadWrite',
65+
'MaxAllowed',
66+
'OpenExistingOnly',
67+
'InclueArchived'
68+
)]
69+
[string]$OpenFlags = 'ReadWrite'
70+
)
71+
begin {
72+
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation)
73+
try {
74+
$Store.Open($OpenFlags)
75+
}
76+
catch {
77+
$_.Exception.Message | Write-Error -ErrorAction Stop
78+
}
79+
}
80+
process {
81+
try {
82+
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new(
83+
$Path,
84+
$null,
85+
(
86+
[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable -bor
87+
[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
88+
)
89+
)
90+
91+
if (Test-CSCertificate -Thumbprint $cert.Thumbprint) {
92+
Write-Warning -Message ('The certificate with thumbprint {0} is already present!' -f $cert.Thumbprint)
93+
}
94+
else {
95+
$Store.Add($cert)
96+
}
97+
}
98+
catch {
99+
$_.Exception.Message | Write-Error -ErrorAction Stop
100+
$ErrorParams = @{
101+
ErrorAction = 'Stop'
102+
Exception = [System.Exception]::new(
103+
'Could not read or add the pfx certificate!'
104+
)
105+
}
106+
Write-Error @ErrorParams
107+
}
108+
}
109+
end {
110+
$Store.Close()
111+
}
112+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
function Test-CSCertificate {
2+
<#
3+
.SYNOPSIS
4+
Tests if the given certificate exists in a store.
5+
6+
.DESCRIPTION
7+
Use this function to ensure if a certificate is already imported into a given store.
8+
9+
.PARAMETER Thumbprint
10+
Provide one or more thumprints.
11+
12+
.PARAMETER StoreName
13+
Select the store name in which you want to search the certificates.
14+
15+
.PARAMETER StoreLocation
16+
Select between the both available locations CurrentUser odr LocalMachine.
17+
18+
.INPUTS
19+
[None]
20+
21+
.OUTPUTS
22+
[bool]
23+
24+
.EXAMPLE
25+
Test-CSCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser'
26+
27+
.NOTES
28+
File Name : Test-CSCertificate.ps1
29+
Author : Marco Blessing - marco.blessing@googlemail.com
30+
Requires :
31+
32+
.LINK
33+
https://github.com/OCram85/PSCredentialStore
34+
#>
35+
[CmdletBinding()]
36+
[OutputType([bool])]
37+
param(
38+
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
39+
[ValidateNotNullOrEmpty()]
40+
[string]$Thumbprint,
41+
42+
[Parameter(Mandatory = $false)]
43+
[ValidateSet(
44+
'AddressBook',
45+
'AuthRoot',
46+
'CertificateAuthority',
47+
'Disallowed',
48+
'My',
49+
'Root',
50+
'TrustedPeople',
51+
'TrustedPublisher'
52+
)]
53+
[string]$StoreName = 'My',
54+
55+
[Parameter(Mandatory = $false)]
56+
[ValidateSet(
57+
'CurrentUser',
58+
'LocalMachine'
59+
)]
60+
[string]$StoreLocation = 'CurrentUser'
61+
)
62+
63+
begin {
64+
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::New($StoreName, $StoreLocation)
65+
try {
66+
$Store.Open('ReadOnly')
67+
}
68+
catch {
69+
$_.Exception.Message | Write-Error -ErrorAction Stop
70+
}
71+
}
72+
73+
process {
74+
$Cert = $Store.Certificates | Where-Object { $_.Thumbprint -eq $Thumbprint }
75+
76+
if ($null -eq $Cert) {
77+
return $false
78+
}
79+
else {
80+
return $true
81+
}
82+
}
83+
end {
84+
$Store.Close()
85+
}
86+
}

src/Item/Get-CredentialStoreItem.ps1

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,24 @@ function Get-CredentialStoreItem {
8787
$CSMembers = Get-Member -InputObject $CS
8888
# Let's first check if the given remote host exists as object property
8989
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) {
90-
$Cert = Get-PfxCertificate -FilePath $CS.PfXCertificate -ErrorAction Stop
90+
try {
91+
if ($null -eq $CS.PfxCertificate) {
92+
$Cert = Get-CSCertificate -Thumbprint $CS.Thumbprint
93+
}
94+
else {
95+
$Cert = Get-PfxCertificate -FilePath $CS.PfxCertificate -ErrorAction Stop
96+
}
97+
}
98+
catch {
99+
$_.Exception.Message | Write-Error
100+
$ErrorParams = @{
101+
ErrorAction = 'Stop'
102+
Exception = [System.Security.Cryptography.CryptographicException]::new(
103+
'Could not read the given PFX certificate.'
104+
)
105+
}
106+
Write-Error @ErrorParams
107+
}
91108
$DecryptedKey = $Cert.PrivateKey.Decrypt(
92109
[Convert]::FromBase64String($CS.$CredentialName.EncryptedKey),
93110
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1

src/Item/New-CredentialStoreItem.ps1

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,21 @@ function New-CredentialStoreItem {
117117

118118
if ($Credential.UserName) {
119119
try {
120-
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
120+
if ($null -eq $CSContent.PfxCertificate) {
121+
$Cert = Get-CSCertificate -Thumbprint $CSContent.Thumbprint
122+
if ($null -eq $Cert) {
123+
$ErrorParams = @{
124+
ErrorAction = 'Stop'
125+
Exception = [System.Security.Cryptography.X509Certificates.FileNotFoundException]::new(
126+
('Could not find the linked certificate with thumbprint {0}' -f $CSContent.Thumbprint)
127+
)
128+
}
129+
Write-Error @ErrorParams
130+
}
131+
}
132+
else {
133+
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
134+
}
121135
}
122136
catch {
123137
$_.Exception.Message | Write-Error

src/Item/Set-CredentialStoreItem.ps1

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,20 @@ function Set-CredentialStoreItem {
103103

104104
if ($Credential.UserName) {
105105
try {
106-
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
106+
if ($null -eq $CSContent.PfxCertificate) {
107+
$Cert = Get-CSCertificate -Thumbprint $CSContent.Thumbprint
108+
}
109+
else {
110+
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
111+
}
107112
}
108113
catch {
109114
$_.Exception.Message | Write-Error
110115
$ErrorParams = @{
111-
Message = 'Could not read the given PFX certificate.'
112116
ErrorAction = 'Stop'
113-
Exception = [System.Security.Cryptography.CryptographicException]::new()
117+
Exception = [System.Security.Cryptography.CryptographicException]::new(
118+
'Could not read the given PFX certificate.'
119+
)
114120
}
115121
Write-Error @ErrorParams
116122
}

src/PSCredentialStore.psd1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@
6363
# 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.
6464
FunctionsToExport = @(
6565
# Certificate
66+
'Get-CSCertificate',
67+
'Import-CSCertificate',
6668
'New-CRTAttribute',
6769
'New-PfxCertificate',
70+
'Test-CSCertificate',
6871
'Use-PfxCertificate',
6972
# Connection
7073
'Connect-To',
@@ -79,8 +82,7 @@
7982
# Store
8083
'Get-CredentialStore',
8184
'New-CredentialStore',
82-
'Test-CredentialStore',
83-
'Update-CredentialStore'
85+
'Test-CredentialStore'
8486
)
8587

8688
# Cmdlets 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 cmdlets to export.

0 commit comments

Comments
 (0)