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:
parent
ab13962f6e
commit
afab3c870c
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
src/Vendor/libressl255/* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pfx filter=lfs diff=lfs merge=lfs -text
|
43
.travis.yml
Normal file
43
.travis.yml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
language: csharp
|
||||||
|
dotnet: 2.2.101
|
||||||
|
mono: none
|
||||||
|
|
||||||
|
git:
|
||||||
|
depth: 1000
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
# Disable OSX bulds for now
|
||||||
|
# - osx
|
||||||
|
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
dist: xenial
|
||||||
|
osx_image: xcode8.1
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
|
||||||
|
addons:
|
||||||
|
artifacts:
|
||||||
|
#paths: $(ls ./../dist/PowerShellGet.zip | tr "\n" ":")
|
||||||
|
paths: ./dist/PowerShellGet.zip
|
||||||
|
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Default 2.0.0 Ruby is buggy
|
||||||
|
# Default bundler version is buggy
|
||||||
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
|
rvm install ruby-2.3.3;
|
||||||
|
rvm --default use 2.3.3;
|
||||||
|
fi
|
||||||
|
- bash <(wget -O - https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.sh)
|
||||||
|
- pushd tools
|
||||||
|
- chmod +x travis.sh
|
||||||
|
- popd
|
||||||
|
|
||||||
|
script:
|
||||||
|
- echo "TRAVIS_EVENT_TYPE value $TRAVIS_EVENT_TYPE"
|
||||||
|
- ./tools/travis.sh
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -42,7 +42,7 @@
|
|||||||
"type": "PowerShell",
|
"type": "PowerShell",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "PowerShell Interactive Session",
|
"name": "PowerShell Interactive Session",
|
||||||
"cwd": "${workspaceRoot}"
|
"cwd": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -26,7 +26,8 @@
|
|||||||
"powershell.codeFormatting.whitespaceAroundOperator": true,
|
"powershell.codeFormatting.whitespaceAroundOperator": true,
|
||||||
"powershell.codeFormatting.whitespaceAfterSeparator": true,
|
"powershell.codeFormatting.whitespaceAfterSeparator": true,
|
||||||
"powershell.codeFormatting.ignoreOneLineBlock": true,
|
"powershell.codeFormatting.ignoreOneLineBlock": true,
|
||||||
"powershell.codeFormatting.alignPropertyValuePairs": false,
|
"powershell.codeFormatting.alignPropertyValuePairs": true,
|
||||||
|
"powershell.codeFormatting.preset": "Custom",
|
||||||
// cspell spellchecker options
|
// cspell spellchecker options
|
||||||
"cSpell.enabledLanguageIds": [
|
"cSpell.enabledLanguageIds": [
|
||||||
"c",
|
"c",
|
||||||
|
28
README.md
28
README.md
@ -23,14 +23,28 @@ need to store credentials for non interactive usage like in scheduled tasks.
|
|||||||
For more details read the [about_PSCredentialStore](/docs/about_PSCredentialStore.md) page on github or via CLI with
|
For more details read the [about_PSCredentialStore](/docs/about_PSCredentialStore.md) page on github or via CLI with
|
||||||
`Get-Help about_PSCredentialStore`.
|
`Get-Help about_PSCredentialStore`.
|
||||||
|
|
||||||
|
:exclamation: Upcoming Changes :exclamation:
|
||||||
|
================
|
||||||
|
|
||||||
|
The will be some breaking changes starting with the `0.5.0.xxx`:
|
||||||
|
|
||||||
|
- **PSCredentialStore will use PFX certificates to encrypt your credentials.**
|
||||||
|
- This replaces the the current encryption methods and you need to recreate or upgrade your pre existing stores.
|
||||||
|
- The changes allows the PSCredentialStore module to support the PowerShell `Core` editions.
|
||||||
|
- Yes this means, you can use the module on any PowerShell 6 supported linux distribution.
|
||||||
|
- It's also possible to create a shared credential store and transfer it onto a another platform like:
|
||||||
|
`Windows -- to --> Linux` and vice versa.
|
||||||
|
- Automatically creates self signed certificate with 2048 bits RSA keys for encryption.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
PowerShellGallery.com (Recommended Way)
|
PowerShellGallery.com (Recommended Way)
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
* Make sure you use PowerShell 4.0 or higher with `$PSVersionTable`.
|
* Make sure you use PowerShell 5.1 or higher with `$PSVersionTable`.
|
||||||
* Use the builtin PackageManagement and install with: `Install-Module PSCredentialStore`
|
* Use the builtin PackageManagement and install with: `Import-Module PowerShellGet; Install-Module 'PSCredentialStore' -Repository 'PSGallery'`
|
||||||
|
* Additionally use the `-AllowPrerelease` switch until we publish the final release!
|
||||||
* Done. Start exploring the Module with `Import-Module PSCredentialStore ; Get-Command -Module PSCredentialStore`
|
* Done. Start exploring the Module with `Import-Module PSCredentialStore ; Get-Command -Module PSCredentialStore`
|
||||||
|
|
||||||
Manual Way
|
Manual Way
|
||||||
@ -97,3 +111,13 @@ Connect-To -RemoteHost "fas.myside.local" -Type NetAppFAS
|
|||||||
Connect-To -RemoteHost "esx01.myside.local" -Type VMware
|
Connect-To -RemoteHost "esx01.myside.local" -Type VMware
|
||||||
Connect-To -RemoteHost "vcr.myside.local" -Type CisServer
|
Connect-To -RemoteHost "vcr.myside.local" -Type CisServer
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
A huge thanks to all the people who helped with their projects and indirect contributions which made this possible!
|
||||||
|
|
||||||
|
- This module is inspired by the awesome work of @dlwyatt with articles like these:
|
||||||
|
- https://powershell.org/2013/11/24/saving-passwords-and-preventing-other-processes-from-decrypting-them/
|
||||||
|
- https://powershell.org/2014/02/01/revisited-powershell-and-encryption/
|
||||||
|
- The awesome people from [LibreSSL](http://www.libressl.org/) which publishes the [portable openssl/libressl binaries](https://github.com/libressl-portable/portable)!
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: 0.2.3.{build}
|
version: 0.5.0.{build}
|
||||||
|
|
||||||
#branches:
|
#branches:
|
||||||
# only:
|
# only:
|
||||||
@ -20,6 +20,7 @@ image: Visual Studio 2017
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: Import-Module .\tools\AppVeyor.psm1
|
- ps: Import-Module .\tools\AppVeyor.psm1
|
||||||
|
- ps: Import-Module .\tools\CoverallsIO.psm1
|
||||||
- ps: Invoke-InstallDependencies
|
- ps: Invoke-InstallDependencies
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
@ -37,10 +38,10 @@ build_script:
|
|||||||
- ps: Invoke-AppVeyorBuild
|
- ps: Invoke-AppVeyorBuild
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- ps: Invoke-AppVeyorTests
|
|
||||||
- ps: |
|
- ps: |
|
||||||
|
$CodeCoverage = Invoke-AppVeyorTests
|
||||||
if ($null -ne $Env:CoverallsToken) {
|
if ($null -ne $Env:CoverallsToken) {
|
||||||
Invoke-CoverageReport
|
Invoke-CoverageReport -PesterCoverageReport $CodeCoverage
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Warning "No CoverallsToken found. This build seems to be triggered by a PR. Skipping this step..."
|
Write-Warning "No CoverallsToken found. This build seems to be triggered by a PR. Skipping this step..."
|
||||||
@ -60,7 +61,7 @@ deploy:
|
|||||||
secure: M+bBX5/nKdJB0eViP7xtrLVTwf3vGDUA9N2MMprZp2i+9ZR3CBVcJnSzJWUmalhB
|
secure: M+bBX5/nKdJB0eViP7xtrLVTwf3vGDUA9N2MMprZp2i+9ZR3CBVcJnSzJWUmalhB
|
||||||
artifact: PSCredentialStore.zip # upload all NuGet packages to release assets
|
artifact: PSCredentialStore.zip # upload all NuGet packages to release assets
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: true
|
||||||
on:
|
on:
|
||||||
branch: master # build release on master branch changes
|
branch: master # build release on master branch changes
|
||||||
|
|
||||||
|
BIN
assets/logo256.png
Normal file
BIN
assets/logo256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
@ -63,7 +63,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -19,7 +19,7 @@ Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonPara
|
|||||||
|
|
||||||
### Shared
|
### Shared
|
||||||
```
|
```
|
||||||
Get-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Shared] [-Path <String>]
|
||||||
[<CommonParameters>]
|
[<CommonParameters>]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -19,7 +19,7 @@ Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonPara
|
|||||||
|
|
||||||
### Shared
|
### Shared
|
||||||
```
|
```
|
||||||
Get-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Shared] [-Path <String>]
|
||||||
[<CommonParameters>]
|
[<CommonParameters>]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -20,8 +20,8 @@ New-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential
|
|||||||
|
|
||||||
### Shared
|
### Shared
|
||||||
```
|
```
|
||||||
New-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>]
|
New-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential <PSCredential>] [-Shared]
|
||||||
[-Credential <PSCredential>] [-Shared] [<CommonParameters>]
|
[-Path <String>] [<CommonParameters>]
|
||||||
```
|
```
|
||||||
|
|
||||||
## DESCRIPTION
|
## DESCRIPTION
|
||||||
@ -51,7 +51,7 @@ Aliases:
|
|||||||
Required: False
|
Required: False
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: None
|
Default value: None
|
||||||
Accept pipeline input: False
|
Accept pipeline input: True (ByValue)
|
||||||
Accept wildcard characters: False
|
Accept wildcard characters: False
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -19,7 +19,7 @@ Remove-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonP
|
|||||||
|
|
||||||
### Shared
|
### Shared
|
||||||
```
|
```
|
||||||
Remove-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
Remove-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Shared] [-Path <String>]
|
||||||
[<CommonParameters>]
|
[<CommonParameters>]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -14,13 +14,14 @@ Changes the credentials for the given remote host in the store.
|
|||||||
|
|
||||||
### Private (Default)
|
### Private (Default)
|
||||||
```
|
```
|
||||||
Set-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonParameters>]
|
Set-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential <PSCredential>]
|
||||||
|
[<CommonParameters>]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Shared
|
### Shared
|
||||||
```
|
```
|
||||||
Set-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
Set-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential <PSCredential>] [-Shared]
|
||||||
[<CommonParameters>]
|
[-Path <String>] [<CommonParameters>]
|
||||||
```
|
```
|
||||||
|
|
||||||
## DESCRIPTION
|
## DESCRIPTION
|
||||||
@ -37,6 +38,21 @@ Set-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.lo
|
|||||||
|
|
||||||
## PARAMETERS
|
## PARAMETERS
|
||||||
|
|
||||||
|
### -Credential
|
||||||
|
{{Fill Credential Description}}
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: PSCredential
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: None
|
||||||
|
Accept pipeline input: True (ByValue)
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
### -Identifier
|
### -Identifier
|
||||||
Defaults to "".
|
Defaults to "".
|
||||||
Specify a string, which separates two CredentialStoreItems for the
|
Specify a string, which separates two CredentialStoreItems for the
|
||||||
@ -94,7 +110,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -63,7 +63,7 @@ Type: SwitchParameter
|
|||||||
Parameter Sets: Shared
|
Parameter Sets: Shared
|
||||||
Aliases:
|
Aliases:
|
||||||
|
|
||||||
Required: False
|
Required: True
|
||||||
Position: Named
|
Position: Named
|
||||||
Default value: False
|
Default value: False
|
||||||
Accept pipeline input: False
|
Accept pipeline input: False
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"Version": "1.2.0",
|
"Version": "2.0.0",
|
||||||
"Creation": "2016-06-14 08:41:10"
|
"Creation": "2016-06-14 08:41:10"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
!マ<><EFBE8F>゙澄H4サ<34><EFBDBB>"=w肛Sヨ2
|
|
Binary file not shown.
BIN
resources/cs/PSCredentialStore.pfx
(Stored with Git LFS)
Normal file
BIN
resources/cs/PSCredentialStore.pfx
(Stored with Git LFS)
Normal file
Binary file not shown.
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 {}
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
function Get-ChallengeFile {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Reads the challenge file as binary content.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
Use this function to tread a challenge file. Returns a [Byte[]] Array.
|
|
||||||
|
|
||||||
.PARAMETER Path
|
|
||||||
Specify a file to read.
|
|
||||||
|
|
||||||
.INPUTS
|
|
||||||
[None]
|
|
||||||
|
|
||||||
.OUTPUTS
|
|
||||||
[Byte[]]
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\Get-RandomKey -Path "C:\TMP\Challenge.bin"
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
```
|
|
||||||
File Name : Get-ChallengeFile.ps1
|
|
||||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
|
||||||
Requires :
|
|
||||||
```
|
|
||||||
.LINK
|
|
||||||
https://github.com/OCram85/PSCredentialStore
|
|
||||||
#>
|
|
||||||
|
|
||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $false)]
|
|
||||||
[string]$Path = "{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData
|
|
||||||
)
|
|
||||||
|
|
||||||
if (Test-Path $Path) {
|
|
||||||
try {
|
|
||||||
[io.file]::ReadAllBytes($Path)
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error ("Could not read file {0}." -f $Path) -ErrorAction Stop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
Function Set-ChallengeFile() {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Writes the given key into the challenge file
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
You can use the file content for ConvertTo-SecureString operations.
|
|
||||||
|
|
||||||
.PARAMETER Path
|
|
||||||
The file you wish to create.
|
|
||||||
|
|
||||||
.PARAMETER KeySize
|
|
||||||
Specify the key size for the encryption key.
|
|
||||||
|
|
||||||
.PARAMETER Force
|
|
||||||
Use this switch to override an older file version.
|
|
||||||
|
|
||||||
.INPUTS
|
|
||||||
[None]
|
|
||||||
|
|
||||||
.OUTPUTS
|
|
||||||
[None]
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\Set-ChallengeFile -Path "C:\TMP\myfile.json" -Force
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
File Name : Set-ChallengeFile.ps1
|
|
||||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
|
||||||
Requires :
|
|
||||||
|
|
||||||
.LINK
|
|
||||||
https://github.com/OCram85/PSCredentialStore
|
|
||||||
#>
|
|
||||||
|
|
||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $false)]
|
|
||||||
[string]$Path = "{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $false)]
|
|
||||||
[ValidateSet(16, 24, 32)]
|
|
||||||
[string]$KeySize = "24",
|
|
||||||
|
|
||||||
[switch]$Force
|
|
||||||
)
|
|
||||||
|
|
||||||
if ((Test-Path -Path $Path)) {
|
|
||||||
if ($Force -eq $true) {
|
|
||||||
Remove-Item -Path $Path -Confirm:$false -Force
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Error "The given file already exists!. Use the -Force switch to override it." -ErrorAction Stop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$PSCredentialStoreDataDir = Split-Path -Path $Path -Parent
|
|
||||||
if (-not (Test-Path $PSCredentialStoreDataDir)) {
|
|
||||||
try {
|
|
||||||
New-Item -ItemType Directory -Path $PSCredentialStoreDataDir
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error ("Could not create the parent data dir {0}" -f $PSCredentialDataDir) -ErrorAction Stop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$Keys = Get-RandomKey -Size $KeySize
|
|
||||||
[io.file]::WriteAllBytes($Path, $Keys)
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
$_.Exception | Format-List -Force | Out-String | Write-Error -ErrorAction Stop
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
function Test-ChallengeFile {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Simple path check for challenge file needed by the CredentialStores.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
This is supposed to be a internal function to check the existence for a challenge file.
|
|
||||||
|
|
||||||
.PARAMETER Path
|
|
||||||
Specify the path to the challenge file.
|
|
||||||
|
|
||||||
.INPUTS
|
|
||||||
[None]
|
|
||||||
|
|
||||||
.OUTPUTS
|
|
||||||
[Bool].
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
If (Test-ChallengeFile) {
|
|
||||||
Write-Host "The file exists."
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning "Couldn't find the given file!"
|
|
||||||
}
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
File Name : Test-ChallengeFile.ps1
|
|
||||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
|
||||||
Requires :
|
|
||||||
|
|
||||||
.LINK
|
|
||||||
https://github.com/OCram85/PSCredentialStore
|
|
||||||
#>
|
|
||||||
|
|
||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $false)]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[String]$Path = "{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData
|
|
||||||
)
|
|
||||||
|
|
||||||
if (Test-Path $Path) {
|
|
||||||
$true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$false
|
|
||||||
}
|
|
||||||
}
|
|
@ -93,15 +93,30 @@ function Connect-To {
|
|||||||
[Parameter(Mandatory = $False, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $False, ParameterSetName = "Private")]
|
||||||
[PSCredential]$Credentials,
|
[PSCredential]$Credentials,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetNAme = "Shared")]
|
||||||
|
[switch]$Shared,
|
||||||
|
|
||||||
[Parameter(Mandatory = $False, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $False, ParameterSetName = "Shared")]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
[string]$Path,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetNAme = "Shared")]
|
[Parameter(Mandatory = $False, ParameterSetName = "Private")]
|
||||||
[switch]$Shared
|
[Parameter(Mandatory = $False, ParameterSetName = "Shared")]
|
||||||
|
[switch]$PassThru
|
||||||
)
|
)
|
||||||
|
|
||||||
begin {
|
begin {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# First check the optional modules
|
# First check the optional modules
|
||||||
if (-not (Resolve-Dependency -Name $Type)) {
|
if (-not (Resolve-Dependency -Name $Type)) {
|
||||||
Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f $Type) -ErrorAction 'Stop'
|
Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f $Type) -ErrorAction 'Stop'
|
||||||
@ -118,10 +133,6 @@ function Connect-To {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process {
|
process {
|
||||||
# Set the correct CredentialStore Path depending on the used ParameterSetName
|
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
|
||||||
}
|
|
||||||
if (-not ($Credentials)) {
|
if (-not ($Credentials)) {
|
||||||
# Load the credential from the CredentialStore. If the credential doesn't exist, we need to
|
# Load the credential from the CredentialStore. If the credential doesn't exist, we need to
|
||||||
# return 1, so a calling if statement can handle the failure detection.
|
# return 1, so a calling if statement can handle the failure detection.
|
||||||
@ -131,10 +142,10 @@ function Connect-To {
|
|||||||
try {
|
try {
|
||||||
if ($Identifier -ne "") {
|
if ($Identifier -ne "") {
|
||||||
$RemoteHostIdentifier = "{0}/{1}" -f $Identifier, $RemoteHost
|
$RemoteHostIdentifier = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||||
$creds = Get-CredentialStoreItem -RemoteHost $RemoteHostIdentifier -Path $Path
|
$creds = Get-CredentialStoreItem -Shared -RemoteHost $RemoteHostIdentifier -Path $Path
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$creds = Get-CredentialStoreItem -RemoteHost $RemoteHost -Path $Path
|
$creds = Get-CredentialStoreItem -Shared -RemoteHost $RemoteHost -Path $Path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,9 +239,15 @@ function Connect-To {
|
|||||||
}
|
}
|
||||||
"CisServer" {
|
"CisServer" {
|
||||||
try {
|
try {
|
||||||
|
if ($PassThru.IsPresent) {
|
||||||
|
Connect-CisServer -Server $RemoteHost -Credential $creds -ErrorAction Stop
|
||||||
|
}
|
||||||
|
else {
|
||||||
Connect-CisServer -Server $RemoteHost -Credential $creds -ErrorAction Stop | Out-Null
|
Connect-CisServer -Server $RemoteHost -Credential $creds -ErrorAction Stop | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
catch {
|
catch {
|
||||||
# Write a error message to the log.
|
# Write a error message to the log.
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
function Get-RandomKey {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Returns a random key
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
You can use the key for further use with SecureStrings.
|
|
||||||
|
|
||||||
.PARAMETER Size
|
|
||||||
Define the key size. You can choose between 16, 24 and 32
|
|
||||||
|
|
||||||
.INPUTS
|
|
||||||
[None]
|
|
||||||
|
|
||||||
.OUTPUTS
|
|
||||||
Returns a Random key as [Byte[]] array.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\Get-RandomKey -Size 24
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
```
|
|
||||||
File Name : Get-RandomKey.ps1
|
|
||||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
|
||||||
Requires :
|
|
||||||
```
|
|
||||||
|
|
||||||
.LINK
|
|
||||||
https://github.com/OCram85/PSCredentialStore
|
|
||||||
#>
|
|
||||||
|
|
||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[ValidateSet(16, 24, 32)]
|
|
||||||
[string]$size
|
|
||||||
)
|
|
||||||
# Init the vars
|
|
||||||
[Byte[]]$Key = @()
|
|
||||||
$i = 0
|
|
||||||
|
|
||||||
while ($i -ne $size) {
|
|
||||||
$element = Get-Random -Minimum 0 -Maximum 255
|
|
||||||
Write-Debug ("The current element is {0}." -f $element)
|
|
||||||
$Key += $element
|
|
||||||
$i++
|
|
||||||
}
|
|
||||||
$Key
|
|
||||||
}
|
|
@ -41,11 +41,8 @@ function Get-CredentialStoreItem {
|
|||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||||
[OutputType([System.Management.Automation.PSCredential])]
|
[OutputType([PSCredential])]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
@ -56,15 +53,28 @@ function Get-CredentialStoreItem {
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$Identifier,
|
[string]$Identifier,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
|
[switch]$Shared,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Path
|
||||||
)
|
)
|
||||||
|
|
||||||
# First set a constand path for private CredentialStore mode.
|
begin {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
if ($Identifier -ne "") {
|
if ($Identifier -ne "") {
|
||||||
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||||
}
|
}
|
||||||
@ -72,26 +82,24 @@ function Get-CredentialStoreItem {
|
|||||||
$CredentialName = $RemoteHost
|
$CredentialName = $RemoteHost
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-CredentialStore -Path $Path) {
|
if (Test-CredentialStore -Shared -Path $Path) {
|
||||||
$CS = Get-CredentialStore -Path $Path
|
$CS = Get-CredentialStore -Shared -Path $Path
|
||||||
$CSMembers = Get-Member -InputObject $CS
|
$CSMembers = Get-Member -InputObject $CS
|
||||||
# Let`s first check if the given remote host exists as object property
|
# Let's first check if the given remote host exists as object property
|
||||||
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -eq $CredentialName)) {
|
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) {
|
||||||
if ($CS.Type -eq "Private") {
|
$Cert = Get-PfxCertificate -FilePath $CS.PfXCertificate -ErrorAction Stop
|
||||||
$CSItem = [ordered]@{
|
$DecryptedKey = $Cert.PrivateKey.Decrypt(
|
||||||
User = $CS.$CredentialName.User
|
[Convert]::FromBase64String($CS.$CredentialName.EncryptedKey),
|
||||||
Password = ConvertTo-SecureString -String $CS.$CredentialName.Password
|
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
|
||||||
|
)
|
||||||
|
|
||||||
|
if (! $ExpandOutput.isPresent) {
|
||||||
|
[PSCredential]::new(
|
||||||
|
$CS.$CredentialName.User,
|
||||||
|
($CS.$CredentialName.Password | ConvertTo-SecureString -Key $DecryptedKey)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$Key = Get-ChallengeFile
|
|
||||||
$CSItem = [ordered]@{
|
|
||||||
User = $CS.$CredentialName.User
|
|
||||||
Password = ConvertTo-SecureString -String $CS.$CredentialName.Password -Key $Key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $CSItem.User, $CSItem.Password
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
$MsgParams = @{
|
$MsgParams = @{
|
||||||
ErrorAction = "Stop"
|
ErrorAction = "Stop"
|
||||||
@ -108,3 +116,9 @@ function Get-CredentialStoreItem {
|
|||||||
Write-Error @MsgParams
|
Write-Error @MsgParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -42,9 +42,6 @@ function New-CredentialStoreItem {
|
|||||||
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
@ -59,26 +56,51 @@ function New-CredentialStoreItem {
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[PSCredential]$Credential,
|
[PSCredential]$Credential,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
|
[switch]$Shared,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Path
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# First set a constand path for private CredentialStore mode.
|
begin {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
# Lets do a quick test on the given CredentialStore.
|
# Lets do a quick test on the given CredentialStore.
|
||||||
if (-not(Test-CredentialStore -Path $Path)) {
|
if (-not(Test-CredentialStore -Shared -Path $Path)) {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
Message = "Could not add anything into the given CredentailStore."
|
Exception = [System.IO.FileNotFoundException]::new(
|
||||||
|
'Could not add anything into the given CredentialStore.'
|
||||||
|
)
|
||||||
ErrorAction = "Stop"
|
ErrorAction = "Stop"
|
||||||
}
|
}
|
||||||
Write-Error @MessageParams
|
Write-Error @MessageParams
|
||||||
}
|
}
|
||||||
|
|
||||||
# Read the file content based on the given ParameterSetName
|
# Read the file content based on the given ParameterSetName
|
||||||
$CSContent = Get-CredentialStore -Path $Path
|
<#
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq 'Private') {
|
||||||
|
$CSContent = Get-CredentialStore
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
|
||||||
|
$CSContent = Get-CredentialStore -Shared -Path $Path
|
||||||
|
}
|
||||||
|
#>
|
||||||
|
$CSContent = Get-CredentialStore -Shared -Path $Path
|
||||||
|
|
||||||
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
@ -94,13 +116,20 @@ function New-CredentialStoreItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($Credential.UserName) {
|
if ($Credential.UserName) {
|
||||||
if ($CSContent.Type -eq "Shared") {
|
try {
|
||||||
$Key = Get-ChallengeFile
|
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
||||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password -Key $Key
|
|
||||||
}
|
}
|
||||||
else {
|
catch {
|
||||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password
|
$_.Exception.Message | Write-Error
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Security.Cryptography.CryptographicException]::new(
|
||||||
|
'Could not read the given PFX certificate.'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
|
||||||
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
|
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
Message = "The given host already exists. Nothing to do here."
|
Message = "The given host already exists. Nothing to do here."
|
||||||
@ -108,16 +137,20 @@ function New-CredentialStoreItem {
|
|||||||
Write-Warning @MessageParams
|
Write-Warning @MessageParams
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
$RSAKey = Get-RandomAESKey
|
||||||
|
|
||||||
$CredentialHash = [ordered]@{
|
$CredentialHash = [ordered]@{
|
||||||
User = $Credential.UserName
|
User = $Credential.UserName
|
||||||
Password = $encypted
|
Password = ConvertFrom-SecureString -SecureString $Credential.Password -Key $RSAKey
|
||||||
Creation = $CurrentDate
|
Created = $CurrentDate
|
||||||
|
LastChange = $null
|
||||||
|
EncryptedKey = [Convert]::ToBase64String($Cert.PublicKey.Key.Encrypt($RSAKey, [System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1))
|
||||||
}
|
}
|
||||||
Add-Member -InputObject $CSContent -Name $CredentialName -MemberType NoteProperty -Value $CredentialHash
|
Add-Member -InputObject $CSContent -Name $CredentialName -MemberType NoteProperty -Value $CredentialHash
|
||||||
try {
|
try {
|
||||||
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
|
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
|
||||||
}
|
}
|
||||||
catch [System.Exception] {
|
catch {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
Message = "Couldn't add item into credential store!"
|
Message = "Couldn't add item into credential store!"
|
||||||
ErrorAction = "Stop"
|
ErrorAction = "Stop"
|
||||||
@ -134,3 +167,9 @@ function New-CredentialStoreItem {
|
|||||||
Write-Error @MessageParams
|
Write-Error @MessageParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -27,8 +27,16 @@ function Remove-CredentialStoreItem {
|
|||||||
[None]
|
[None]
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
Remove-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local"
|
Remove-CredentialStoreItem -RemoteHost "esx01.myside.local"
|
||||||
Remove-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" -Identifier svc
|
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-CredentialStoreItem -Shared -RemoteHost "esx01.myside.local"
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-CredentialStoreItem -Shared -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local"
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-CredentialStoreItem -RemoteHost "esx01.myside.local" -Identifier svc
|
||||||
|
|
||||||
.NOTES
|
.NOTES
|
||||||
```
|
```
|
||||||
@ -43,9 +51,6 @@ function Remove-CredentialStoreItem {
|
|||||||
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[string]$RemoteHost,
|
[string]$RemoteHost,
|
||||||
@ -54,26 +59,39 @@ function Remove-CredentialStoreItem {
|
|||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[string]$Identifier,
|
[string]$Identifier,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
|
[switch]$Shared,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Path
|
||||||
)
|
)
|
||||||
|
|
||||||
# First set a constand path for private CredentialStore mode.
|
begin {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
# Lets do a quick test on the given CredentialStore.
|
# Lets do a quick test on the given CredentialStore.
|
||||||
if (-not(Test-CredentialStore -Path $Path)) {
|
if (-not(Test-CredentialStore -Shared -Path $Path)) {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
Message = "Could not add anything into the given CredentailStore."
|
Message = "Could not add anything into the given CredentialStore."
|
||||||
ErrorAction = "Stop"
|
ErrorAction = "Stop"
|
||||||
}
|
}
|
||||||
Write-Error @MessageParams
|
Write-Error @MessageParams
|
||||||
}
|
}
|
||||||
|
|
||||||
# Read the file content based on the given ParameterSetName
|
# Read the file content based on the given ParameterSetName
|
||||||
$CSContent = Get-CredentialStore -Path $Path
|
$CSContent = Get-CredentialStore -Shared -Path $Path
|
||||||
|
|
||||||
if ($Identifier -ne "") {
|
if ($Identifier -ne "") {
|
||||||
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||||
@ -82,15 +100,21 @@ function Remove-CredentialStoreItem {
|
|||||||
$CredentialName = $RemoteHost
|
$CredentialName = $RemoteHost
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
|
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype NoteProperty) {
|
||||||
# We need to use the .NET Method because there is no easier way in PowerShell.
|
# We need to use the .NET Method because there is no easier way in PowerShell.
|
||||||
$CSContent.PSObject.Properties.Remove($CredentialName)
|
$CSContent.PSObject.Properties.Remove($CredentialName)
|
||||||
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
|
ConvertTo-Json -InputObject $CSContent -Depth 5 | Out-File -FilePath $Path -Encoding utf8
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
Message = "The given CredentailStoreItem does not exist."
|
Message = "The given CredentialStoreItem does not exist."
|
||||||
}
|
}
|
||||||
Write-Warning @MessageParams
|
Write-Warning @MessageParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -42,9 +42,6 @@ function Set-CredentialStoreItem {
|
|||||||
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[string]$RemoteHost,
|
[string]$RemoteHost,
|
||||||
@ -57,17 +54,30 @@ function Set-CredentialStoreItem {
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[PSCredential]$Credential,
|
[PSCredential]$Credential,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
|
[switch]$Shared,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Path
|
||||||
)
|
)
|
||||||
|
|
||||||
# First set a constant path for private CredentialStore mode.
|
begin {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
# Lets do a quick test on the given CredentialStore.
|
# Lets do a quick test on the given CredentialStore.
|
||||||
if (-not(Test-CredentialStore -Path $Path)) {
|
if (-not(Test-CredentialStore -Shared -Path $Path)) {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
Message = "Could not add anything into the given CredentailStore."
|
Message = "Could not add anything into the given CredentailStore."
|
||||||
ErrorAction = "Stop"
|
ErrorAction = "Stop"
|
||||||
@ -76,7 +86,7 @@ function Set-CredentialStoreItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Read the file content based on the given ParameterSetName
|
# Read the file content based on the given ParameterSetName
|
||||||
$CSContent = Get-CredentialStore -Path $Path
|
$CSContent = Get-CredentialStore -Shared -Path $Path
|
||||||
|
|
||||||
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
@ -92,24 +102,31 @@ function Set-CredentialStoreItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($Credential.UserName) {
|
if ($Credential.UserName) {
|
||||||
if ($CSContent.Type -eq "Shared") {
|
try {
|
||||||
$Key = Get-ChallengeFile
|
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
||||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password -Key $Key
|
|
||||||
}
|
}
|
||||||
else {
|
catch {
|
||||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password
|
$_.Exception.Message | Write-Error
|
||||||
|
$ErrorParams = @{
|
||||||
|
Message = 'Could not read the given PFX certificate.'
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Security.Cryptography.CryptographicException]::new()
|
||||||
}
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
|
||||||
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
|
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
|
||||||
|
$RSAKey = Get-RandomAESKey
|
||||||
$CSContent.$CredentialName.User = $Credential.UserName
|
$CSContent.$CredentialName.User = $Credential.UserName
|
||||||
$CSContent.$CredentialName.Password = $encypted
|
$CSContent.$CredentialName.Password = ConvertFrom-SecureString -SecureString $Credential.Password -Key $RSAKey
|
||||||
$CSContent.$CredentialName.Creation = $CurrentDate
|
$CSContent.$CredentialName.LastChange = $CurrentDate
|
||||||
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
|
$CSContent.$CredentialName.EncryptedKey = [Convert]::ToBase64String(
|
||||||
}
|
$Cert.PublicKey.Key.Encrypt(
|
||||||
else {
|
$RSAKey,
|
||||||
$MessageParams = @{
|
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
|
||||||
Message = "The given CredentailStoreItem does not exist."
|
)
|
||||||
}
|
)
|
||||||
Write-Warning @MessageParams
|
ConvertTo-Json -InputObject $CSContent -Depth 5 | Out-File -FilePath $Path -Encoding utf8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Else {
|
Else {
|
||||||
@ -120,3 +137,8 @@ function Set-CredentialStoreItem {
|
|||||||
Write-Error @MessageParams
|
Write-Error @MessageParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
function Test-CredentialStoreItem() {
|
function Test-CredentialStoreItem {
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Checks if the given RemoteHost identifier combination exists in the credential store.
|
Checks if the given RemoteHost identifier combination exists in the credential store.
|
||||||
@ -64,10 +64,20 @@ function Test-CredentialStoreItem() {
|
|||||||
[switch]$Shared
|
[switch]$Shared
|
||||||
)
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
if ($Identifier -ne "") {
|
if ($Identifier -ne "") {
|
||||||
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||||
}
|
}
|
||||||
@ -75,10 +85,10 @@ function Test-CredentialStoreItem() {
|
|||||||
$CredentialName = $RemoteHost
|
$CredentialName = $RemoteHost
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-CredentialStore -Path $Path) {
|
if (Test-CredentialStore -Shared -Path $Path) {
|
||||||
$CS = Get-CredentialStore -Path $Path
|
$CS = Get-CredentialStore -Shared -Path $Path
|
||||||
$CSMembers = Get-Member -InputObject $CS
|
$CSMembers = Get-Member -InputObject $CS
|
||||||
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -eq $CredentialName)) {
|
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) {
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -93,3 +103,9 @@ function Test-CredentialStoreItem() {
|
|||||||
Write-Error @MsgParams
|
Write-Error @MsgParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,22 +1,13 @@
|
|||||||
#
|
|
||||||
# Module manifest for module 'PSCredentialStore'
|
|
||||||
#
|
|
||||||
# Generated by: OCram85
|
|
||||||
#
|
|
||||||
# Generated on: 27.07.2017
|
|
||||||
#
|
|
||||||
|
|
||||||
@{
|
@{
|
||||||
|
|
||||||
# Script module or binary module file associated with this manifest.
|
# Script module or binary module file associated with this manifest.
|
||||||
RootModule = 'PSCredentialStore'
|
RootModule = 'PSCredentialStore.psm1'
|
||||||
|
|
||||||
# Version number of this module.
|
# Version number of this module.
|
||||||
# Do not touch the version number. It gets replaced in the build process.
|
ModuleVersion = '0.0.9999'
|
||||||
ModuleVersion = '0.0.0.9999'
|
|
||||||
|
|
||||||
# Supported PSEditions
|
# Supported PSEditions
|
||||||
# CompatiblePSEditions = @()
|
CompatiblePSEditions = 'Desktop', 'Core'
|
||||||
|
|
||||||
# ID used to uniquely identify this module
|
# ID used to uniquely identify this module
|
||||||
GUID = '6800e192-9df8-4e30-b253-eb2c799bbe84'
|
GUID = '6800e192-9df8-4e30-b253-eb2c799bbe84'
|
||||||
@ -28,18 +19,18 @@
|
|||||||
CompanyName = ''
|
CompanyName = ''
|
||||||
|
|
||||||
# Copyright statement for this module
|
# Copyright statement for this module
|
||||||
Copyright = '(c) 2017 OCram85. All rights reserved.'
|
Copyright = '(c) 2019 OCram85. All rights reserved.'
|
||||||
|
|
||||||
# Description of the functionality provided by this module
|
# Description of the functionality provided by this module
|
||||||
Description = 'A simple credential manager to store and reuse multiple credential objects.'
|
Description = 'A simple credential manager to store and reuse multiple credential objects.'
|
||||||
|
|
||||||
# Minimum version of the Windows PowerShell engine required by this module
|
# Minimum version of the PowerShell engine required by this module
|
||||||
PowerShellVersion = '4.0'
|
PowerShellVersion = '5.1'
|
||||||
|
|
||||||
# Name of the Windows PowerShell host required by this module
|
# Name of the PowerShell host required by this module
|
||||||
# PowerShellHostName = ''
|
# PowerShellHostName = ''
|
||||||
|
|
||||||
# Minimum version of the Windows PowerShell host required by this module
|
# Minimum version of the PowerShell host required by this module
|
||||||
# PowerShellHostVersion = ''
|
# PowerShellHostVersion = ''
|
||||||
|
|
||||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||||
@ -71,21 +62,25 @@
|
|||||||
|
|
||||||
# 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.
|
# 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 = @(
|
FunctionsToExport = @(
|
||||||
# Connection Group
|
# Certificate
|
||||||
|
'New-CRTAttribute',
|
||||||
|
'New-PfxCertificate',
|
||||||
|
'Use-PfxCertificate',
|
||||||
|
# Connection
|
||||||
'Connect-To',
|
'Connect-To',
|
||||||
'Disconnect-From',
|
'Disconnect-From',
|
||||||
'Test-CSConnection',
|
'Test-CSConnection',
|
||||||
# Item Group
|
# Item
|
||||||
'Get-CredentialStoreItem',
|
'Get-CredentialStoreItem',
|
||||||
'Set-CredentialStoreItem',
|
|
||||||
'New-CredentialStoreItem',
|
'New-CredentialStoreItem',
|
||||||
'Remove-CredentialStoreItem',
|
'Remove-CredentialStoreItem',
|
||||||
|
'Set-CredentialStoreItem',
|
||||||
'Test-CredentialStoreItem',
|
'Test-CredentialStoreItem',
|
||||||
# Store Group
|
# Store
|
||||||
'Get-CredentialStore',
|
'Get-CredentialStore',
|
||||||
'New-CredentialStore',
|
'New-CredentialStore',
|
||||||
'Test-CredentialStore'
|
'Test-CredentialStore',
|
||||||
|
'Update-CredentialStore'
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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.
|
# 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.
|
||||||
@ -112,9 +107,7 @@
|
|||||||
PSData = @{
|
PSData = @{
|
||||||
|
|
||||||
# Tags applied to this module. These help with module discovery in online galleries.
|
# Tags applied to this module. These help with module discovery in online galleries.
|
||||||
Tags = @('CredentialStore',
|
Tags = 'CredentialStore', 'CredentialManager'
|
||||||
'CredentialManager'
|
|
||||||
)
|
|
||||||
|
|
||||||
# A URL to the license for this module.
|
# A URL to the license for this module.
|
||||||
LicenseUri = 'https://github.com/OCram85/PSCredentialStore/blob/master/LICENSE'
|
LicenseUri = 'https://github.com/OCram85/PSCredentialStore/blob/master/LICENSE'
|
||||||
@ -123,11 +116,20 @@
|
|||||||
ProjectUri = 'https://github.com/OCram85/PSCredentialStore'
|
ProjectUri = 'https://github.com/OCram85/PSCredentialStore'
|
||||||
|
|
||||||
# A URL to an icon representing this module.
|
# A URL to an icon representing this module.
|
||||||
# IconUri = ''
|
IconUri = 'https://raw.githubusercontent.com/OCram85/PSCredentialStore/master/assets/logo256.png'
|
||||||
|
|
||||||
# ReleaseNotes of this module
|
# ReleaseNotes of this module
|
||||||
ReleaseNotes = 'This is a pre-release version!. Do not use in production!'
|
ReleaseNotes = 'This is a pre-release version!. Do not use in production!'
|
||||||
|
|
||||||
|
# Prerelease string of this module
|
||||||
|
Prerelease = 'alpha1'
|
||||||
|
|
||||||
|
# Flag to indicate whether the module requires explicit user acceptance for install/update
|
||||||
|
# RequireLicenseAcceptance = $false
|
||||||
|
|
||||||
|
# External dependent modules of this module
|
||||||
|
# ExternalModuleDependencies = @()
|
||||||
|
|
||||||
} # End of PSData hashtable
|
} # End of PSData hashtable
|
||||||
|
|
||||||
} # End of PrivateData hashtable
|
} # End of PrivateData hashtable
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
$Items = (Get-ChildItem -Path ("{0}\*.ps1" -f $PSScriptRoot ) -Recurse ).FullName | Where-Object {
|
#region module-definition
|
||||||
|
|
||||||
|
#endregion module-definition
|
||||||
|
Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope 'Script' -ErrorAction Stop
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region dot-sourcing
|
||||||
|
# dot-sourcing all module functions. The export is handled via manifest file.
|
||||||
|
|
||||||
|
$Items = (Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath '*.ps1') -Recurse ).FullName | Where-Object {
|
||||||
$_ -notmatch "(Classes|Init)"
|
$_ -notmatch "(Classes|Init)"
|
||||||
}
|
}
|
||||||
ForEach ($Item in $Items) {
|
foreach ($Item in $Items) {
|
||||||
# Write-Verbose ("dot sourcing file {0}" -f $Item)
|
# Write-Verbose ("dot sourcing file {0}" -f $Item)
|
||||||
. $Item
|
. $Item
|
||||||
}
|
}
|
||||||
|
#endregion dot-sourcing
|
||||||
# Exports are now controlled by module manifest
|
|
||||||
# Export-ModuleMember -Function *
|
|
||||||
|
61
src/Private/Get-DefaultCredentialStorePath.ps1
Normal file
61
src/Private/Get-DefaultCredentialStorePath.ps1
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
function Get-DefaultCredentialStorePath {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Returns the default CredentialStore path based on the current OS.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This is a low level helper function.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
[None]
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
[string]
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Get-DefaultCredentialStorePath.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([string])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[switch]$Shared
|
||||||
|
)
|
||||||
|
|
||||||
|
begin {}
|
||||||
|
|
||||||
|
process {
|
||||||
|
if ($Shared.IsPresent) {
|
||||||
|
if ($IsLinux) {
|
||||||
|
return Join-Path -Path '/var/opt' -ChildPath 'PSCredentialStore/CredentialStore.json'
|
||||||
|
}
|
||||||
|
if ($IsMacOS) {
|
||||||
|
return Join-Path -Path '/var/opt' -ChildPath 'PSCredentialStore/CredentialStore.json'
|
||||||
|
}
|
||||||
|
elseif (($isWindows) -or ($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop')) {
|
||||||
|
return Join-Path -Path $env:ProgramData -ChildPath 'PSCredentialStore/CredentialStore.json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($IsLinux) {
|
||||||
|
return Join-Path -Path $Env:HOME -ChildPath 'CredentialStore.json'
|
||||||
|
}
|
||||||
|
if ($IsMacOS) {
|
||||||
|
return Join-Path -Path $Env:HOME -ChildPath 'CredentialStore.json'
|
||||||
|
}
|
||||||
|
elseif (($isWindows) -or ($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop')) {
|
||||||
|
return Join-Path -Path $env:AppData -ChildPath 'CredentialStore.json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end {}
|
||||||
|
}
|
44
src/Private/Get-RandomAESKey.ps1
Normal file
44
src/Private/Get-RandomAESKey.ps1
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
function Get-RandomAESKey {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Generate a new 32-byte AES key.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Uses the System.Security.Cryptography namespace for random aes key generation.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
[None]
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
[byte[]]
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Get-RandomAESKey
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Get-RandomAESKey.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([byte[]])]
|
||||||
|
param()
|
||||||
|
|
||||||
|
begin {}
|
||||||
|
|
||||||
|
process {
|
||||||
|
$key = [byte[]]::new(32)
|
||||||
|
$rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()
|
||||||
|
$rng.GetBytes($key)
|
||||||
|
Write-Output $key
|
||||||
|
if ($null -ne $key) {
|
||||||
|
[array]::Clear($key, 0, $key.Length)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
end {}
|
||||||
|
}
|
44
src/Private/Get-TempDir.ps1
Normal file
44
src/Private/Get-TempDir.ps1
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
function Get-TempDir {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Returns the valid temp dir of the current OS
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Returns the valid temp dir of the current OS.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
[None]
|
||||||
|
.OUTPUTS
|
||||||
|
[string]
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-TempDir
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Get-TempDir.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([string])]
|
||||||
|
param()
|
||||||
|
begin {
|
||||||
|
|
||||||
|
}
|
||||||
|
process {
|
||||||
|
if ($IsLinux) {
|
||||||
|
return (Resolve-Path -Path '/tmp/').Path
|
||||||
|
}
|
||||||
|
if ($IsMacOS) {
|
||||||
|
return (Resolve-Path -Path '/tmp/').Path
|
||||||
|
}
|
||||||
|
elseif (($isWindows) -or ($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop')) {
|
||||||
|
return (Resolve-Path -Path $env:TEMP).Path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end {
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ function Test-Module {
|
|||||||
|
|
||||||
.NOTES
|
.NOTES
|
||||||
```
|
```
|
||||||
File Name : Get-RandomKey.ps1
|
File Name : Test-Module.ps1
|
||||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
Requires :
|
Requires :
|
||||||
```
|
```
|
||||||
@ -50,10 +50,6 @@ function Test-Module {
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$Name,
|
[string]$Name,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false)]
|
|
||||||
[ValidateSet('Module', 'PSSnapin', 'Custom')]
|
|
||||||
[string]$Type = 'Module',
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $false)]
|
[Parameter(Mandatory = $false)]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$MessagePattern = @"
|
[string]$MessagePattern = @"
|
||||||
@ -62,15 +58,12 @@ Could not find the required {0} called {1}. Please install the required {0} to r
|
|||||||
[Parameter(Mandatory = $false)]
|
[Parameter(Mandatory = $false)]
|
||||||
[switch]$StopIfFails
|
[switch]$StopIfFails
|
||||||
)
|
)
|
||||||
begin {
|
begin {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
process {
|
process {
|
||||||
$Message = $MessagePattern -f $Type, $Name
|
$Message = $MessagePattern -f $Type, $Name
|
||||||
Write-Debug $Message
|
Write-Debug $Message
|
||||||
switch ($Type) {
|
|
||||||
'Module' {
|
|
||||||
if (Get-Module -Name $Name -ListAvailable) {
|
if (Get-Module -Name $Name -ListAvailable) {
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
@ -82,25 +75,5 @@ Could not find the required {0} called {1}. Please install the required {0} to r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'PSSnapin' {
|
end {}
|
||||||
if (Get-PSSnapin -Name $Name -Registered -ErrorAction SilentlyContinue) {
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ($StopIfFails) {
|
|
||||||
Write-Error -Message $Message -ErrorAction Stop -Category NotInstalled
|
|
||||||
}
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
'Custom' {
|
|
||||||
Throw 'Custom tests are not implemented yet!'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -35,22 +35,36 @@ function Get-CredentialStore {
|
|||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||||
|
[OutputType("PSCredentialStore.Store")]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[string]$Path,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared
|
[switch]$Shared
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($PSCmdlet.ParameterSetName -eq 'Private') {
|
begin {}
|
||||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
|
||||||
|
process {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-CredentialStore -Path $Path) {
|
if (Test-CredentialStore -Path $Path -Shared) {
|
||||||
try {
|
try {
|
||||||
$FileContent = Get-Content -Path $Path -Raw
|
$FileContent = Get-Content -Path $Path -Raw
|
||||||
ConvertFrom-Json $FileContent
|
$CS = ConvertFrom-Json $FileContent
|
||||||
|
$CS.PSObject.TypeNames.Insert(0, "PSCredentialStore.Store")
|
||||||
|
return $CS
|
||||||
}
|
}
|
||||||
catch [System.Exception] {
|
catch [System.Exception] {
|
||||||
$MessageParams = @{
|
$MessageParams = @{
|
||||||
@ -68,3 +82,7 @@ function Get-CredentialStore {
|
|||||||
Write-Error @MessageParams
|
Write-Error @MessageParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -22,7 +22,8 @@ function New-CredentialStore {
|
|||||||
[None]
|
[None]
|
||||||
|
|
||||||
.OUTPUTS
|
.OUTPUTS
|
||||||
[None]
|
['PSCredentialStore.Store'] Returns the recently created CredentialStore object if the -PassThru parameter
|
||||||
|
was given.
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
New-CredentialStore
|
New-CredentialStore
|
||||||
@ -50,63 +51,163 @@ function New-CredentialStore {
|
|||||||
https://github.com/OCram85/PSCredentialStore
|
https://github.com/OCram85/PSCredentialStore
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = "Private")]
|
||||||
|
[OutputType("PSCredentialStore.Store")]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared,
|
[switch]$Shared,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
[string]$Path,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$Force
|
[switch]$Force,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
|
[switch]$PassThru,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
|
[Switch]$SkipPFXCertCreation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
# Lets get the current Date in a human readable format.
|
# Lets get the current Date in a human readable format.
|
||||||
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
# Set latest Credential Store version
|
# Set latest Credential Store version
|
||||||
Set-Variable -Name "CSVersion" -Value "1.2.0" -Option Constant
|
# Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope
|
||||||
|
}
|
||||||
|
|
||||||
# Set the CredentialStore path for private mode.
|
process {
|
||||||
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
$Path = "{0}\CredentialStore.json" -f $Env:APPDATA
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test if in the given store already a CredentialStore exists.
|
# Test if in the CredentialStore already exists.
|
||||||
Write-Verbose "Test if there is already a credential store."
|
Write-Verbose "Test if there is already a credential store."
|
||||||
if ((Test-CredentialStore -Path $Path) -and ($Force -ne $true)) {
|
if ((Test-Path -Path $Path) -and ($Force -ne $true)) {
|
||||||
$MessageParam = @{
|
$ErrorParams = @{
|
||||||
Message = "The given file already exists. Use the 'Force' switch to override the existing store."
|
ErrorAction = 'Stop'
|
||||||
ErrorAction = "Stop"
|
Exception = [System.InvalidOperationException]::new(
|
||||||
|
'The given file already exists. Use the -Force switch to override the existing store.'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Write-Error @MessageParam
|
Write-Error @ErrorParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! $SkipPFXCertCreation.IsPresent) {
|
||||||
|
$CRTParams = @{
|
||||||
|
Country = 'DE'
|
||||||
|
State = 'PSCredentialStore'
|
||||||
|
City = 'PSCredentialStore'
|
||||||
|
Organization = 'PSCredentialStore'
|
||||||
|
OrganizationalUnitName = ' '
|
||||||
|
CommonName = 'PrivateStore'
|
||||||
|
}
|
||||||
|
$CRTAttribute = New-CRTAttribute @CRTParams
|
||||||
|
|
||||||
|
# If we are working with a ne shared store we have to create the location first.
|
||||||
|
# Otherwise openssl fails with unknown path
|
||||||
|
|
||||||
|
$StoreHome = Split-Path -Path $Path -Parent
|
||||||
|
if (! (Test-Path -Path $StoreHome)) {
|
||||||
|
New-Item -ItemType Directory -Path $StoreHome -ErrorAction Stop
|
||||||
|
}
|
||||||
|
|
||||||
|
$PfxParams = @{
|
||||||
|
CRTAttribute = $CRTAttribute
|
||||||
|
KeyName = Join-Path -Path $StoreHome -ChildPath 'private.key'
|
||||||
|
CertName = Join-Path -Path $StoreHome -ChildPath 'PSCredentialStore.pfx'
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Confirm = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Test-Path $PfxParams.CertName) -and (! $Force.IsPresent)) {
|
||||||
|
$ErrorParams = @{
|
||||||
|
Exception = [System.IO.InvalidDataException]::new(
|
||||||
|
'There is already a PfxCertificate for a private CredentialStore!'
|
||||||
|
)
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
New-PfxCertificate @PfxParams
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Exception]::new(
|
||||||
|
'Could not create the private PfXCertificate!'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$FreshCert = Get-PfxCertificate -FilePath $PfxParams.CertName -ErrorAction Stop
|
||||||
|
}
|
||||||
|
catch [System.Management.Automation.ItemNotFoundException] {
|
||||||
|
$_.Exception.Message | Write-Error
|
||||||
|
Write-Error -Message 'Could not read the new PfxCertificate.' -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# We need to use the IDictionary to keep the property sorting in the object.
|
# We need to use the IDictionary to keep the property sorting in the object.
|
||||||
$ObjProperties = [ordered]@{
|
$ObjProperties = [ordered]@{
|
||||||
|
PSTypeName = 'PSCredentialStore.Store'
|
||||||
Version = $CSVersion
|
Version = $CSVersion
|
||||||
Creation = $CurrentDate
|
Created = $CurrentDate
|
||||||
|
PfxCertificate = $null
|
||||||
|
Thumbprint = $null
|
||||||
|
Type = $null
|
||||||
}
|
}
|
||||||
|
if (! $SkipPFXCertCreation.IsPresent) {
|
||||||
|
$ObjProperties.PfXCertificate = $PfxParams.CertName
|
||||||
|
$ObjProperties.Thumbprint = $FreshCert.Thumbprint
|
||||||
|
}
|
||||||
|
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Shared") {
|
if ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
$ObjProperties.Type = "Shared"
|
$ObjProperties.Type = "Shared"
|
||||||
# Check if a ChallengeFile already exists. We don't want to overide it.
|
|
||||||
# Otherwise previous created CredentialStores couln't be decrypted anymore.
|
|
||||||
if (-not (Test-ChallengeFile)) {
|
|
||||||
Set-ChallengeFile
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$ObjProperties.Type = "Private"
|
$ObjProperties.Type = "Private"
|
||||||
}
|
}
|
||||||
# Create a new object for easy conversion into a json file
|
|
||||||
$CredentialStoreObj = New-Object -TypeName psobject -Property $ObjProperties
|
$CredentialStoreObj = [PSCustomObject]$ObjProperties
|
||||||
try {
|
try {
|
||||||
ConvertTo-Json -InputObject $CredentialStoreObj | Out-File -FilePath $Path
|
$JSON = ConvertTo-Json -InputObject $CredentialStoreObj -ErrorAction Stop
|
||||||
|
$JSON | Out-File -FilePath $Path -ErrorAction Stop -Force
|
||||||
}
|
}
|
||||||
catch [System.Exception] {
|
catch {
|
||||||
$_.Exception | Format-List -Force | Out-String | Write-Error -ErrorAction Stop
|
$_.Exception.Message | Write-Error
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.IO.IOException]::new(
|
||||||
|
'Unable to convert or write the CredentialStore'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PassThru.IsPresent) {
|
||||||
|
return $CredentialStoreObj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,37 +26,40 @@ function Test-CredentialStore {
|
|||||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
[string]$Path,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||||
[switch]$Shared
|
[switch]$Shared
|
||||||
)
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
# Set latest Credential Store version
|
||||||
$Path = "{0}\CredentialStore.json" -f $Env:APPDATA
|
#Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set latest Credential Store version
|
process {
|
||||||
Set-Variable -Name "CSVersion" -Value "1.2.0" -Option Constant
|
# Set the CredentialStore for private, shared or custom mode.
|
||||||
|
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||||
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
}
|
||||||
|
elseif ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
if (!($PSBoundParameters.ContainsKey('Path'))) {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Verbose -Message ("Path is: {0}" -f $Path)
|
||||||
|
|
||||||
if (Test-Path $Path) {
|
if (Test-Path $Path) {
|
||||||
Write-Verbose "CredentialStore in given path found."
|
Write-Verbose "CredentialStore in given path found."
|
||||||
|
return $true
|
||||||
# try tor read the store. Removed the Get-CredentialStore function to avoid recursive calls.
|
|
||||||
try {
|
|
||||||
$FileContent = Get-Content -Path $Path -Raw
|
|
||||||
$CSContent = ConvertFrom-Json $FileContent
|
|
||||||
}
|
}
|
||||||
catch {
|
else {
|
||||||
Write-Warning "Could not read or convert the given CredentialStore."
|
|
||||||
Return $False
|
|
||||||
}
|
|
||||||
Return $True
|
|
||||||
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Verbose "The given CredentialStore does not exist!"
|
Write-Verbose "The given CredentialStore does not exist!"
|
||||||
Return $False
|
return $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end {}
|
||||||
|
|
||||||
|
}
|
||||||
|
140
src/Store/Update-CredentialStore.ps1
Normal file
140
src/Store/Update-CredentialStore.ps1
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
function Update-CredentialStore {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
A brief description of the function or script.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Describe the function of the script using a single sentence or more.
|
||||||
|
|
||||||
|
.PARAMETER One
|
||||||
|
Description of the Parameter (what it does)
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
Describe the script input parameters (if any), otherwise it may also list the word "[None]".
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
Describe the script output parameters (if any), otherwise it may also list the word "[None]".
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Remove-Some-Script.ps1 -One content
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Update-CredentialStore.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[Version]$From = '1.2.0',
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[Version]$To = '2.0.0',
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Path,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$PfxCertificate
|
||||||
|
|
||||||
|
)
|
||||||
|
begin {
|
||||||
|
}
|
||||||
|
process {
|
||||||
|
if (Test-Path -Path $Path) {
|
||||||
|
$CSOld = Get-CredentialStore -Shared -Path $Path -ErrorAction Stop
|
||||||
|
if ($CSOld.Version -ne $From) {
|
||||||
|
$ErrorParams = @{
|
||||||
|
Message = 'Can not migrate CredentialStore from version {0} to {1}' -f $From, $To
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Exception]::new()
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
|
||||||
|
$CSNew = [PSCustomObject]@{
|
||||||
|
PSTypeName = 'PSCredentialStore.Store'
|
||||||
|
Version = $To
|
||||||
|
Created = $CurrentDate
|
||||||
|
PfxCertificate = $null
|
||||||
|
Thumbprint = $null
|
||||||
|
Type = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PWD -eq (Get-DefaultCredentialStorePath)) {
|
||||||
|
$CSNew.Type = 'Private'
|
||||||
|
}
|
||||||
|
elseif ($PWD -eq (Get-DefaultCredentialStorePath -Shared)) {
|
||||||
|
$CSNew.Type = 'Shared'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ErrorParams = @{
|
||||||
|
Message = 'Can not determine a valid CredentialStore Type!'
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Exception]::new()
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
$Cert = Get-PfxCertificate -FilePath $PfxCertificate -ErrorAction Stop
|
||||||
|
|
||||||
|
$CSNew.PfxCertificate = Join-Path -Path $PfxCertificate
|
||||||
|
$CSNew.Thumbprint = $Cert.Thumbprint
|
||||||
|
|
||||||
|
|
||||||
|
$CredentialItems = $CSOld | Get-Member -MemberType NoteProperty | Where-Object {
|
||||||
|
$_.Definition -like "*.PSCustomObject*"
|
||||||
|
} | Select-Object -ExpandProperty Name
|
||||||
|
|
||||||
|
# iterate through all existing items
|
||||||
|
foreach ($Item in $CredentialItems) {
|
||||||
|
|
||||||
|
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
||||||
|
$RSAKey = Get-RandomAESKey
|
||||||
|
|
||||||
|
$CredentialObj = [PSCustomObject]@{
|
||||||
|
User = $Item.UserName
|
||||||
|
Password = $null
|
||||||
|
Created = $CurrentDate
|
||||||
|
LastChange = $null
|
||||||
|
EncryptedKey = [Convert]::ToBase64String(
|
||||||
|
$Cert.PublicKey.Key.Encrypt(
|
||||||
|
$RSAKey,
|
||||||
|
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if ($CSOld.Type -eq 'Private') {
|
||||||
|
$CredentialObject.Password = ConvertTo-SecureString -SecureString $Item.Password | ConvertFrom-SecureString -Key $RSAKey
|
||||||
|
}
|
||||||
|
elseif ($CSNew.Type -eq 'Shared') {
|
||||||
|
$ChallengeKey = [io.file]::ReadAllBytes((Join-Path -Path $PWD -ChildPath '/Challenge.bin'))
|
||||||
|
$CredentialObject.Password = ConvertTo-SecureString -SecureString $Item.Password -Key $ChallengeKey | ConvertFrom-SecureString -Key $RSAKey
|
||||||
|
}
|
||||||
|
Add-Member -InputObject $CSNew -Name (
|
||||||
|
($Item | Get-Variable).Name
|
||||||
|
) -MemberType NoteProperty -Value $CredentialObj
|
||||||
|
}
|
||||||
|
$CSNew | ConvertTo-Json -Depth 5 | Out-File -LiteralPath (
|
||||||
|
Join-Path -Path $PWD -ChildPath './CredentialStore.json'
|
||||||
|
) -Encoding utf8 -Confirm:$true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ErrorParams = @{
|
||||||
|
Message = 'Could not find the given CredentialStore path!'
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.IO.FileNotFoundException]::new()
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end {
|
||||||
|
}
|
||||||
|
}
|
BIN
src/Vendor/libressl255/LICENSE
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/LICENSE
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libcrypto-41.dll
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libcrypto-41.dll
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libcrypto-41.exp
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libcrypto-41.exp
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libcrypto-41.lib
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libcrypto-41.lib
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libcrypto-41.pdb
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libcrypto-41.pdb
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libssl-43.dll
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libssl-43.dll
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libssl-43.exp
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libssl-43.exp
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libssl-43.lib
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libssl-43.lib
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libssl-43.pdb
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libssl-43.pdb
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libtls-15.dll
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libtls-15.dll
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libtls-15.exp
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libtls-15.exp
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libtls-15.lib
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libtls-15.lib
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/libtls-15.pdb
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/libtls-15.pdb
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/ocspcheck.exe
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/ocspcheck.exe
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
src/Vendor/libressl255/openssl.exe
(Stored with Git LFS)
vendored
Normal file
BIN
src/Vendor/libressl255/openssl.exe
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
245
src/openssl.conf
Normal file
245
src/openssl.conf
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
# extensions =
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
dir = ./demoCA # Where everything is kept
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem # The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extentions to add to the cert
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days = 30 # how long before next CRL
|
||||||
|
default_md = md5 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = DE
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = BW
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = PSCredentialStore
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = PSCredentialStore
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
#organizationalUnitName_default = PSCRedentialStore
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 40
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 0
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, codeSigning
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier = hash
|
||||||
|
authorityKeyIdentifier = keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, codeSigning
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier = keyid:always,issuer:always
|
@ -1,15 +1,17 @@
|
|||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
$RepoRoot = (Get-Item -Path (Get-GitDirectory) -Force).Parent | Select-Object -ExpandProperty 'FullName'
|
||||||
|
Write-Verbose -Message ('RepoRoot: {0}' -f $RepoRoot) -Verbose
|
||||||
|
|
||||||
|
$ManifestFilePath = Join-Path -Path $RepoRoot -ChildPath '/src/PSCredentialStore.psd1'
|
||||||
|
Write-Verbose -Message ("ManifestFilePath: {0}" -f $ManifestFilePath) -Verbose
|
||||||
Describe "Pre-Flight module tests" {
|
Describe "Pre-Flight module tests" {
|
||||||
$ManifestFilePath = "{0}\src\PSCredentialstore.psd1" -f $RepoRoot
|
|
||||||
Context "Manifest file related" {
|
Context "Manifest file related" {
|
||||||
It "Test the parsed file itsef" {
|
It "Test the parsed file itself" {
|
||||||
{ Test-ModuleManifest -Path $ManifestFilePath } | Should -Not -Throw
|
{ Test-ModuleManifest -Path $ManifestFilePath -Verbose } | Should -Not -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Context "Module consistency tests" {
|
Context "Module consistency tests" {
|
||||||
IT "Importing should work" {
|
It "Importing should work" {
|
||||||
{ Import-Module -Name $ManifestFilePath -Global -Force }| Should -Not -Throw
|
{ Import-Module -Name $ManifestFilePath -Global -Force -Verbose } | Should -Not -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Get-RandomKey.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Set-ChallengeFile" {
|
|
||||||
Context "Tests with custom path" {
|
|
||||||
It "Working dir and path not exist" {
|
|
||||||
{Set-ChallengeFile -Path 'C:\PSCredentialStore\Challenge.bin'} | Should -Not -Throw
|
|
||||||
}
|
|
||||||
It "No parameter and non file should return true" {
|
|
||||||
if (Test-Path -Path ("{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData)) {
|
|
||||||
Remove-Item -Path ("{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData)
|
|
||||||
}
|
|
||||||
Set-ChallengeFile
|
|
||||||
Test-Path -Path ("{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData) | Should -Be $true
|
|
||||||
}
|
|
||||||
It "Existing Credential file should return error" {
|
|
||||||
{ Set-ChallengeFile } | Should -Throw
|
|
||||||
Remove-Item -Path ("{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData)
|
|
||||||
}
|
|
||||||
It "Use -Force switch should create a new challenge file" {
|
|
||||||
# prepare for test and clean up old data
|
|
||||||
if (Test-Path -Path ("{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData)) {
|
|
||||||
Remove-Item -Path ("{0}\PSCredentialStore\Challenge.bin" -f $env:ProgramData)
|
|
||||||
}
|
|
||||||
Set-ChallengeFile
|
|
||||||
{ Set-ChallengeFile -Force } | Should -Not -Throw
|
|
||||||
}
|
|
||||||
It "Test directory creation for shared store" {
|
|
||||||
if (Test-Path -Path ("{0}\PSCredentialStore" -f $env:ProgramData)) {
|
|
||||||
Remove-Item -Path ("{0}\PSCredentialStore" -f $env:ProgramData) -Force -Recurse
|
|
||||||
}
|
|
||||||
Set-ChallengeFile
|
|
||||||
Test-Path -Path ("{0}\PSCredentialStore" -f $env:ProgramData) | Should -Be $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "General Exception handling" {
|
|
||||||
Mock New-Item {throw "foobar exception"}
|
|
||||||
It "Test exception handling if the root directory could not be created" {
|
|
||||||
if (Test-Path -Path ("{0}\PSCredentialStore" -f $env:ProgramData)) {
|
|
||||||
Remove-Item -Path ("{0}\PSCredentialStore" -f $env:ProgramData) -Force -Recurse
|
|
||||||
}
|
|
||||||
{ Set-ChallengeFile } | Should -Throw "Could not create the parent data dir"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "Test-ChallengeFile.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Test-ChallengeFile" {
|
|
||||||
Context "Basic input tests" {
|
|
||||||
Mock Test-Path {return $true}
|
|
||||||
It "No parameter with existing challenge file" {
|
|
||||||
{Test-ChallengeFile} | Should -Not -Throw
|
|
||||||
}
|
|
||||||
It "No parameter and existing file should return true" {
|
|
||||||
Test-ChallengeFile | Should -Be $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Execute with parameter" {
|
|
||||||
$TestChFile = "{0}\resources\cs\Challenge.bin" -f $RepoRoot
|
|
||||||
It "Provide valid path" {
|
|
||||||
Test-ChallengeFile -Path $TestChFile | Should -Be $true
|
|
||||||
}
|
|
||||||
It "Provide fake path" {
|
|
||||||
Test-ChallengeFile -Path "C:\notexisting.bin" | Should -Be $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
# . (Get-ChildItem -Path $RepoRoot -Filter "<FunctionName>.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Get-ModuleBase" {
|
|
||||||
Context "Basic syntax check" {
|
|
||||||
It "Test1: Should not throw" {
|
|
||||||
{ Get-ModuleBase } | Should -Not -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
# . (Get-ChildItem -Path $RepoRoot -Filter "<FunctionName>.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Get-RandomKey" {
|
|
||||||
Context "Basic input tests" {
|
|
||||||
It "Test1: Should throw if wrong size is given" {
|
|
||||||
{Get-RandomKey -size 43} | Should -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Basic syntax check" {
|
|
||||||
It "Test1: Should return a key with a length of 16" {
|
|
||||||
$Key = Get-RandomKey -size 16
|
|
||||||
$Key.length | Should -Be 16
|
|
||||||
}
|
|
||||||
It "Test2: Should return a key with a length of 24" {
|
|
||||||
$Key = Get-RandomKey -size 24
|
|
||||||
$Key.length | Should -Be 24
|
|
||||||
}
|
|
||||||
It "Test3: Should return a key with a length of 32" {
|
|
||||||
$Key = Get-RandomKey -size 32
|
|
||||||
$Key.length | Should -Be 32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "<FunctionName>.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Test-ModuleName" {
|
|
||||||
Context "Basic input tests" {
|
|
||||||
It "Testing standard module should not throw" {
|
|
||||||
{ Test-Module -Name 'PowerShellGet' -Type Module } | Should -Not -Throw
|
|
||||||
}
|
|
||||||
It "Existing module should return true" {
|
|
||||||
Test-Module -Name 'PowerShellGet' -Type Module | Should -Be $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Custom Type tests" {
|
|
||||||
It "Using custom type should throw" {
|
|
||||||
{ Test-Module -Name "foobarr" -Type Custom} | Should -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Working with PSSnapins" {
|
|
||||||
It "Loading first PSSnaping should not throw " {
|
|
||||||
$Snap = Get-PSSnapin -Registered | Select-Object -First 1
|
|
||||||
{ Test-Module -Name $Snap.Name -Type PSSnapin } | Should -Not -Throw
|
|
||||||
}
|
|
||||||
It "Loading first PSSnaping should return true" {
|
|
||||||
$Snap = Get-PSSnapin -Registered | Select-Object -First 1
|
|
||||||
Test-Module -Name $Snap.Name -Type PSSnapin | Should -Be $true
|
|
||||||
}
|
|
||||||
It "Not existing PSSnaping should return false" {
|
|
||||||
Test-Module -Name 'foobar2000' -Type PSSnapin | Should -Be $false
|
|
||||||
}
|
|
||||||
It "StopifFails switch should thrown an error" {
|
|
||||||
{Test-Module -Name 'foobar2000' -Type PSSnapin -StopIfFails }| Should -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Working with modules" {
|
|
||||||
It "Loading first module should not throw " {
|
|
||||||
$Mod = Get-Module -ListAvailable | Select-Object -First 1
|
|
||||||
{ Test-Module -Name $Mod.Name -Type Module } | Should -Not -Throw
|
|
||||||
}
|
|
||||||
It "Loading first module should return true" {
|
|
||||||
$Snap = Get-Module -ListAvailable | Select-Object -First 1
|
|
||||||
Test-Module -Name $Snap.Name -Type Module | Should -Be $true
|
|
||||||
}
|
|
||||||
It "Not existing module should return false" {
|
|
||||||
Test-Module -Name 'foobar2000' -Type Module | Should -Be $false
|
|
||||||
}
|
|
||||||
It "StopifFails switch should thrown an error" {
|
|
||||||
{Test-Module -Name 'foobar2000' -Type Module -StopIfFails }| Should -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
||||||
# $RepoRoot = (Get-Item -Path $here).Parent.Parent.FullName
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "Test-CredentialStore.ps1" -Recurse).FullName
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "New-CredentialStore.ps1" -Recurse).FullName
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "Get-CredentialStore.ps1" -Recurse).FullName
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "Get-CredentialStoreItem.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Test-ChallengeFile.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Get-ChallengeFile.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Set-ChallengeFile.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Get-RandomKey.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "New-CredentialStoreItem" {
|
|
||||||
Context "Private Credential Store tests" {
|
|
||||||
It "Test1: Add entry to existing private store." {
|
|
||||||
If (-not (Test-CredentialStore)) {
|
|
||||||
New-CredentialStore
|
|
||||||
}
|
|
||||||
[String]$tmp = (65..90) + (97..122) | Get-Random -Count 5 | % {[char]$_}
|
|
||||||
$tmp = $tmp.Replace(' ', '')
|
|
||||||
$tmpUser = "MyUser"
|
|
||||||
$tmpPwd = "fooobarysdfsfs" | ConvertTo-SecureString -AsPlainText -Force
|
|
||||||
$creds = New-Object -TypeName PsCredential -ArgumentList $tmpUser, $tmpPwd
|
|
||||||
New-CredentialStoreItem -RemoteHost $tmp -Credential $creds
|
|
||||||
# Had to remove the `{ <exp> } | Shoud Not Throw` because the return would be empty.
|
|
||||||
$content = Get-CredentialStoreItem -RemoteHost $tmp
|
|
||||||
$content.UserName | Should Be "MyUser"
|
|
||||||
#Cleanup Temp entry
|
|
||||||
$CS = Get-CredentialStore
|
|
||||||
$CS.PSObject.Properties.Remove($tmp)
|
|
||||||
ConvertTo-Json -InputObject $CS | Out-File -FilePath ("{0}\CredentialStore.json" -f $env:AppData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Test with new shared Credential Store" {
|
|
||||||
It "Test2: Create new RemoteHost entry" {
|
|
||||||
# prepare test environment
|
|
||||||
$tmpCS = 'C:\CredentialStore.json'
|
|
||||||
New-CredentialStore -Shared -Path $tmpCS
|
|
||||||
|
|
||||||
$UserName = "myuser"
|
|
||||||
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
|
||||||
$mycreds = New-Object -TypeName PSCredential -ArgumentList $UserName, $Password
|
|
||||||
$RemoteHost = "foobar"
|
|
||||||
{ New-CredentialStoreItem -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds -Shared } | Should Not Throw
|
|
||||||
$tmpCS = Get-Content -Path $tmpCS -Raw | ConvertFrom-Json
|
|
||||||
$res = Get-Member -InputObject $tmpCS -Name $RemoteHost -Membertype Properties
|
|
||||||
$res.Name | Should Be $RemoteHost
|
|
||||||
}
|
|
||||||
It "Adds Item with identifier to shared store" {
|
|
||||||
$tmpCS = 'C:\CredentialStore.json'
|
|
||||||
$UserName = "myuser"
|
|
||||||
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
|
||||||
$mycreds = New-Object -TypeName PSCredential -ArgumentList $UserName, $Password
|
|
||||||
$RemoteHost = "foobar2"
|
|
||||||
New-CredentialStoreItem -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds -Identifier 'Foo'
|
|
||||||
$writtenItem = Get-CredentialStoreItem -Path $tmpCS -RemoteHost $RemoteHost -Identifier 'Foo'
|
|
||||||
($writtenItem.UserName -eq $UserName) -and ($writtenItem.Password.Length -gt 0) | Should -Be $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Test optional parameter lookup" {
|
|
||||||
Mock Get-Credential {
|
|
||||||
$UserName = 'testuser'
|
|
||||||
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
|
||||||
return [PSCredential]::new($UserName, $Password)
|
|
||||||
|
|
||||||
}
|
|
||||||
It "Test missing Credential" {
|
|
||||||
$tmpCS = 'C:\CredentialStore.json'
|
|
||||||
New-CredentialStoreItem -Path $tmpCs -Shared -RemoteHost 'foobar3'
|
|
||||||
$writtenItem = Get-CredentialStoreItem -Path $tmpCS -Shared -RemoteHost 'foobar3'
|
|
||||||
$writtenItem.UserName | Should -Be "testuser"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "General Exception handling" {
|
|
||||||
Mock Test-CredentialStore {return $false}
|
|
||||||
Mock Get-Credential {
|
|
||||||
$UserName = 'myUser'
|
|
||||||
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
|
||||||
return [PSCredential]::new($UserName, $Password)
|
|
||||||
|
|
||||||
}
|
|
||||||
It "Missing CredentialStore should throw" {
|
|
||||||
{ New-CredentialStoreItem -Path 'C:\missingStore.json' -RemoteHost 'notrelevant' } | Should -Throw "Could not add anything"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Testing pipeline paramter" {
|
|
||||||
It "Add the item with credential value from pipe" {
|
|
||||||
$UserName = 'pipeUser'
|
|
||||||
$Password = ConvertTo-SecureString -String "pipePasswd" -AsPlainText -Force
|
|
||||||
{ [PSCredential]::new($UserName, $Password) | New-CredentialStoreItem -RemoteHost 'PipeHost' } | Should -Not -Throw
|
|
||||||
}
|
|
||||||
|
|
||||||
It "Testing written item" {
|
|
||||||
(Get-CredentialStoreItem -RemoteHost 'PipeHost').UserName | Should -Be 'pipeUser'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
85
tests/Item/03_New-CredentialStoreItem.Tests.ps1
Normal file
85
tests/Item/03_New-CredentialStoreItem.Tests.ps1
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
Describe "New-CredentialStoreItem" {
|
||||||
|
Context "Private Credential Store tests" {
|
||||||
|
It "Test1: Add entry to existing private store." {
|
||||||
|
# Creat a fresh CredentialStore first
|
||||||
|
New-CredentialStore -Force
|
||||||
|
|
||||||
|
[String]$tmp = (65..90) + (97..122) | Get-Random -Count 5 | % {[char]$_}
|
||||||
|
$tmp = $tmp.Replace(' ', '')
|
||||||
|
$tmpUser = "MyUser"
|
||||||
|
$tmpPwd = "fooobarysdfsfs" | ConvertTo-SecureString -AsPlainText -Force
|
||||||
|
$creds = [PSCredential]::new($tmpUser, $tmpPwd)
|
||||||
|
New-CredentialStoreItem -RemoteHost $tmp -Credential $creds
|
||||||
|
# Had to remove the `{ <exp> } | Shoud Not Throw` because the return would be empty.
|
||||||
|
$content = Get-CredentialStoreItem -RemoteHost $tmp
|
||||||
|
$content.UserName | Should -Be "MyUser"
|
||||||
|
#Cleanup Temp entry
|
||||||
|
$CS = Get-CredentialStore
|
||||||
|
$CS.PSObject.Properties.Remove($tmp)
|
||||||
|
ConvertTo-Json -InputObject $CS | Out-File -FilePath (Get-DefaultCredentialStorePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Test with new shared Credential Store" {
|
||||||
|
It "Test2: Create new RemoteHost entry" {
|
||||||
|
# prepare test environment
|
||||||
|
$tmpCS = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
|
||||||
|
New-CredentialStore -Shared -Path $tmpCS -Force
|
||||||
|
|
||||||
|
$UserName = "myuser"
|
||||||
|
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
||||||
|
$mycreds = [PSCredential]::new($UserName, $Password)
|
||||||
|
$RemoteHost = "foobar"
|
||||||
|
{ New-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds } | Should -Not -Throw
|
||||||
|
$tmpCS = Get-Content -Path $tmpCS -Raw | ConvertFrom-Json
|
||||||
|
$res = Get-Member -InputObject $tmpCS -Name $RemoteHost -Membertype Properties
|
||||||
|
$res.Name | Should -Be $RemoteHost
|
||||||
|
}
|
||||||
|
It "Adds Item with identifier to shared store" {
|
||||||
|
$tmpCS = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
|
||||||
|
New-CredentialStore -Shared -Path $tmpCS -Force
|
||||||
|
|
||||||
|
$UserName = "myuser"
|
||||||
|
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
||||||
|
$mycreds = [PSCredential]::new($UserName, $Password)
|
||||||
|
$RemoteHost = "foobar2"
|
||||||
|
New-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds -Identifier 'Foo'
|
||||||
|
$writtenItem = Get-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Identifier 'Foo'
|
||||||
|
($writtenItem.UserName -eq $UserName) -and ($writtenItem.Password.Length -gt 0) | Should -Be $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Test optional parameter lookup" {
|
||||||
|
|
||||||
|
It "Test missing Credential" {
|
||||||
|
function global:Get-Credential ([string]$Message) {
|
||||||
|
$UserName = 'testuser'
|
||||||
|
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
||||||
|
return [PSCredential]::new($UserName, $Password)
|
||||||
|
}
|
||||||
|
$tmpCS = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
|
||||||
|
New-CredentialStoreItem -Path $tmpCs -Shared -RemoteHost 'foobar3'
|
||||||
|
$writtenItem = Get-CredentialStoreItem -Path $tmpCS -Shared -RemoteHost 'foobar3'
|
||||||
|
$writtenItem.UserName | Should -Be "testuser"
|
||||||
|
|
||||||
|
Remove-Item -Path 'Function:\Get-Credential'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Context "General Exception handling" {
|
||||||
|
Mock Test-CredentialStore {return $false}
|
||||||
|
It "Missing CredentialStore should throw" {
|
||||||
|
{ New-CredentialStoreItem -Shared -Path 'C:\missingStore.json' -RemoteHost 'notrelevant' } | Should -Throw "Could not add anything"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Testing pipeline paramter" {
|
||||||
|
It "Add the item with credential value from pipe" {
|
||||||
|
$UserName = 'pipeUser'
|
||||||
|
$Password = ConvertTo-SecureString -String "pipePasswd" -AsPlainText -Force
|
||||||
|
{ [PSCredential]::new($UserName, $Password) | New-CredentialStoreItem -RemoteHost 'PipeHost' } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Testing written item" {
|
||||||
|
(Get-CredentialStoreItem -RemoteHost 'PipeHost').UserName | Should -Be 'pipeUser'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
tests/Private/01_Get-DefaultCredentialStorePath.Tests.ps1
Normal file
49
tests/Private/01_Get-DefaultCredentialStorePath.Tests.ps1
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
Describe "Get-DefaultCredentialStorePath" {
|
||||||
|
Context "Basic syntax test" {
|
||||||
|
It "Test1: Should not throw" {
|
||||||
|
{ Get-DefaultCredentialStorePath } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context "Private Type" {
|
||||||
|
It "Should return correct paths" {
|
||||||
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
#Write-Verbose -Message ('Delivered path is: {0}' -f $Path) -Verbose
|
||||||
|
if ($Env:APPVEYOR) {
|
||||||
|
$PathRef = Join-Path -Path $Env:APPDATA -ChildPath 'CredentialStore.json'
|
||||||
|
$Path | Should -Be $PathRef
|
||||||
|
}
|
||||||
|
elseif ($ENV:TRAVIS) {
|
||||||
|
if ($IsLinux) {
|
||||||
|
$PathRef = Join-Path -Path $Env:HOME -ChildPath 'CredentialStore.json'
|
||||||
|
$Path | Should -Be $PathRef
|
||||||
|
}
|
||||||
|
elseif ($IsMacOS) {
|
||||||
|
$PathRef = Join-Path -Path $Env:HOME -ChildPath 'CredentialStore.json'
|
||||||
|
$Path | Should -Be $PathRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context "Shared Type" {
|
||||||
|
It "Should return correct paths" {
|
||||||
|
$Path = Get-DefaultCredentialStorePath -Shared
|
||||||
|
#Write-Verbose -Message ('Delivered path is: {0}' -f $Path) -Verbose
|
||||||
|
if ($Env:APPVEYOR) {
|
||||||
|
$PathRef = Join-Path -Path $env:ProgramData -ChildPath 'PSCredentialStore/CredentialStore.json'
|
||||||
|
$Path | Should -Be $PathRef
|
||||||
|
}
|
||||||
|
elseif ($ENV:TRAVIS) {
|
||||||
|
if ($IsLinux) {
|
||||||
|
$PathRef = Join-Path -Path '/var/opt' -ChildPath 'PSCredentialStore/CredentialStore.json'
|
||||||
|
$Path | Should -Be $PathRef
|
||||||
|
}
|
||||||
|
elseif ($IsMacOS) {
|
||||||
|
$PathRef = Join-Path -Path '/var/opt' -ChildPath 'PSCredentialStore/CredentialStore.json'
|
||||||
|
$Path | Should -Be $PathRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
tests/Private/01_Get-ModuleBase.Tests.ps1
Normal file
7
tests/Private/01_Get-ModuleBase.Tests.ps1
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Describe "Get-ModuleBase" {
|
||||||
|
Context "Basic syntax check" {
|
||||||
|
It "Test1: Should not throw" {
|
||||||
|
{ Get-ModuleBase } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
tests/Private/01_Get-RandomAESKey.Tests.ps1
Normal file
13
tests/Private/01_Get-RandomAESKey.Tests.ps1
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Describe "Get-RandomKey" {
|
||||||
|
Context "Basic input tests" {
|
||||||
|
It "Test1: Should not throw " {
|
||||||
|
{Get-RandomAESKey} | Should -Not -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Basic syntax check" {
|
||||||
|
It "Test2: Should return a key with a length of 32 bytes" {
|
||||||
|
$Key = Get-RandomAESKey
|
||||||
|
$Key.length | Should -Be 32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
tests/Private/01_Get-TempDir.Tests.ps1
Normal file
27
tests/Private/01_Get-TempDir.Tests.ps1
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Describe "Get-TempDir" {
|
||||||
|
Context "Basic tests" {
|
||||||
|
It "Should not throw" {
|
||||||
|
{Get-TempDir} | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Should return the correct os tmp path" {
|
||||||
|
$Path = Get-TempDir
|
||||||
|
|
||||||
|
if ($ENV:TRAVIS) {
|
||||||
|
if ($IsLinux) {
|
||||||
|
$RefPath = (Resolve-Path -Path '/tmp/').Path
|
||||||
|
$Path | Should -Be $RefPath
|
||||||
|
}
|
||||||
|
if ($IsMacOS) {
|
||||||
|
$RefPath = (Resolve-Path -Path '/tmp/').Path
|
||||||
|
$Path | Should -Be $RefPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($Env:APPVEYOR) {
|
||||||
|
if (($isWindows) -or ($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop')) {
|
||||||
|
$RefPath = (Resolve-Path -Path $env:TEMP).Path
|
||||||
|
$Path | Should -Be $RefPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,6 @@
|
|||||||
#region HEADER
|
|
||||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
||||||
# $RepoRoot = (Get-Item -Path $here).Parent.Parent.FullName
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Get-ModuleBase.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Test-Module.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Resolve-Dependency" {
|
Describe "Resolve-Dependency" {
|
||||||
Context "Basic syntax check" {
|
Context "Basic syntax check" {
|
||||||
Mock Get-ModuleBase {return "{0}\resources" -f $PWD}
|
Mock Get-ModuleBase {return (Join-Path -Path $PWD -ChildPath '/resources')}
|
||||||
Mock Test-Module {return $true}
|
Mock Test-Module {return $true}
|
||||||
It "Test1: Should not throw" {
|
It "Test1: Should not throw" {
|
||||||
{ Resolve-Dependency -Name 'foobar2000' } | Should -Not -Throw
|
{ Resolve-Dependency -Name 'foobar2000' } | Should -Not -Throw
|
||||||
@ -32,7 +11,10 @@ Describe "Resolve-Dependency" {
|
|||||||
}
|
}
|
||||||
Context "Enforce Error" {
|
Context "Enforce Error" {
|
||||||
# Return incorrect module base to enforce there is no config file.
|
# Return incorrect module base to enforce there is no config file.
|
||||||
Mock Get-ModuleBase {return "C:\"}
|
Mock Get-ModuleBase {
|
||||||
|
if ($IsWindows) {return "C:\"}
|
||||||
|
elseif ($isLinux) {return "/"}
|
||||||
|
}
|
||||||
It "Missing dependency file should not cause an error" {
|
It "Missing dependency file should not cause an error" {
|
||||||
{ Resolve-Dependency -Name 'awesome'} | Should -Not -Throw
|
{ Resolve-Dependency -Name 'awesome'} | Should -Not -Throw
|
||||||
}
|
}
|
||||||
@ -42,7 +24,7 @@ Describe "Resolve-Dependency" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Context "Testing input variations" {
|
Context "Testing input variations" {
|
||||||
Mock Get-ModuleBase {return "{0}\resources" -f $PWD}
|
Mock Get-ModuleBase {return (Join-Path -Path $PWD -ChildPath '/resources')}
|
||||||
It "Should return true if all given dependencies exist" {
|
It "Should return true if all given dependencies exist" {
|
||||||
Resolve-Dependency -Name 'Existing' | Should -Be $true
|
Resolve-Dependency -Name 'Existing' | Should -Be $true
|
||||||
}
|
}
|
26
tests/Private/01_Test-Module.Tests.ps1
Normal file
26
tests/Private/01_Test-Module.Tests.ps1
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Describe "Test-ModuleName" {
|
||||||
|
Context "Basic input tests" {
|
||||||
|
It "Testing standard module should not throw" {
|
||||||
|
{ Test-Module -Name 'PowerShellGet' } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Existing module should return true" {
|
||||||
|
Test-Module -Name 'PowerShellGet' | Should -Be $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Working with modules" {
|
||||||
|
It "Loading first module should not throw " {
|
||||||
|
$Mod = Get-Module -ListAvailable | Select-Object -First 1
|
||||||
|
{ Test-Module -Name $Mod.Name } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Loading first module should return true" {
|
||||||
|
$Snap = Get-Module -ListAvailable | Select-Object -First 1
|
||||||
|
Test-Module -Name $Snap.Name | Should -Be $true
|
||||||
|
}
|
||||||
|
It "Not existing module should return false" {
|
||||||
|
Test-Module -Name 'foobar2000' | Should -Be $false
|
||||||
|
}
|
||||||
|
It "StopifFails switch should thrown an error" {
|
||||||
|
{Test-Module -Name 'foobar2000' -StopIfFails }| Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
||||||
# $RepoRoot = (Get-Item -Path $here).Parent.Parent.FullName
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "Test-CredentialStore.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Get-CredentialStore" {
|
|
||||||
Context "Basic logic tests" {
|
|
||||||
$TestCredentialStore = Resolve-Path -Path ("{0}\resources\cs\CredentialStore.json" -f $RepoRoot)
|
|
||||||
It "Test1: Read CS without params" {
|
|
||||||
If (Test-Path -Path ("{0}\CredentialStore.json" -f $env:APPDATA)) {
|
|
||||||
{Get-CredentialStore} | Should Not Throw
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning "Default private Credential Store not found. Skipping..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
It "Test2: Read Credential Store with testing data" {
|
|
||||||
|
|
||||||
{Get-CredentialStore -Path $TestCredentialStore} | Should Not Throw
|
|
||||||
}
|
|
||||||
It "Test3: Not existing path should return false" {
|
|
||||||
{ Get-CredentialStore -Path 'C:\foobar\CredentialStore.json' -Shared }| Should -Throw "Could not find the CredentialStore."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Testing invalid json data" {
|
|
||||||
Mock Test-CredentialStore {return $true}
|
|
||||||
Mock Get-Content {return '"foo":"bar",'}
|
|
||||||
It "Should throw with invalid CredentialStore" {
|
|
||||||
{ Get-Credentialstore -Path "C:\dummy.json"} | Should -Throw "Unknown CredentialStore format. Invalid JSON file."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,120 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
||||||
# $RepoRoot = (Get-Item -Path $here).Parent.Parent.FullName
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
#. (Get-ChildItem -Path $RepoRoot -Filter "Test-CredentialStore.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Test-ChallengeFile.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Set-ChallengeFile.ps1" -Recurse).FullName
|
|
||||||
. (Get-ChildItem -Path $RepoRoot -Filter "Get-RandomKey.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
|
|
||||||
# Backup existing credential stores
|
|
||||||
$VerbosePreference = "Continue"
|
|
||||||
Write-Verbose "Backup private Credential Store..."
|
|
||||||
$CSPath = ("{0}\CredentialStore.json" -f $env:APPDATA)
|
|
||||||
$BackupFile = "{0}.back" -f $CSPath
|
|
||||||
If (Test-Path -Path $CSPath) {
|
|
||||||
Move-Item -Path $CSPath -Destination $BackupFile
|
|
||||||
}
|
|
||||||
Write-Verbose "Backup shared CredentialStore..."
|
|
||||||
$CSShared = ("{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData)
|
|
||||||
$BackupSharedFile = "{0}.back" -f $CSShared
|
|
||||||
If (Test-Path -Path $CSShared) {
|
|
||||||
Move-Item -Path $CSShared -Destination $BackupSharedFile
|
|
||||||
}
|
|
||||||
Write-Verbose "Remove old CredentialStore in Temp dir"
|
|
||||||
$CSTemp = "{0}\CredentialStore.json" -f $Env:TEMP
|
|
||||||
If (Test-Path -Path $CSTemp) {
|
|
||||||
Remove-Item -Path $CSTemp
|
|
||||||
}
|
|
||||||
$VerbosePreference = "SilentlyContinue"
|
|
||||||
|
|
||||||
Describe "New-CredentialStore" {
|
|
||||||
Context "Private CS tests" {
|
|
||||||
$pCS = Join-Path -Path $env:APPDATA -ChildPath "CredentialStore.json"
|
|
||||||
It "Test1: Create new private CredentialStore" {
|
|
||||||
New-CredentialStore
|
|
||||||
$result = Test-Path -Path $pCS
|
|
||||||
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
|
|
||||||
($result -eq $True) -and ($CS.Type -eq "Private") | Should Be $True
|
|
||||||
}
|
|
||||||
It "Test2: Try to override private Store" {
|
|
||||||
{New-CredentialStore} | Should Throw
|
|
||||||
}
|
|
||||||
It "Test3: Reset existing Credential Store" {
|
|
||||||
$now = Get-Date
|
|
||||||
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
|
|
||||||
$CSCreation = [DateTime]$CS.Creation
|
|
||||||
New-CredentialStore -Force
|
|
||||||
$now -gt $csCreation | Should Be $True
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Shared CS tests" {
|
|
||||||
$pCS = Join-Path -Path $env:ProgramData -ChildPath "PSCredentialStore\CredentialStore.json"
|
|
||||||
It "Test1: Create a new Shared Credential Store" {
|
|
||||||
New-CredentialStore -Shared
|
|
||||||
Test-Path -Path ("{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData) | Should Be $True
|
|
||||||
}
|
|
||||||
It "Test2: Try to override existing shared CS" {
|
|
||||||
{New-CredentialStore -Shared} | Should Throw
|
|
||||||
}
|
|
||||||
It "Test3: Reset shared CredentialStore" {
|
|
||||||
$now = Get-Date
|
|
||||||
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
|
|
||||||
$CSCreation = [DateTime]$CS.Creation
|
|
||||||
New-CredentialStore -Force -Shared
|
|
||||||
$now -gt $csCreation | Should Be $True
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Custom Shared CS tests" {
|
|
||||||
$pCS = Join-Path -Path $env:TEMP -ChildPath "CredentialStore.json"
|
|
||||||
It "Test1: Create new custom shared" {
|
|
||||||
{New-CredentialStore -Path $pCS -Shared} | Should Not Throw
|
|
||||||
}
|
|
||||||
It "Test2: Try to override exiting one" {
|
|
||||||
{New-CredentialStore -Path $pCS -Shared} | Should Throw
|
|
||||||
}
|
|
||||||
It "Test3: Reset existing custom CredentialStore" {
|
|
||||||
{New-CredentialStore -Path $pCS -Shared -Force} | Should Not Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "Test exception handling" {
|
|
||||||
Mock Out-File {throw "foobar exception"}
|
|
||||||
It "JSON Converstion should fail and throw" {
|
|
||||||
{ New-CredentialStore -Path "C:\dummy.json"} | Should -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Cleanup test stores and restore existing ones.
|
|
||||||
$VerbosePreference = "Continue"
|
|
||||||
Write-Verbose "Restoring private CredentialStore"
|
|
||||||
If (Test-Path -Path $BackupFile) {
|
|
||||||
If (Test-Path -Path $CSPath) {
|
|
||||||
Remove-Item -Path $CSPath
|
|
||||||
Move-Item -Path $BackupFile -Destination $CSPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Verbose "Restoring shared CredentialStore"
|
|
||||||
If (Test-Path -Path $BackupSharedFile) {
|
|
||||||
If (Test-Path -Path $CSShared) {
|
|
||||||
Remove-Item -Path $CSShared
|
|
||||||
Move-Item -Path $BackupSharedFile -Destination $CSShared
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$VerbosePreference = "SilentlyContinue"
|
|
@ -1,49 +0,0 @@
|
|||||||
#region HEADER
|
|
||||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
||||||
# $RepoRoot = (Get-Item -Path $here).Parent.Parent.FullName
|
|
||||||
$RepoRoot = (Get-GitDirectory).replace('\.git', '')
|
|
||||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
|
||||||
$sut = $sut -replace "\d{2}`_", ''
|
|
||||||
$suthome = (Get-ChildItem -Path $RepoRoot -Exclude ".\tests\" -Filter $sut -Recurse).FullName
|
|
||||||
# Skip try loading the source file if it doesn't exists.
|
|
||||||
If ($suthome.Length -gt 0) {
|
|
||||||
. $suthome
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
Write-Warning ("Could not find source file {0}" -f $sut)
|
|
||||||
}
|
|
||||||
|
|
||||||
# load additional functions defined in the repository. Replace the expression <FunctionName>.
|
|
||||||
# . (Get-ChildItem -Path $RepoRoot -Filter "<Function-Name>.ps1" -Recurse).FullName
|
|
||||||
|
|
||||||
#endregion HEADER
|
|
||||||
|
|
||||||
Describe "Test-CredentialStore" {
|
|
||||||
Context "Basic logic tests" {
|
|
||||||
$TestCredentialStore = Resolve-Path -Path ("{0}\resources\cs\CredentialStore.json" -f $RepoRoot)
|
|
||||||
It "Test1: Should Not Throw" {
|
|
||||||
{ Test-CredentialStore -Path $TestCredentialStore } | Should Not Throw
|
|
||||||
}
|
|
||||||
It "Test2: Read valid CredentialStore" {
|
|
||||||
$res = Test-CredentialStore -Path $TestCredentialStore
|
|
||||||
$res | Should Be $True
|
|
||||||
}
|
|
||||||
It "Test3: Read a broken CredentialStore" {
|
|
||||||
$BrokenCS = Resolve-Path -Path ("{0}\resources\cs\Broken_CS.json" -f $RepoRoot)
|
|
||||||
$oWarningPreference = $WarningPreference
|
|
||||||
$WarningPreference = 'SilentlyContinue'
|
|
||||||
$res = Test-CredentialStore -Path $BrokenCS
|
|
||||||
$res | Should Be $False
|
|
||||||
$WarningPreference = $oWarningPreference
|
|
||||||
}
|
|
||||||
It "Test4: Not existing path should return false" {
|
|
||||||
Test-CredentialStore -Path 'C:\foobar\CredentialStore.json' | Should -Be $false
|
|
||||||
}
|
|
||||||
It "Test5: testing private CredentialStore path" {
|
|
||||||
if (Test-Path -Path ("{0}\CredentialStore.json" -f $env:APPDATA) ) {
|
|
||||||
Remove-Item -Path ("{0}\CredentialStore.json" -f $env:APPDATA)
|
|
||||||
}
|
|
||||||
Test-CredentialStore | Should -Be $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
96
tests/Store/02_New-CredentialStore.Tests.ps1
Normal file
96
tests/Store/02_New-CredentialStore.Tests.ps1
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# Backup existing credential stores
|
||||||
|
$VerbosePreference = "Continue"
|
||||||
|
Write-Verbose "Backup private Credential Store..."
|
||||||
|
$CSPath = Get-DefaultCredentialStorePath
|
||||||
|
$BackupFile = "{0}.back" -f $CSPath
|
||||||
|
If (Test-Path -Path $CSPath) {
|
||||||
|
Move-Item -Path $CSPath -Destination $BackupFile
|
||||||
|
}
|
||||||
|
Write-Verbose "Backup shared CredentialStore..."
|
||||||
|
$CSShared = Get-DefaultCredentialStorePath -Shared
|
||||||
|
$BackupSharedFile = "{0}.back" -f $CSShared
|
||||||
|
If (Test-Path -Path $CSShared) {
|
||||||
|
Move-Item -Path $CSShared -Destination $BackupSharedFile
|
||||||
|
}
|
||||||
|
Write-Verbose "Remove old CredentialStore in Temp dir"
|
||||||
|
$CSTemp = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
|
||||||
|
If (Test-Path -Path $CSTemp) {
|
||||||
|
Remove-Item -Path $CSTemp
|
||||||
|
}
|
||||||
|
$VerbosePreference = "SilentlyContinue"
|
||||||
|
|
||||||
|
Describe "New-CredentialStore" {
|
||||||
|
Context "Private CS tests" {
|
||||||
|
$pCS = Get-DefaultCredentialStorePath
|
||||||
|
It "Test1: Create new private CredentialStore" {
|
||||||
|
{ New-CredentialStore -Confirm:$false } | Should -Not -Throw
|
||||||
|
$result = Test-Path -Path $pCS
|
||||||
|
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
|
||||||
|
($result -eq $true) -and ($CS.Type -eq "Private") | Should -Be $true
|
||||||
|
}
|
||||||
|
It "Test2: Try to override private Store" {
|
||||||
|
{ New-CredentialStore -Confirm:$false } | Should -Throw
|
||||||
|
}
|
||||||
|
It "Test3: Reset existing Credential Store" {
|
||||||
|
$now = Get-Date
|
||||||
|
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
|
||||||
|
$CSCreation = [DateTime]$CS.Created
|
||||||
|
New-CredentialStore -Confirm:$false -Force
|
||||||
|
$now -gt $csCreation | Should -Be $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Shared CS tests" {
|
||||||
|
$sCS = Get-DefaultCredentialStorePath -Shared
|
||||||
|
It "Test1: Create a new Shared Credential Store" {
|
||||||
|
{ New-CredentialStore -Confirm:$false -Shared } | Should -Not -Throw
|
||||||
|
Test-Path -Path $sCS | Should -Be $true
|
||||||
|
}
|
||||||
|
It "Test2: Try to override existing shared CS" {
|
||||||
|
{New-CredentialStore -Shared -Confirm:$false} | Should -Throw
|
||||||
|
}
|
||||||
|
It "Test3: Reset shared CredentialStore" {
|
||||||
|
$now = Get-Date
|
||||||
|
$CS = Get-Content -Path $sCS -Raw | ConvertFrom-Json
|
||||||
|
$CSCreation = [DateTime]$CS.Created
|
||||||
|
New-CredentialStore -Force -Shared -Confirm:$false
|
||||||
|
$now -gt $csCreation | Should -Be $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Custom Shared CS tests" {
|
||||||
|
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
|
||||||
|
It "Test1: Create new custom shared" {
|
||||||
|
{New-CredentialStore -Path $cCS -Shared -Confirm:$false} | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Test2: Try to override exiting one" {
|
||||||
|
{New-CredentialStore -Path $cCS -Shared -Confirm:$false} | Should -Throw
|
||||||
|
}
|
||||||
|
It "Test3: Reset existing custom CredentialStore" {
|
||||||
|
{New-CredentialStore -Path $cCS -Shared -Force -Confirm:$false} | Should -Not -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Test exception handling" {
|
||||||
|
Mock Out-File {throw "foobar exception"}
|
||||||
|
It "JSON Conversion should fail and throw" {
|
||||||
|
{ New-CredentialStore -Path (Join-Path -Path (Get-TempDir) -ChildPath '/dummy.json') -Shared -Confirm:$false} | Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup test stores and restore existing ones.
|
||||||
|
$VerbosePreference = "Continue"
|
||||||
|
Write-Verbose "Restoring private CredentialStore"
|
||||||
|
If (Test-Path -Path $BackupFile) {
|
||||||
|
If (Test-Path -Path $CSPath) {
|
||||||
|
Remove-Item -Path $CSPath
|
||||||
|
Move-Item -Path $BackupFile -Destination $CSPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "Restoring shared CredentialStore"
|
||||||
|
If (Test-Path -Path $BackupSharedFile) {
|
||||||
|
If (Test-Path -Path $CSShared) {
|
||||||
|
Remove-Item -Path $CSShared
|
||||||
|
Move-Item -Path $BackupSharedFile -Destination $CSShared
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$VerbosePreference = "SilentlyContinue"
|
36
tests/Store/02_Test-CredentialStore.Tests.ps1
Normal file
36
tests/Store/02_Test-CredentialStore.Tests.ps1
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
$RepoRoot = (Get-Item -Path (Get-GitDirectory) -Force).Parent | Select-Object -ExpandProperty 'FullName'
|
||||||
|
|
||||||
|
Describe "Test-CredentialStore" {
|
||||||
|
Context "Basic logic tests" {
|
||||||
|
$TestCredentialStore = Join-Path -Path $RepoRoot -ChildPath '/resources/cs/CredentialStore.json'
|
||||||
|
It "Test1: Should Not Throw" {
|
||||||
|
{ Test-CredentialStore -Shared -Path $TestCredentialStore } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Test2: Read valid CredentialStore" {
|
||||||
|
$res = Test-CredentialStore -Shared -Path $TestCredentialStore
|
||||||
|
$res | Should -Be $true
|
||||||
|
}
|
||||||
|
It "Test3: Read a broken CredentialStore" {
|
||||||
|
$BrokenCS = Join-Path -Path $RepoRoot -ChildPath '{0}/resources/cs/Broken_CS.json'
|
||||||
|
$oWarningPreference = $WarningPreference
|
||||||
|
$WarningPreference = 'SilentlyContinue'
|
||||||
|
$res = Test-CredentialStore -Shared -Path $BrokenCS
|
||||||
|
$res | Should -Be $false
|
||||||
|
$WarningPreference = $oWarningPreference
|
||||||
|
}
|
||||||
|
It "Test4: Not existing path should return false" {
|
||||||
|
if ($isWindows -or ($PSVersionTable.PSVersion.Major -eq 5)) {
|
||||||
|
Test-CredentialStore -Shared -Path 'C:\foobar\CredentialStore.json' | Should -Be $false
|
||||||
|
}
|
||||||
|
elseif ($isWindows -or $IsMacOS) {
|
||||||
|
Test-CredentialStore -Shared -Path '/var/opt/foo.json' | Should -Be $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
It "Test5: testing private CredentialStore path" {
|
||||||
|
if (Test-Path -Path (Get-DefaultCredentialStorePath)) {
|
||||||
|
Remove-Item -Path (Get-DefaultCredentialStorePath)
|
||||||
|
}
|
||||||
|
Test-CredentialStore | Should -Be $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
tests/Store/03_Get-CredentialStore.Tests.ps1
Normal file
32
tests/Store/03_Get-CredentialStore.Tests.ps1
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
$RepoRoot = (Get-Item -Path (Get-GitDirectory) -Force).Parent | Select-Object -ExpandProperty 'FullName'
|
||||||
|
|
||||||
|
Describe "Get-CredentialStore" {
|
||||||
|
Context "Basic logic tests" {
|
||||||
|
$TestCredentialStore = Join-Path -Path $RepoRoot -ChildPath 'resources/cs/CredentialStore.json'
|
||||||
|
$TestPfxCert = Join-Path -Path $RepoRoot -ChildPath 'resources/cs/PSCredentialStore.pfx'
|
||||||
|
'TestCredentialStore: {0}' -f $TestCredentialStore
|
||||||
|
It "Test1: Read CS without params" {
|
||||||
|
if (! (Test-Path -Path (Get-DefaultCredentialStorePath)) ) {
|
||||||
|
{ New-CredentialStore -Force } | Should -Not -Throw
|
||||||
|
|
||||||
|
}
|
||||||
|
{ Get-CredentialStore } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Test2: Read Credential Store with testing data" {
|
||||||
|
{ Use-PfxCertificate -Shared -CredentialStore $TestCredentialStore -Path $TestPfxCert } | Should -Not -Throw
|
||||||
|
{ Get-CredentialStore -Shared -Path $TestCredentialStore } | Should -Not -Throw
|
||||||
|
}
|
||||||
|
It "Test3: Not existing path should return false" {
|
||||||
|
{ Get-CredentialStore -Shared -Path './CredentialStore.json' }| Should -Throw "Could not find the CredentialStore."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Testing invalid json data" {
|
||||||
|
#Mock Test-CredentialStore {return $true}
|
||||||
|
#Mock Get-Content {return '"foo":"bar",'}
|
||||||
|
$BrokenCS = Join-Path -Path $RepoRoot -ChildPath 'resources/cs/Broken_CS.json'
|
||||||
|
Write-Verbose -Message ('BrokenCS Path: {0}' -f $BrokenCS) -Verbose
|
||||||
|
It "Should throw with invalid CredentialStore" {
|
||||||
|
{ Get-CredentialStore -Path -Shared $BrokenCS } | Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
- Module name
|
- Module name
|
||||||
#>
|
#>
|
||||||
$CALLSIGN = 'PSCredentialStore'
|
$CALLSIGN = 'PSCredentialStore'
|
||||||
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Yellow
|
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
|
||||||
|
|
||||||
Function Invoke-InstallDependencies() {
|
Function Invoke-InstallDependencies() {
|
||||||
@ -16,12 +16,13 @@ Function Invoke-InstallDependencies() {
|
|||||||
|
|
||||||
Process {
|
Process {
|
||||||
Try {
|
Try {
|
||||||
|
Get-PackageProvider -ListAvailable
|
||||||
Install-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force -Verbose
|
Install-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force -Verbose
|
||||||
Import-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force
|
Import-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force
|
||||||
Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.0.8' -Force -SkipPublisherCheck -AllowClobber
|
Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.4.2' -Force -SkipPublisherCheck -AllowClobber
|
||||||
Install-Module -Name 'posh-git' -Scope CurrentUser -RequiredVersion '0.7.1' -Force -SkipPublisherCheck -AllowClobber
|
Install-Module -Name 'posh-git' -Scope CurrentUser -RequiredVersion '1.0.0-beta2' -Force -SkipPublisherCheck -AllowClobber -AllowPrerelease
|
||||||
Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber
|
# Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber
|
||||||
Import-Module -Name 'Pester', 'posh-git', 'PSCoverage'
|
Import-Module -Name 'Pester', 'posh-git' #, 'PSCoverage'
|
||||||
}
|
}
|
||||||
Catch {
|
Catch {
|
||||||
$MsgParams = @{
|
$MsgParams = @{
|
||||||
@ -39,13 +40,13 @@ Function Invoke-AppVeyorBumpVersion() {
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
Param()
|
Param()
|
||||||
|
|
||||||
Write-Host "Listing Env Vars for debugging:" -ForegroundColor Yellow
|
Write-Host "Listing Env Vars for debugging:" -ForegroundColor Black -BackgroundColor Yellow
|
||||||
# Filter Results to prevent exposing secure vars.
|
# Filter Results to prevent exposing secure vars.
|
||||||
Get-ChildItem -Path "Env:*" | Where-Object { $_.name -notmatch "(NuGetToken|CoverallsToken)"} | Sort-Object -Property Name | Format-Table
|
Get-ChildItem -Path "Env:*" | Where-Object { $_.name -notmatch "(NuGetToken|CoverallsToken)"} | Sort-Object -Property Name | Format-Table
|
||||||
|
|
||||||
Try {
|
Try {
|
||||||
$ModManifest = Get-Content -Path (".\src\{0}.psd1" -f $CALLSIGN)
|
$ModManifest = Get-Content -Path (".\src\{0}.psd1" -f $CALLSIGN)
|
||||||
$BumpedManifest = $ModManifest -replace '0.0.0.9999', $Env:APPVEYOR_BUILD_VERSION
|
$BumpedManifest = $ModManifest -replace '0.0.9999', $Env:APPVEYOR_BUILD_VERSION
|
||||||
Remove-Item -Path (".\src\{0}.psd1" -f $CALLSIGN)
|
Remove-Item -Path (".\src\{0}.psd1" -f $CALLSIGN)
|
||||||
Out-File -FilePath (".\src\{0}.psd1" -f $CALLSIGN) -InputObject $BumpedManifest -NoClobber -Encoding utf8 -Force
|
Out-File -FilePath (".\src\{0}.psd1" -f $CALLSIGN) -InputObject $BumpedManifest -NoClobber -Encoding utf8 -Force
|
||||||
}
|
}
|
||||||
@ -62,6 +63,7 @@ Function Invoke-AppVeyorBumpVersion() {
|
|||||||
|
|
||||||
Function Invoke-AppVeyorBuild() {
|
Function Invoke-AppVeyorBuild() {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
|
[OutputType([PsCustomObject])]
|
||||||
Param()
|
Param()
|
||||||
$MsgParams = @{
|
$MsgParams = @{
|
||||||
Message = 'Creating build artifacts'
|
Message = 'Creating build artifacts'
|
||||||
@ -82,7 +84,8 @@ Function Invoke-AppVeyorBuild() {
|
|||||||
Details = 'Pushing artifacts to AppVeyor store.'
|
Details = 'Pushing artifacts to AppVeyor store.'
|
||||||
}
|
}
|
||||||
Add-AppveyorMessage @MsgParams
|
Add-AppveyorMessage @MsgParams
|
||||||
Push-AppveyorArtifact (".\bin\{0}.zip" -f $CALLSIGN)
|
$ArtifactPath = Join-Path -Path '.' -ChildPath ('bin/{0}.zip' -f $CALLSIGN)
|
||||||
|
Push-AppveyorArtifact $ArtifactPath
|
||||||
}
|
}
|
||||||
|
|
||||||
Function Invoke-AppVeyorTests() {
|
Function Invoke-AppVeyorTests() {
|
||||||
@ -95,8 +98,31 @@ Function Invoke-AppVeyorTests() {
|
|||||||
Details = 'Now running all test found in .\tests\ dir.'
|
Details = 'Now running all test found in .\tests\ dir.'
|
||||||
}
|
}
|
||||||
Add-AppveyorMessage @MsgParams
|
Add-AppveyorMessage @MsgParams
|
||||||
$testresults = Invoke-Pester -Path ( Get-ChildItem -Path ".\tests\*.Tests.ps1" -Recurse | Sort-Object -Property Name ) -ExcludeTag 'Disabled' -PassThru
|
|
||||||
ForEach ($Item in $testresults.TestResult) {
|
try {
|
||||||
|
Write-Host '===== Preload internal private functions =====' -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
|
||||||
|
$Privates = Get-ChildItem -Path (Join-Path -Path $Env:APPVEYOR_BUILD_FOLDER -ChildPath '/src/Private/*') -Include "*.ps1" -Recurse
|
||||||
|
foreach ($File in $Privates) {
|
||||||
|
if (Test-Path -Path $File.FullName) {
|
||||||
|
. $File.FullName
|
||||||
|
Write-Verbose -Message ('Private function dot-sourced: {0}' -f $File.FullName) -Verbose
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Warning -Message ('Could not find file: {0} !' -f $File.FullName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error
|
||||||
|
throw 'Could not load required private functions!'
|
||||||
|
}
|
||||||
|
|
||||||
|
#$testresults = Invoke-Pester -Path ( Get-ChildItem -Path ".\tests\*.Tests.ps1" -Recurse | Sort-Object -Property Name ) -ExcludeTag 'Disabled' -PassThru
|
||||||
|
$srcFiles = Get-ChildItem -Path ".\src\*.ps1" -Recurse | Sort-Object -Property 'Name' | Select-Object -ExpandProperty 'FullName'
|
||||||
|
$testFiles = Get-ChildItem -Path ".\tests\*.Tests.ps1" -Recurse | Sort-Object -Property 'Name' | Select-Object -ExpandProperty 'FullName'
|
||||||
|
$TestResults = Invoke-Pester -Path $testFiles -CodeCoverage $srcFiles -PassThru
|
||||||
|
ForEach ($Item in $TestResults.TestResult) {
|
||||||
Switch ($Item.Result) {
|
Switch ($Item.Result) {
|
||||||
"Passed" {
|
"Passed" {
|
||||||
$TestParams = @{
|
$TestParams = @{
|
||||||
@ -134,16 +160,18 @@ Function Invoke-AppVeyorTests() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
If ($testresults.FailedCount -gt 0) {
|
If ($TestResults.FailedCount -gt 0) {
|
||||||
$MsgParams = @{
|
$MsgParams = @{
|
||||||
Message = 'Pester Tests failed.'
|
Message = 'Pester Tests failed.'
|
||||||
Category = 'Error'
|
Category = 'Error'
|
||||||
Details = "$($testresults.FailedCount) tests failed."
|
Details = "$($TestResults.FailedCount) tests failed."
|
||||||
}
|
}
|
||||||
Add-AppveyorMessage @MsgParams
|
Add-AppveyorMessage @MsgParams
|
||||||
Throw $MsgParams.Message
|
Throw $MsgParams.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $TestResults.CodeCoverage
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Function Invoke-CoverageReport() {
|
Function Invoke-CoverageReport() {
|
||||||
@ -151,13 +179,17 @@ Function Invoke-CoverageReport() {
|
|||||||
Param(
|
Param(
|
||||||
[Parameter(Mandatory = $False)]
|
[Parameter(Mandatory = $False)]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[String]$RepoToken = $Env:CoverallsToken
|
[String]$RepoToken = $Env:CoverallsToken,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $True)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[PSCustomObject]$PesterCoverageReport
|
||||||
)
|
)
|
||||||
|
|
||||||
$FileMap = New-PesterFileMap -SourceRoot '.\src' -PesterRoot '.\tests'
|
#$CoverageReport | Format-Custom -Depth 5 | Out-String | Write-Verbose
|
||||||
$CoverageReport = New-CoverageReport -PesterFileMap $FileMap -RepoToken $RepoToken
|
$CoverageReport = New-CoverageReport -CodeCoverage $PesterCoverageReport -RepoToken $RepoToken
|
||||||
Write-Host "CoverageReport JSON:" -ForegroundColor Yellow
|
Write-Host "CoverageReport JSON:" -ForegroundColor Yellow
|
||||||
$CoverageReport | Out-String | Write-Host
|
#$CoverageReport | ConvertTo-Json -Depth 5 | Out-String | Write-Verbose
|
||||||
Publish-CoverageReport -CoverageReport $CoverageReport
|
Publish-CoverageReport -CoverageReport $CoverageReport
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,27 +202,27 @@ Function Invoke-AppVeyorPSGallery() {
|
|||||||
)
|
)
|
||||||
Expand-Archive -Path (".\bin\{0}.zip" -f $CALLSIGN) -DestinationPath ("C:\Users\appveyor\Documents\WindowsPowerShell\Modules\{0}\" -f $CALLSIGN) -Verbose
|
Expand-Archive -Path (".\bin\{0}.zip" -f $CALLSIGN) -DestinationPath ("C:\Users\appveyor\Documents\WindowsPowerShell\Modules\{0}\" -f $CALLSIGN) -Verbose
|
||||||
Import-Module -Name $CALLSIGN -Verbose -Force
|
Import-Module -Name $CALLSIGN -Verbose -Force
|
||||||
Write-Host "Available Package Provider:" -ForegroundColor Yellow
|
Write-Host "Available Package Provider:" -ForegroundColor Black -BackgroundColor Yellow
|
||||||
Get-PackageProvider -ListAvailable
|
Get-PackageProvider -ListAvailable
|
||||||
Write-Host "Available Package Sources:" -ForegroundColor Yellow
|
Write-Host "Available Package Sources:" -ForegroundColor Black -BackgroundColor Yellow
|
||||||
Get-PackageSource
|
Get-PackageSource
|
||||||
Try {
|
Try {
|
||||||
Write-Host "Try to get NuGet Provider:" -ForegroundColor Yellow
|
Write-Host "Try to get NuGet Provider:" -ForegroundColor Black -BackgroundColor Yellow
|
||||||
Get-PackageProvider -Name NuGet -ErrorAction Stop
|
Get-PackageProvider -Name NuGet -ErrorAction Stop
|
||||||
}
|
}
|
||||||
Catch {
|
Catch {
|
||||||
Write-Host "Installing NuGet..." -ForegroundColor Yellow
|
Write-Host "Installing NuGet..." -ForegroundColor Black -BackgroundColor Yellow
|
||||||
Install-PackageProvider -Name NuGet -MinimumVersion '2.8.5.201' -Force -Verbose
|
Install-PackageProvider -Name NuGet -MinimumVersion '2.8.5.201' -Force -Verbose
|
||||||
Import-PackageProvider NuGet -MinimumVersion '2.8.5.201' -Force
|
Import-PackageProvider NuGet -MinimumVersion '2.8.5.201' -Force
|
||||||
}
|
}
|
||||||
Try {
|
Try {
|
||||||
If ($env:APPVEYOR_REPO_BRANCH -eq 'master') {
|
If ($env:APPVEYOR_REPO_BRANCH -eq 'master') {
|
||||||
Write-Host "try to publish module" -ForegroundColor Yellow
|
Write-Host "try to publish module" -ForegroundColor Black -BackgroundColor Yellow
|
||||||
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Yellow
|
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Black -BackgroundColor Yellow
|
||||||
Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -Force
|
Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -Force -AllowPrerelease
|
||||||
}
|
}
|
||||||
Else {
|
Else {
|
||||||
Write-Host "Skip publishing to PS Gallery because we are on $($env:APPVEYOR_REPO_BRANCH) branch." -ForegroundColor Yellow
|
Write-Host "Skip publishing to PS Gallery because we are on $($env:APPVEYOR_REPO_BRANCH) branch." -ForegroundColor Black -BackgroundColor Yellow
|
||||||
# had to remove the publish-Module statement because it would publish although the -WhatIf is given.
|
# had to remove the publish-Module statement because it would publish although the -WhatIf is given.
|
||||||
# Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -WhatIf
|
# Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -WhatIf
|
||||||
}
|
}
|
||||||
|
178
tools/CoverallsIO.psm1
Normal file
178
tools/CoverallsIO.psm1
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
function Get-GitInfo {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$BranchName
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Env:AppVeyor) {
|
||||||
|
return [PSCustomObject]@{
|
||||||
|
head = [PSCustomObject]@{
|
||||||
|
id = $Env:APPVEYOR_REPO_COMMIT
|
||||||
|
author_name = $Env:APPVEYOR_REPO_COMMIT_AUTHOR
|
||||||
|
author_email = $Env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL
|
||||||
|
comitter_name = $Env:APPVEYOR_REPO_COMMIT_AUTHOR
|
||||||
|
comitter_email = $Env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL
|
||||||
|
message = $Env:APPVEYOR_REPO_COMMIT_MESSAGE
|
||||||
|
}
|
||||||
|
branch = $Env:APPVEYOR_REPO_BRANCH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (-not $BranchName) {
|
||||||
|
$BranchName = (git rev-parse --abbrev-ref HEAD)
|
||||||
|
}
|
||||||
|
return [PSCustomObject]@{
|
||||||
|
head = [PSCustomObject]@{
|
||||||
|
id = (git log --format="%H" HEAD -1)
|
||||||
|
author_name = (git log --format="%an" HEAD -1)
|
||||||
|
author_email = (git log --format="%ae" HEAD -1)
|
||||||
|
committer_name = (git log --format="%cn" HEAD -1)
|
||||||
|
committer_email = (git log --format="%ce" HEAD -1)
|
||||||
|
message = (git log --format="%s" HEAD -1)
|
||||||
|
}
|
||||||
|
branch = $BranchName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-CoverageReport {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[PSCustomObject]$CodeCoverage,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$RepoToken,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$ModuleRoot = $(Get-Location)
|
||||||
|
)
|
||||||
|
begin {
|
||||||
|
$CoverReport = [PSCustomObject]@{
|
||||||
|
repo_token = $RepoToken
|
||||||
|
commit_sha = (git log --format="%H" HEAD -1)
|
||||||
|
git = Get-GitInfo
|
||||||
|
service_name = 'appveyor'
|
||||||
|
source_files = @()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
# Find all files with hit commands -> These file have pester tests
|
||||||
|
$UsedFiles = $CodeCoverage.AnalyzedFiles | Where-Object {
|
||||||
|
$CodeCoverage.HitCommands.File -contains $_
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($SourceFile in $UsedFiles) {
|
||||||
|
$Lines = (Get-Content -Path $SourceFile | Measure-Object).Count
|
||||||
|
Write-Verbose ("SourceFile: {0} | LinesCount: {1}" -f $SourceFile, $Lines)
|
||||||
|
$CoverageArray = @()
|
||||||
|
$Hits = 0
|
||||||
|
$Missed = 0
|
||||||
|
|
||||||
|
for ($LinePointer = 1; $LinePointer -le $Lines; $LinePointer++) {
|
||||||
|
|
||||||
|
# Get only hit commands from current src file
|
||||||
|
$curHits = $CodeCoverage.HitCommands | Where-Object {
|
||||||
|
$_.File -eq $SourceFile
|
||||||
|
}
|
||||||
|
[int]$Hits = (
|
||||||
|
$curHits | Where-Object {
|
||||||
|
$_.Line -eq $LinePointer
|
||||||
|
} | Measure-Object
|
||||||
|
).Count
|
||||||
|
|
||||||
|
# again filter only missed commands from the curent file
|
||||||
|
$curMissed = $CodeCoverage.MissedCommands | Where-Object {
|
||||||
|
$_.File -eq $SourceFile
|
||||||
|
}
|
||||||
|
[int]$Missed = (
|
||||||
|
$curMissed | Where-Object {
|
||||||
|
$_.Line -eq $LinePointer
|
||||||
|
} | Measure-Object
|
||||||
|
).Count
|
||||||
|
|
||||||
|
Write-Verbose ("SourceFile:{0} | Line: {1} | Hits: {2} | Missed: {3}" -f $SourceFile, $LinePointer, $Hits, $Missed)
|
||||||
|
if ((-not $Hits -gt 0) -and (-not $Missed -gt 0)) {
|
||||||
|
$CoverageArray += 'null'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($Hits -gt 0) {
|
||||||
|
$CoverageArray += $Hits
|
||||||
|
}
|
||||||
|
elseif ($Missed -gt 0) {
|
||||||
|
$CoverageArray += 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Get rid of the quotation
|
||||||
|
$CoverageArray = $CoverageArray -Replace '"', ''
|
||||||
|
$CoverageSourceFile = [PSCustomObject]@{
|
||||||
|
name = $SourceFile.Replace($ModuleRoot, '').Replace('\', '/')
|
||||||
|
source_digest = (Get-FileHash -Path $SourceFile -Algorithm MD5).Hash
|
||||||
|
coverage = $CoverageArray
|
||||||
|
}
|
||||||
|
If ($CoverageSourceFile.Name.StartsWith('/')) {
|
||||||
|
$CoverageSourceFile.Name = $CoverageSourceFile.Name.Remove(0, 1)
|
||||||
|
}
|
||||||
|
$CoverReport.source_files += $CoverageSourceFile
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find all untested files to create a null coverage file
|
||||||
|
$UnUsedFiles = $CodeCoverage.AnalyzedFiles | Where-Object {
|
||||||
|
$CodeCoverage.HitCommands.File -notcontains $_
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($UnUsedFile in $UnUsedFiles) {
|
||||||
|
$Lines = (Get-Content -Path $UnUsedFile | Measure-Object).Count
|
||||||
|
$CoverageArray = @()
|
||||||
|
for ($LinePointer = 1; $LinePointer -le $Lines; $LinePointer++) {
|
||||||
|
$CoverageArray += '0'
|
||||||
|
}
|
||||||
|
$CoverageSourceFile = [PSCustomObject]@{
|
||||||
|
name = $UnUsedFile.Replace($ModuleRoot, '').Replace('\', '/')
|
||||||
|
source_digest = (Get-FileHash -Path $UnUsedFile -Algorithm MD5).Hash
|
||||||
|
coverage = $CoverageArray
|
||||||
|
}
|
||||||
|
if ($CoverageSourceFile.Name.StartsWith('/')) {
|
||||||
|
$CoverageSourceFile.Name = $CoverageSourceFile.Name.Remove(0, 1)
|
||||||
|
}
|
||||||
|
$CoverReport.source_files += $CoverageSourceFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
Write-Output $CoverReport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Publish-CoverageReport () {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $True)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[PSCustomObject]$CoverageReport
|
||||||
|
)
|
||||||
|
begin {
|
||||||
|
Add-Type -AssemblyName System.Net.Http
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
$CoverageJSON = ConvertTo-Json $CoverageReport -Depth 5
|
||||||
|
# Try to fix null elements in coverage array.
|
||||||
|
$CoverageJSON = $CoverageJSON.Replace('"null"', 'null')
|
||||||
|
$stringContent = New-Object System.Net.Http.StringContent ($CoverageJSON)
|
||||||
|
$httpClient = New-Object System.Net.Http.Httpclient
|
||||||
|
$formdata = New-Object System.Net.Http.MultipartFormDataContent
|
||||||
|
$formData.Add($stringContent, "json_file", "coverage.json")
|
||||||
|
$result = $httpClient.PostAsync('https://coveralls.io/api/v1/jobs', $formData).Result
|
||||||
|
$content = $result.Content.ReadAsStringAsync()
|
||||||
|
}
|
||||||
|
|
||||||
|
end {
|
||||||
|
Write-Output $Content
|
||||||
|
}
|
||||||
|
}
|
66
tools/Travis.psm1
Normal file
66
tools/Travis.psm1
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
$Global:ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
|
$CALLSIGN = 'PSCredentialStore'
|
||||||
|
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
|
||||||
|
function Invoke-InstallDependencies {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param()
|
||||||
|
|
||||||
|
process {
|
||||||
|
try {
|
||||||
|
Write-Host '===== Environment Vars: =====' -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
Get-ChildItem -Path Env:
|
||||||
|
|
||||||
|
Write-Host -Message '===== Existing Variables: =====' -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
Get-Variable -Name * | Format-Table -AutoSize
|
||||||
|
|
||||||
|
Get-PackageProvider -ListAvailable
|
||||||
|
Import-PackageProvider -Name 'NuGet' -MinimumVersion '2.8.5.208' -Verbose -Force
|
||||||
|
|
||||||
|
Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.4.2' -Force -SkipPublisherCheck -AllowClobber -Verbose
|
||||||
|
Install-Module -Name 'posh-git' -Scope CurrentUser -RequiredVersion '1.0.0-beta2' -Force -SkipPublisherCheck -AllowClobber -AllowPrerelease -Verbose
|
||||||
|
|
||||||
|
Import-Module -Name 'Pester', 'posh-git' -Verbose
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error
|
||||||
|
throw 'Could not install the required dependencies!'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-UnitTests {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param()
|
||||||
|
|
||||||
|
process {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host '===== Preload internal private functions =====' -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
|
||||||
|
$Privates = Get-ChildItem -Path (Join-Path -Path $Env:TRAVIS_BUILD_DIR -ChildPath '/src/Private/*') -Include "*.ps1" -Recurse -ErrorAction Stop
|
||||||
|
foreach ($File in $Privates) {
|
||||||
|
if (Test-Path -Path $File.FullName) {
|
||||||
|
. $File.FullName
|
||||||
|
Write-Verbose -Message ('Private function dot-sourced: {0}' -f $File.FullName) -Verbose
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Warning -Message ('Could not find file: {0} !' -f $File.FullName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error
|
||||||
|
throw 'Could not load required private functions!'
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host '===== Running Pester =====' -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
$TestFiles = Get-ChildItem -Path (Join-Path -Path '.' -ChildPath './tests/*.Tests.ps1') -Recurse| Sort-Object -Property Name
|
||||||
|
$TestResults = Invoke-Pester -Script $TestFiles -ExcludeTag 'Disabled' -PassThru
|
||||||
|
|
||||||
|
if ($TestResults.FailedCount -gt 0) {
|
||||||
|
throw ('{0} tests failed!' -f $TestResults.FailedCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
tools/travis.sh
Normal file
14
tools/travis.sh
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
set -x
|
||||||
|
ulimit -n 4096
|
||||||
|
|
||||||
|
echo "TRAVIS_EVENT_TYPE value $TRAVIS_EVENT_TYPE"
|
||||||
|
|
||||||
|
if [ $TRAVIS_EVENT_TYPE = cron ] || [ $TRAVIS_EVENT_TYPE = api ]; then
|
||||||
|
sudo pwsh -NoProfile -NonInteractive -c "Import-Module ./tools/Travis.psm1;
|
||||||
|
Invoke-InstallDependencies;
|
||||||
|
Invoke-UnitTests;"
|
||||||
|
else
|
||||||
|
sudo pwsh -NoProfile -NonInteractive -c "Import-Module ./tools/Travis.psm1;
|
||||||
|
Invoke-InstallDependencies;
|
||||||
|
Invoke-UnitTests;"
|
||||||
|
fi
|
Loading…
Reference in New Issue
Block a user