PowerShell 6 Core Support #35
|
@ -0,0 +1,2 @@
|
|||
src/Vendor/libressl255/* filter=lfs diff=lfs merge=lfs -text
|
||||
*.pfx filter=lfs diff=lfs merge=lfs -text
|
|
@ -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
|
|
@ -42,7 +42,7 @@
|
|||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"name": "PowerShell Interactive Session",
|
||||
"cwd": "${workspaceRoot}"
|
||||
"cwd": ""
|
||||
}
|
||||
]
|
||||
}
|
|
@ -26,7 +26,8 @@
|
|||
"powershell.codeFormatting.whitespaceAroundOperator": true,
|
||||
"powershell.codeFormatting.whitespaceAfterSeparator": true,
|
||||
"powershell.codeFormatting.ignoreOneLineBlock": true,
|
||||
"powershell.codeFormatting.alignPropertyValuePairs": false,
|
||||
"powershell.codeFormatting.alignPropertyValuePairs": true,
|
||||
"powershell.codeFormatting.preset": "Custom",
|
||||
// cspell spellchecker options
|
||||
"cSpell.enabledLanguageIds": [
|
||||
"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
|
||||
`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
|
||||
============
|
||||
|
||||
PowerShellGallery.com (Recommended Way)
|
||||
---------------------------------------
|
||||
|
||||
* Make sure you use PowerShell 4.0 or higher with `$PSVersionTable`.
|
||||
* Use the builtin PackageManagement and install with: `Install-Module PSCredentialStore`
|
||||
* Make sure you use PowerShell 5.1 or higher with `$PSVersionTable`.
|
||||
* 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`
|
||||
|
||||
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 "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:
|
||||
# only:
|
||||
|
@ -20,6 +20,7 @@ image: Visual Studio 2017
|
|||
|
||||
install:
|
||||
- ps: Import-Module .\tools\AppVeyor.psm1
|
||||
- ps: Import-Module .\tools\CoverallsIO.psm1
|
||||
- ps: Invoke-InstallDependencies
|
||||
|
||||
environment:
|
||||
|
@ -37,10 +38,10 @@ build_script:
|
|||
- ps: Invoke-AppVeyorBuild
|
||||
|
||||
test_script:
|
||||
- ps: Invoke-AppVeyorTests
|
||||
- ps: |
|
||||
$CodeCoverage = Invoke-AppVeyorTests
|
||||
if ($null -ne $Env:CoverallsToken) {
|
||||
Invoke-CoverageReport
|
||||
Invoke-CoverageReport -PesterCoverageReport $CodeCoverage
|
||||
}
|
||||
else {
|
||||
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
|
||||
artifact: PSCredentialStore.zip # upload all NuGet packages to release assets
|
||||
draft: false
|
||||
prerelease: false
|
||||
prerelease: true
|
||||
on:
|
||||
branch: master # build release on master branch changes
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
|
@ -63,7 +63,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -19,7 +19,7 @@ Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonPara
|
|||
|
||||
### Shared
|
||||
```
|
||||
Get-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
||||
Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Shared] [-Path <String>]
|
||||
[<CommonParameters>]
|
||||
```
|
||||
|
||||
|
@ -93,7 +93,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -19,7 +19,7 @@ Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonPara
|
|||
|
||||
### Shared
|
||||
```
|
||||
Get-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
||||
Get-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Shared] [-Path <String>]
|
||||
[<CommonParameters>]
|
||||
```
|
||||
|
||||
|
@ -93,7 +93,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -20,8 +20,8 @@ New-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential
|
|||
|
||||
### Shared
|
||||
```
|
||||
New-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>]
|
||||
[-Credential <PSCredential>] [-Shared] [<CommonParameters>]
|
||||
New-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential <PSCredential>] [-Shared]
|
||||
[-Path <String>] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
|
@ -51,7 +51,7 @@ Aliases:
|
|||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept pipeline input: True (ByValue)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
|
@ -111,7 +111,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -19,7 +19,7 @@ Remove-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonP
|
|||
|
||||
### Shared
|
||||
```
|
||||
Remove-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
||||
Remove-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Shared] [-Path <String>]
|
||||
[<CommonParameters>]
|
||||
```
|
||||
|
||||
|
@ -94,7 +94,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -14,13 +14,14 @@ Changes the credentials for the given remote host in the store.
|
|||
|
||||
### Private (Default)
|
||||
```
|
||||
Set-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [<CommonParameters>]
|
||||
Set-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential <PSCredential>]
|
||||
[<CommonParameters>]
|
||||
```
|
||||
|
||||
### Shared
|
||||
```
|
||||
Set-CredentialStoreItem [-Path <String>] -RemoteHost <String> [-Identifier <String>] [-Shared]
|
||||
[<CommonParameters>]
|
||||
Set-CredentialStoreItem -RemoteHost <String> [-Identifier <String>] [-Credential <PSCredential>] [-Shared]
|
||||
[-Path <String>] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
|
@ -37,6 +38,21 @@ Set-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.lo
|
|||
|
||||
## 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
|
||||
Defaults to "".
|
||||
Specify a string, which separates two CredentialStoreItems for the
|
||||
|
@ -94,7 +110,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -63,7 +63,7 @@ Type: SwitchParameter
|
|||
Parameter Sets: Shared
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: False
|
||||
Accept pipeline input: False
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"Version": "1.2.0",
|
||||
"Version": "2.0.0",
|
||||
"Creation": "2016-06-14 08:41:10"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
!マ<><EFBE8F>゙澄H4サ<34><EFBDBB>"=w肛Sヨ2
|
Binary file not shown.
Binary file not shown.
|
@ -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 {
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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")]
|
||||
[PSCredential]$Credentials,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetNAme = "Shared")]
|
||||
[switch]$Shared,
|
||||
|
||||
[Parameter(Mandatory = $False, ParameterSetName = "Shared")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
||||
[string]$Path,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetNAme = "Shared")]
|
||||
[switch]$Shared
|
||||
[Parameter(Mandatory = $False, ParameterSetName = "Private")]
|
||||
[Parameter(Mandatory = $False, ParameterSetName = "Shared")]
|
||||
[switch]$PassThru
|
||||
)
|
||||
|
||||
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
|
||||
if (-not (Resolve-Dependency -Name $Type)) {
|
||||
Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f $Type) -ErrorAction 'Stop'
|
||||
|
@ -118,10 +133,6 @@ function Connect-To {
|
|||
}
|
||||
|
||||
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)) {
|
||||
# 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.
|
||||
|
@ -131,10 +142,10 @@ function Connect-To {
|
|||
try {
|
||||
if ($Identifier -ne "") {
|
||||
$RemoteHostIdentifier = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||
$creds = Get-CredentialStoreItem -RemoteHost $RemoteHostIdentifier -Path $Path
|
||||
$creds = Get-CredentialStoreItem -Shared -RemoteHost $RemoteHostIdentifier -Path $Path
|
||||
}
|
||||
else {
|
||||
$creds = Get-CredentialStoreItem -RemoteHost $RemoteHost -Path $Path
|
||||
$creds = Get-CredentialStoreItem -Shared -RemoteHost $RemoteHost -Path $Path
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,9 +239,15 @@ function Connect-To {
|
|||
}
|
||||
"CisServer" {
|
||||
try {
|
||||
if ($PassThru.IsPresent) {
|
||||
Connect-CisServer -Server $RemoteHost -Credential $creds -ErrorAction Stop
|
||||
}
|
||||
else {
|
||||
Connect-CisServer -Server $RemoteHost -Credential $creds -ErrorAction Stop | Out-Null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
catch {
|
||||
# Write a error message to the log.
|
||||
$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")]
|
||||
[OutputType([System.Management.Automation.PSCredential])]
|
||||
[OutputType([PSCredential])]
|
||||
param(
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
|
@ -56,15 +53,28 @@ function Get-CredentialStoreItem {
|
|||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Identifier,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[switch]$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") {
|
||||
$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 "") {
|
||||
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||
}
|
||||
|
@ -72,26 +82,24 @@ function Get-CredentialStoreItem {
|
|||
$CredentialName = $RemoteHost
|
||||
}
|
||||
|
||||
if (Test-CredentialStore -Path $Path) {
|
||||
$CS = Get-CredentialStore -Path $Path
|
||||
if (Test-CredentialStore -Shared -Path $Path) {
|
||||
$CS = Get-CredentialStore -Shared -Path $Path
|
||||
$CSMembers = Get-Member -InputObject $CS
|
||||
# Let`s first check if the given remote host exists as object property
|
||||
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -eq $CredentialName)) {
|
||||
if ($CS.Type -eq "Private") {
|
||||
$CSItem = [ordered]@{
|
||||
User = $CS.$CredentialName.User
|
||||
Password = ConvertTo-SecureString -String $CS.$CredentialName.Password
|
||||
# Let's first check if the given remote host exists as object property
|
||||
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) {
|
||||
$Cert = Get-PfxCertificate -FilePath $CS.PfXCertificate -ErrorAction Stop
|
||||
$DecryptedKey = $Cert.PrivateKey.Decrypt(
|
||||
[Convert]::FromBase64String($CS.$CredentialName.EncryptedKey),
|
||||
[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 {
|
||||
$MsgParams = @{
|
||||
ErrorAction = "Stop"
|
||||
|
@ -107,4 +115,10 @@ function Get-CredentialStoreItem {
|
|||
}
|
||||
Write-Error @MsgParams
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,9 +42,6 @@ function New-CredentialStoreItem {
|
|||
|
||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||
param(
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
|
@ -59,26 +56,51 @@ function New-CredentialStoreItem {
|
|||
[ValidateNotNullOrEmpty()]
|
||||
[PSCredential]$Credential,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[switch]$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") {
|
||||
$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.
|
||||
if (-not(Test-CredentialStore -Path $Path)) {
|
||||
if (-not(Test-CredentialStore -Shared -Path $Path)) {
|
||||
$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"
|
||||
}
|
||||
Write-Error @MessageParams
|
||||
}
|
||||
|
||||
# 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"
|
||||
|
||||
|
@ -94,13 +116,20 @@ function New-CredentialStoreItem {
|
|||
}
|
||||
|
||||
if ($Credential.UserName) {
|
||||
if ($CSContent.Type -eq "Shared") {
|
||||
$Key = Get-ChallengeFile
|
||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password -Key $Key
|
||||
try {
|
||||
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
||||
}
|
||||
else {
|
||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password
|
||||
catch {
|
||||
$_.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) {
|
||||
$MessageParams = @{
|
||||
Message = "The given host already exists. Nothing to do here."
|
||||
|
@ -108,16 +137,20 @@ function New-CredentialStoreItem {
|
|||
Write-Warning @MessageParams
|
||||
}
|
||||
else {
|
||||
$RSAKey = Get-RandomAESKey
|
||||
|
||||
$CredentialHash = [ordered]@{
|
||||
User = $Credential.UserName
|
||||
Password = $encypted
|
||||
Creation = $CurrentDate
|
||||
Password = ConvertFrom-SecureString -SecureString $Credential.Password -Key $RSAKey
|
||||
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
|
||||
try {
|
||||
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
|
||||
}
|
||||
catch [System.Exception] {
|
||||
catch {
|
||||
$MessageParams = @{
|
||||
Message = "Couldn't add item into credential store!"
|
||||
ErrorAction = "Stop"
|
||||
|
@ -133,4 +166,10 @@ function New-CredentialStoreItem {
|
|||
}
|
||||
Write-Error @MessageParams
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,8 +27,16 @@ function Remove-CredentialStoreItem {
|
|||
[None]
|
||||
|
||||
.EXAMPLE
|
||||
Remove-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local"
|
||||
Remove-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" -Identifier svc
|
||||
Remove-CredentialStoreItem -RemoteHost "esx01.myside.local"
|
||||
|
||||
.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
|
||||
```
|
||||
|
@ -43,9 +51,6 @@ function Remove-CredentialStoreItem {
|
|||
|
||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||
param(
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[string]$RemoteHost,
|
||||
|
@ -54,26 +59,39 @@ function Remove-CredentialStoreItem {
|
|||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[string]$Identifier,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[switch]$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") {
|
||||
$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.
|
||||
if (-not(Test-CredentialStore -Path $Path)) {
|
||||
if (-not(Test-CredentialStore -Shared -Path $Path)) {
|
||||
$MessageParams = @{
|
||||
Message = "Could not add anything into the given CredentailStore."
|
||||
Message = "Could not add anything into the given CredentialStore."
|
||||
ErrorAction = "Stop"
|
||||
}
|
||||
Write-Error @MessageParams
|
||||
}
|
||||
|
||||
# Read the file content based on the given ParameterSetName
|
||||
$CSContent = Get-CredentialStore -Path $Path
|
||||
$CSContent = Get-CredentialStore -Shared -Path $Path
|
||||
|
||||
if ($Identifier -ne "") {
|
||||
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||
|
@ -82,15 +100,21 @@ function Remove-CredentialStoreItem {
|
|||
$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.
|
||||
$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 {
|
||||
$MessageParams = @{
|
||||
Message = "The given CredentailStoreItem does not exist."
|
||||
Message = "The given CredentialStoreItem does not exist."
|
||||
}
|
||||
Write-Warning @MessageParams
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,9 +42,6 @@ function Set-CredentialStoreItem {
|
|||
|
||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||
param(
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Private")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[string]$RemoteHost,
|
||||
|
@ -57,17 +54,30 @@ function Set-CredentialStoreItem {
|
|||
[ValidateNotNullOrEmpty()]
|
||||
[PSCredential]$Credential,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[switch]$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") {
|
||||
$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.
|
||||
if (-not(Test-CredentialStore -Path $Path)) {
|
||||
if (-not(Test-CredentialStore -Shared -Path $Path)) {
|
||||
$MessageParams = @{
|
||||
Message = "Could not add anything into the given CredentailStore."
|
||||
ErrorAction = "Stop"
|
||||
|
@ -76,7 +86,7 @@ function Set-CredentialStoreItem {
|
|||
}
|
||||
|
||||
# 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"
|
||||
|
||||
|
@ -92,24 +102,31 @@ function Set-CredentialStoreItem {
|
|||
}
|
||||
|
||||
if ($Credential.UserName) {
|
||||
if ($CSContent.Type -eq "Shared") {
|
||||
$Key = Get-ChallengeFile
|
||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password -Key $Key
|
||||
try {
|
||||
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
||||
}
|
||||
else {
|
||||
$encypted = ConvertFrom-SecureString -SecureString $Credential.Password
|
||||
catch {
|
||||
$_.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) {
|
||||
$RSAKey = Get-RandomAESKey
|
||||
$CSContent.$CredentialName.User = $Credential.UserName
|
||||
$CSContent.$CredentialName.Password = $encypted
|
||||
$CSContent.$CredentialName.Creation = $CurrentDate
|
||||
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
|
||||
}
|
||||
else {
|
||||
$MessageParams = @{
|
||||
Message = "The given CredentailStoreItem does not exist."
|
||||
}
|
||||
Write-Warning @MessageParams
|
||||
$CSContent.$CredentialName.Password = ConvertFrom-SecureString -SecureString $Credential.Password -Key $RSAKey
|
||||
$CSContent.$CredentialName.LastChange = $CurrentDate
|
||||
$CSContent.$CredentialName.EncryptedKey = [Convert]::ToBase64String(
|
||||
$Cert.PublicKey.Key.Encrypt(
|
||||
$RSAKey,
|
||||
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
|
||||
)
|
||||
)
|
||||
ConvertTo-Json -InputObject $CSContent -Depth 5 | Out-File -FilePath $Path -Encoding utf8
|
||||
}
|
||||
}
|
||||
Else {
|
||||
|
@ -119,4 +136,9 @@ function Set-CredentialStoreItem {
|
|||
}
|
||||
Write-Error @MessageParams
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
function Test-CredentialStoreItem() {
|
||||
function Test-CredentialStoreItem {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks if the given RemoteHost identifier combination exists in the credential store.
|
||||
|
@ -64,10 +64,20 @@ function Test-CredentialStoreItem() {
|
|||
[switch]$Shared
|
||||
)
|
||||
|
||||
begin {
|
||||
# Set the CredentialStore for private, shared or custom mode.
|
||||
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
|
||||
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 "") {
|
||||
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
|
||||
}
|
||||
|
@ -75,10 +85,10 @@ function Test-CredentialStoreItem() {
|
|||
$CredentialName = $RemoteHost
|
||||
}
|
||||
|
||||
if (Test-CredentialStore -Path $Path) {
|
||||
$CS = Get-CredentialStore -Path $Path
|
||||
if (Test-CredentialStore -Shared -Path $Path) {
|
||||
$CS = Get-CredentialStore -Shared -Path $Path
|
||||
$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
|
||||
}
|
||||
else {
|
||||
|
@ -92,4 +102,10 @@ function Test-CredentialStoreItem() {
|
|||
}
|
||||
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.
|
||||
RootModule = 'PSCredentialStore'
|
||||
RootModule = 'PSCredentialStore.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
# Do not touch the version number. It gets replaced in the build process.
|
||||
ModuleVersion = '0.0.0.9999'
|
||||
ModuleVersion = '0.0.9999'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
CompatiblePSEditions = 'Desktop', 'Core'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '6800e192-9df8-4e30-b253-eb2c799bbe84'
|
||||
|
@ -28,18 +19,18 @@
|
|||
CompanyName = ''
|
||||
|
||||
# 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 = 'A simple credential manager to store and reuse multiple credential objects.'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '4.0'
|
||||
# Minimum version of the PowerShell engine required by this module
|
||||
PowerShellVersion = '5.1'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# Name of the PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# Minimum version of the PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# 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.
|
||||
FunctionsToExport = @(
|
||||
# Connection Group
|
||||
# Certificate
|
||||
'New-CRTAttribute',
|
||||
'New-PfxCertificate',
|
||||
'Use-PfxCertificate',
|
||||
# Connection
|
||||
'Connect-To',
|
||||
'Disconnect-From',
|
||||
'Test-CSConnection',
|
||||
# Item Group
|
||||
# Item
|
||||
'Get-CredentialStoreItem',
|
||||
'Set-CredentialStoreItem',
|
||||
'New-CredentialStoreItem',
|
||||
'Remove-CredentialStoreItem',
|
||||
'Set-CredentialStoreItem',
|
||||
'Test-CredentialStoreItem',
|
||||
# Store Group
|
||||
# Store
|
||||
'Get-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.
|
||||
|
@ -112,9 +107,7 @@
|
|||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
Tags = @('CredentialStore',
|
||||
'CredentialManager'
|
||||
)
|
||||
Tags = 'CredentialStore', 'CredentialManager'
|
||||
|
||||
# A URL to the license for this module.
|
||||
LicenseUri = 'https://github.com/OCram85/PSCredentialStore/blob/master/LICENSE'
|
||||
|
@ -123,11 +116,20 @@
|
|||
ProjectUri = 'https://github.com/OCram85/PSCredentialStore'
|
||||
|
||||
# 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 = '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 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)"
|
||||
}
|
||||
ForEach ($Item in $Items) {
|
||||
foreach ($Item in $Items) {
|
||||
# Write-Verbose ("dot sourcing file {0}" -f $Item)
|
||||
. $Item
|
||||
}
|
||||
|
||||
# Exports are now controlled by module manifest
|
||||
# Export-ModuleMember -Function *
|
||||
#endregion dot-sourcing
|
||||
|
|
|
@ -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 {}
|
||||
}
|
|
@ -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 {}
|
||||
}
|
|
@ -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
|
||||
```
|
||||
File Name : Get-RandomKey.ps1
|
||||
File Name : Test-Module.ps1
|
||||
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||
Requires :
|
||||
```
|
||||
|
@ -50,10 +50,6 @@ function Test-Module {
|
|||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Name,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet('Module', 'PSSnapin', 'Custom')]
|
||||
[string]$Type = 'Module',
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$MessagePattern = @"
|
||||
|
@ -62,15 +58,12 @@ Could not find the required {0} called {1}. Please install the required {0} to r
|
|||
[Parameter(Mandatory = $false)]
|
||||
[switch]$StopIfFails
|
||||
)
|
||||
begin {
|
||||
|
||||
}
|
||||
begin {}
|
||||
|
||||
process {
|
||||
$Message = $MessagePattern -f $Type, $Name
|
||||
Write-Debug $Message
|
||||
switch ($Type) {
|
||||
'Module' {
|
||||
|
||||
if (Get-Module -Name $Name -ListAvailable) {
|
||||
return $true
|
||||
}
|
||||
|
@ -82,25 +75,5 @@ Could not find the required {0} called {1}. Please install the required {0} to r
|
|||
}
|
||||
}
|
||||
|
||||
'PSSnapin' {
|
||||
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 {
|
||||
|
||||
}
|
||||
end {}
|
||||
}
|
|
@ -35,22 +35,36 @@ function Get-CredentialStore {
|
|||
#>
|
||||
|
||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||
[OutputType("PSCredentialStore.Store")]
|
||||
param(
|
||||
[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
|
||||
)
|
||||
|
||||
if ($PSCmdlet.ParameterSetName -eq 'Private') {
|
||||
$Path = "{0}\CredentialStore.json" -f $env:APPDATA
|
||||
begin {}
|
||||
|
||||
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 {
|
||||
$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] {
|
||||
$MessageParams = @{
|
||||
|
@ -67,4 +81,8 @@ function Get-CredentialStore {
|
|||
}
|
||||
Write-Error @MessageParams
|
||||
}
|
||||
}
|
||||
|
||||
end {}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ function New-CredentialStore {
|
|||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
[None]
|
||||
['PSCredentialStore.Store'] Returns the recently created CredentialStore object if the -PassThru parameter
|
||||
was given.
|
||||
|
||||
.EXAMPLE
|
||||
New-CredentialStore
|
||||
|
@ -50,63 +51,163 @@ function New-CredentialStore {
|
|||
https://github.com/OCram85/PSCredentialStore
|
||||
#>
|
||||
|
||||
[CmdletBinding(DefaultParameterSetName = "Private")]
|
||||
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = "Private")]
|
||||
[OutputType("PSCredentialStore.Store")]
|
||||
param(
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Shared")]
|
||||
[switch]$Shared,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
|
||||
[string]$Path,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||
[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.
|
||||
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
# 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)
|
||||
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."
|
||||
if ((Test-CredentialStore -Path $Path) -and ($Force -ne $true)) {
|
||||
$MessageParam = @{
|
||||
Message = "The given file already exists. Use the 'Force' switch to override the existing store."
|
||||
ErrorAction = "Stop"
|
||||
if ((Test-Path -Path $Path) -and ($Force -ne $true)) {
|
||||
$ErrorParams = @{
|
||||
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.
|
||||
$ObjProperties = [ordered]@{
|
||||
PSTypeName = 'PSCredentialStore.Store'
|
||||
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") {
|
||||
$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 {
|
||||
$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 {
|
||||
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] {
|
||||
$_.Exception | Format-List -Force | Out-String | Write-Error -ErrorAction Stop
|
||||
catch {
|
||||
$_.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")]
|
||||
param(
|
||||
[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
|
||||
)
|
||||
|
||||
|
||||
if ($PSCmdlet.ParameterSetName -eq "Private") {
|
||||
$Path = "{0}\CredentialStore.json" -f $Env:APPDATA
|
||||
begin {
|
||||
# Set latest Credential Store version
|
||||
#Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant
|
||||
}
|
||||
|
||||
# Set latest Credential Store version
|
||||
Set-Variable -Name "CSVersion" -Value "1.2.0" -Option Constant
|
||||
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
|
||||
}
|
||||
}
|
||||
Write-Verbose -Message ("Path is: {0}" -f $Path)
|
||||
|
||||
if (Test-Path $Path) {
|
||||
Write-Verbose "CredentialStore in given path found."
|
||||
|
||||
# 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
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Could not read or convert the given CredentialStore."
|
||||
Return $False
|
||||
}
|
||||
Return $True
|
||||
|
||||
}
|
||||
Else {
|
||||
else {
|
||||
Write-Verbose "The given CredentialStore does not exist!"
|
||||
Return $False
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
end {}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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" {
|
||||
$ManifestFilePath = "{0}\src\PSCredentialstore.psd1" -f $RepoRoot
|
||||
Context "Manifest file related" {
|
||||
It "Test the parsed file itsef" {
|
||||
{ Test-ModuleManifest -Path $ManifestFilePath } | Should -Not -Throw
|
||||
It "Test the parsed file itself" {
|
||||
{ Test-ModuleManifest -Path $ManifestFilePath -Verbose } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
Context "Module consistency tests" {
|
||||
IT "Importing should work" {
|
||||
{ Import-Module -Name $ManifestFilePath -Global -Force }| Should -Not -Throw
|
||||
It "Importing should work" {
|
||||
{ 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'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
Describe "Get-ModuleBase" {
|
||||
Context "Basic syntax check" {
|
||||
It "Test1: Should not throw" {
|
||||
{ Get-ModuleBase } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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" {
|
||||
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}
|
||||
It "Test1: Should not throw" {
|
||||
{ Resolve-Dependency -Name 'foobar2000' } | Should -Not -Throw
|
||||
|
@ -32,7 +11,10 @@ Describe "Resolve-Dependency" {
|
|||
}
|
||||
Context "Enforce Error" {
|
||||
# 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" {
|
||||
{ Resolve-Dependency -Name 'awesome'} | Should -Not -Throw
|
||||
}
|
||||
|
@ -42,7 +24,7 @@ Describe "Resolve-Dependency" {
|
|||
}
|
||||
}
|
||||
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" {
|
||||
Resolve-Dependency -Name 'Existing' | Should -Be $true
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
#>
|
||||
$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() {
|
||||
|
@ -16,12 +16,13 @@ Function Invoke-InstallDependencies() {
|
|||
|
||||
Process {
|
||||
Try {
|
||||
Get-PackageProvider -ListAvailable
|
||||
Install-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force -Verbose
|
||||
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 'posh-git' -Scope CurrentUser -RequiredVersion '0.7.1' -Force -SkipPublisherCheck -AllowClobber
|
||||
Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber
|
||||
Import-Module -Name 'Pester', 'posh-git', 'PSCoverage'
|
||||
Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.4.2' -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
|
||||
Import-Module -Name 'Pester', 'posh-git' #, 'PSCoverage'
|
||||
}
|
||||
Catch {
|
||||
$MsgParams = @{
|
||||
|
@ -39,13 +40,13 @@ Function Invoke-AppVeyorBumpVersion() {
|
|||
[CmdletBinding()]
|
||||
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.
|
||||
Get-ChildItem -Path "Env:*" | Where-Object { $_.name -notmatch "(NuGetToken|CoverallsToken)"} | Sort-Object -Property Name | Format-Table
|
||||
|
||||
Try {
|
||||
$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)
|
||||
Out-File -FilePath (".\src\{0}.psd1" -f $CALLSIGN) -InputObject $BumpedManifest -NoClobber -Encoding utf8 -Force
|
||||
}
|
||||
|
@ -62,6 +63,7 @@ Function Invoke-AppVeyorBumpVersion() {
|
|||
|
||||
Function Invoke-AppVeyorBuild() {
|
||||
[CmdletBinding()]
|
||||
[OutputType([PsCustomObject])]
|
||||
Param()
|
||||
$MsgParams = @{
|
||||
Message = 'Creating build artifacts'
|
||||
|
@ -82,7 +84,8 @@ Function Invoke-AppVeyorBuild() {
|
|||
Details = 'Pushing artifacts to AppVeyor store.'
|
||||
}
|
||||
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() {
|
||||
|
@ -95,8 +98,31 @@ Function Invoke-AppVeyorTests() {
|
|||
Details = 'Now running all test found in .\tests\ dir.'
|
||||
}
|
||||
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) {
|
||||
"Passed" {
|
||||
$TestParams = @{
|
||||
|
@ -134,16 +160,18 @@ Function Invoke-AppVeyorTests() {
|
|||
}
|
||||
}
|
||||
}
|
||||
If ($testresults.FailedCount -gt 0) {
|
||||
If ($TestResults.FailedCount -gt 0) {
|
||||
$MsgParams = @{
|
||||
Message = 'Pester Tests failed.'
|
||||
Category = 'Error'
|
||||
Details = "$($testresults.FailedCount) tests failed."
|
||||
Details = "$($TestResults.FailedCount) tests failed."
|
||||
}
|
||||
Add-AppveyorMessage @MsgParams
|
||||
Throw $MsgParams.Message
|
||||
}
|
||||
|
||||
return $TestResults.CodeCoverage
|
||||
|
||||
}
|
||||
|
||||
Function Invoke-CoverageReport() {
|
||||
|
@ -151,13 +179,17 @@ Function Invoke-CoverageReport() {
|
|||
Param(
|
||||
[Parameter(Mandatory = $False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]$RepoToken = $Env:CoverallsToken
|
||||
[String]$RepoToken = $Env:CoverallsToken,
|
||||
|
||||
[Parameter(Mandatory = $True)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[PSCustomObject]$PesterCoverageReport
|
||||
)
|
||||
|
||||
$FileMap = New-PesterFileMap -SourceRoot '.\src' -PesterRoot '.\tests'
|
||||
$CoverageReport = New-CoverageReport -PesterFileMap $FileMap -RepoToken $RepoToken
|
||||
#$CoverageReport | Format-Custom -Depth 5 | Out-String | Write-Verbose
|
||||
$CoverageReport = New-CoverageReport -CodeCoverage $PesterCoverageReport -RepoToken $RepoToken
|
||||
Write-Host "CoverageReport JSON:" -ForegroundColor Yellow
|
||||
$CoverageReport | Out-String | Write-Host
|
||||
#$CoverageReport | ConvertTo-Json -Depth 5 | Out-String | Write-Verbose
|
||||
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
|
||||
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
|
||||
Write-Host "Available Package Sources:" -ForegroundColor Yellow
|
||||
Write-Host "Available Package Sources:" -ForegroundColor Black -BackgroundColor Yellow
|
||||
Get-PackageSource
|
||||
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
|
||||
}
|
||||
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
|
||||
Import-PackageProvider NuGet -MinimumVersion '2.8.5.201' -Force
|
||||
}
|
||||
Try {
|
||||
If ($env:APPVEYOR_REPO_BRANCH -eq 'master') {
|
||||
Write-Host "try to publish module" -ForegroundColor Yellow
|
||||
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Yellow
|
||||
Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -Force
|
||||
Write-Host "try to publish module" -ForegroundColor Black -BackgroundColor Yellow
|
||||
Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Black -BackgroundColor Yellow
|
||||
Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -Force -AllowPrerelease
|
||||
}
|
||||
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.
|
||||
# Publish-Module -Name $CALLSIGN -NuGetApiKey $env:NuGetToken -Verbose -WhatIf
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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