forked from OCram85/PSCredentialStore
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
d92d963979 | |||
5a68527061 |
@ -20,10 +20,9 @@ matrix:
|
|||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
|
|
||||||
addons:
|
#addons:
|
||||||
artifacts:
|
# artifacts:
|
||||||
#paths: $(ls ./../dist/PowerShellGet.zip | tr "\n" ":")
|
# paths: ./dist/PowerShellGet.zip
|
||||||
paths: ./dist/PowerShellGet.zip
|
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
@ -24,7 +24,6 @@ image: Visual Studio 2017
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: Import-Module .\tools\AppVeyor.psm1
|
- ps: Import-Module .\tools\AppVeyor.psm1
|
||||||
- ps: Import-Module .\tools\CoverallsIO.psm1
|
|
||||||
- ps: Invoke-InstallDependencies
|
- ps: Invoke-InstallDependencies
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
81
src/Certificate/Get-CSCertificate.ps1
Normal file
81
src/Certificate/Get-CSCertificate.ps1
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
function Get-CSCertificate {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Returns the certificate object given by thumbprint.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
You can use this function to get a stored certificate. Search for the object by its unique thumbprint.
|
||||||
|
|
||||||
|
.PARAMETER Thumbprint
|
||||||
|
Provide one or more thumprints.
|
||||||
|
|
||||||
|
.PARAMETER StoreName
|
||||||
|
Select the store name in which you want to search the certificates.
|
||||||
|
|
||||||
|
.PARAMETER StoreLocation
|
||||||
|
Select between the both available locations CurrentUser odr LocalMachine.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
[string]
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
[System.Security.Cryptography.X509Certificates.X509Certificate2[]]
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-CSCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser'
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Get-CSCertificate.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string[]]$Thumbprint,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'AddressBook',
|
||||||
|
'AuthRoot',
|
||||||
|
'CertificateAuthority',
|
||||||
|
'Disallowed',
|
||||||
|
'My',
|
||||||
|
'Root',
|
||||||
|
'TrustedPeople',
|
||||||
|
'TrustedPublisher'
|
||||||
|
)]
|
||||||
|
[string]$StoreName = 'My',
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'CurrentUser',
|
||||||
|
'LocalMachine'
|
||||||
|
)]
|
||||||
|
[string]$StoreLocation = 'CurrentUser'
|
||||||
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
|
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::New($StoreName, $StoreLocation)
|
||||||
|
try {
|
||||||
|
$Store.Open('ReadOnly')
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
foreach ($Thumb in $Thumbprint) {
|
||||||
|
Write-Output $Store.Certificates | Where-Object { $_.Thumbprint -eq $Thumb }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end {
|
||||||
|
$Store.Close()
|
||||||
|
}
|
||||||
|
}
|
112
src/Certificate/Import-CSCertificate.ps1
Normal file
112
src/Certificate/Import-CSCertificate.ps1
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
function Import-CSCertificate {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
adds a given pfx certificate file to current uerers personal certificate store.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This function is used to import existing pfx certificate files. The Import-PFXCertificate cmdle from the
|
||||||
|
PKI module imports the certficate into a deprecated store. Thus you can't read the private key afterwards or
|
||||||
|
using it for decrypting data.
|
||||||
|
|
||||||
|
.PARAMETER Path
|
||||||
|
Path to an existing *.pfx certificate file.
|
||||||
|
|
||||||
|
.PARAMETER StoreName
|
||||||
|
Additionally you change change the store where you want the certificate into.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
[None]
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
[None]
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Import-CSCertificate -Path (Join-Path -Path $Env:APPDATA -ChildPath '/PSCredentialStore.pfx')
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Import-CSCertificate.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Path,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'AddressBook',
|
||||||
|
'AuthRoot',
|
||||||
|
'CertificateAuthority',
|
||||||
|
'Disallowed',
|
||||||
|
'My',
|
||||||
|
'Root',
|
||||||
|
'TrustedPeople',
|
||||||
|
'TrustedPublisher'
|
||||||
|
)]
|
||||||
|
[string]$StoreName = 'My',
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'CurrentUser',
|
||||||
|
'LocalMachine'
|
||||||
|
)]
|
||||||
|
[string]$StoreLocation = 'CurrentUser',
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'ReadOnly',
|
||||||
|
'ReadWrite',
|
||||||
|
'MaxAllowed',
|
||||||
|
'OpenExistingOnly',
|
||||||
|
'InclueArchived'
|
||||||
|
)]
|
||||||
|
[string]$OpenFlags = 'ReadWrite'
|
||||||
|
)
|
||||||
|
begin {
|
||||||
|
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation)
|
||||||
|
try {
|
||||||
|
$Store.Open($OpenFlags)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process {
|
||||||
|
try {
|
||||||
|
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new(
|
||||||
|
$Path,
|
||||||
|
$null,
|
||||||
|
(
|
||||||
|
[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable -bor
|
||||||
|
[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Test-CSCertificate -Thumbprint $cert.Thumbprint) {
|
||||||
|
Write-Warning -Message ('The certificate with thumbprint {0} is already present!' -f $cert.Thumbprint)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Store.Add($cert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error -ErrorAction Stop
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Exception]::new(
|
||||||
|
'Could not read or add the pfx certificate!'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end {
|
||||||
|
$Store.Close()
|
||||||
|
}
|
||||||
|
}
|
86
src/Certificate/Test-CSCertificate.ps1
Normal file
86
src/Certificate/Test-CSCertificate.ps1
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
function Test-CSCertificate {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Tests if the given certificate exists in a store.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Use this function to ensure if a certificate is already imported into a given store.
|
||||||
|
|
||||||
|
.PARAMETER Thumbprint
|
||||||
|
Provide one or more thumprints.
|
||||||
|
|
||||||
|
.PARAMETER StoreName
|
||||||
|
Select the store name in which you want to search the certificates.
|
||||||
|
|
||||||
|
.PARAMETER StoreLocation
|
||||||
|
Select between the both available locations CurrentUser odr LocalMachine.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
[None]
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
[bool]
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Test-CSCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser'
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
File Name : Test-CSCertificate.ps1
|
||||||
|
Author : Marco Blessing - marco.blessing@googlemail.com
|
||||||
|
Requires :
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/OCram85/PSCredentialStore
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([bool])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string]$Thumbprint,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'AddressBook',
|
||||||
|
'AuthRoot',
|
||||||
|
'CertificateAuthority',
|
||||||
|
'Disallowed',
|
||||||
|
'My',
|
||||||
|
'Root',
|
||||||
|
'TrustedPeople',
|
||||||
|
'TrustedPublisher'
|
||||||
|
)]
|
||||||
|
[string]$StoreName = 'My',
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[ValidateSet(
|
||||||
|
'CurrentUser',
|
||||||
|
'LocalMachine'
|
||||||
|
)]
|
||||||
|
[string]$StoreLocation = 'CurrentUser'
|
||||||
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
|
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::New($StoreName, $StoreLocation)
|
||||||
|
try {
|
||||||
|
$Store.Open('ReadOnly')
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
$Cert = $Store.Certificates | Where-Object { $_.Thumbprint -eq $Thumbprint }
|
||||||
|
|
||||||
|
if ($null -eq $Cert) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end {
|
||||||
|
$Store.Close()
|
||||||
|
}
|
||||||
|
}
|
@ -87,7 +87,24 @@ function Get-CredentialStoreItem {
|
|||||||
$CSMembers = Get-Member -InputObject $CS
|
$CSMembers = Get-Member -InputObject $CS
|
||||||
# Let's first check if the given remote host exists as object property
|
# Let's first check if the given remote host exists as object property
|
||||||
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) {
|
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) {
|
||||||
$Cert = Get-PfxCertificate -FilePath $CS.PfXCertificate -ErrorAction Stop
|
try {
|
||||||
|
if ($null -eq $CS.PfxCertificate) {
|
||||||
|
$Cert = Get-CSCertificate -Thumbprint $CS.Thumbprint
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Cert = Get-PfxCertificate -FilePath $CS.PfxCertificate -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$_.Exception.Message | Write-Error
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Security.Cryptography.CryptographicException]::new(
|
||||||
|
'Could not read the given PFX certificate.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
$DecryptedKey = $Cert.PrivateKey.Decrypt(
|
$DecryptedKey = $Cert.PrivateKey.Decrypt(
|
||||||
[Convert]::FromBase64String($CS.$CredentialName.EncryptedKey),
|
[Convert]::FromBase64String($CS.$CredentialName.EncryptedKey),
|
||||||
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
|
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
|
||||||
|
@ -117,7 +117,21 @@ function New-CredentialStoreItem {
|
|||||||
|
|
||||||
if ($Credential.UserName) {
|
if ($Credential.UserName) {
|
||||||
try {
|
try {
|
||||||
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
if ($null -eq $CSContent.PfxCertificate) {
|
||||||
|
$Cert = Get-CSCertificate -Thumbprint $CSContent.Thumbprint
|
||||||
|
if ($null -eq $Cert) {
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.Security.Cryptography.X509Certificates.FileNotFoundException]::new(
|
||||||
|
('Could not find the linked certificate with thumbprint {0}' -f $CSContent.Thumbprint)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$_.Exception.Message | Write-Error
|
$_.Exception.Message | Write-Error
|
||||||
|
@ -103,14 +103,20 @@ function Set-CredentialStoreItem {
|
|||||||
|
|
||||||
if ($Credential.UserName) {
|
if ($Credential.UserName) {
|
||||||
try {
|
try {
|
||||||
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
if ($null -eq $CSContent.PfxCertificate) {
|
||||||
|
$Cert = Get-CSCertificate -Thumbprint $CSContent.Thumbprint
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$_.Exception.Message | Write-Error
|
$_.Exception.Message | Write-Error
|
||||||
$ErrorParams = @{
|
$ErrorParams = @{
|
||||||
Message = 'Could not read the given PFX certificate.'
|
|
||||||
ErrorAction = 'Stop'
|
ErrorAction = 'Stop'
|
||||||
Exception = [System.Security.Cryptography.CryptographicException]::new()
|
Exception = [System.Security.Cryptography.CryptographicException]::new(
|
||||||
|
'Could not read the given PFX certificate.'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Write-Error @ErrorParams
|
Write-Error @ErrorParams
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,11 @@
|
|||||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||||
FunctionsToExport = @(
|
FunctionsToExport = @(
|
||||||
# Certificate
|
# Certificate
|
||||||
|
'Get-CSCertificate',
|
||||||
|
'Import-CSCertificate',
|
||||||
'New-CRTAttribute',
|
'New-CRTAttribute',
|
||||||
'New-PfxCertificate',
|
'New-PfxCertificate',
|
||||||
|
'Test-CSCertificate',
|
||||||
'Use-PfxCertificate',
|
'Use-PfxCertificate',
|
||||||
# Connection
|
# Connection
|
||||||
'Connect-To',
|
'Connect-To',
|
||||||
@ -79,8 +82,7 @@
|
|||||||
# Store
|
# Store
|
||||||
'Get-CredentialStore',
|
'Get-CredentialStore',
|
||||||
'New-CredentialStore',
|
'New-CredentialStore',
|
||||||
'Test-CredentialStore',
|
'Test-CredentialStore'
|
||||||
'Update-CredentialStore'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||||
@ -122,7 +124,7 @@
|
|||||||
ReleaseNotes = 'This is a pre-release version!. Do not use in production!'
|
ReleaseNotes = 'This is a pre-release version!. Do not use in production!'
|
||||||
|
|
||||||
# Prerelease string of this module
|
# Prerelease string of this module
|
||||||
Prerelease = 'alpha1'
|
Prerelease = 'preview'
|
||||||
|
|
||||||
# Flag to indicate whether the module requires explicit user acceptance for install/update
|
# Flag to indicate whether the module requires explicit user acceptance for install/update
|
||||||
# RequireLicenseAcceptance = $false
|
# RequireLicenseAcceptance = $false
|
||||||
|
@ -70,6 +70,11 @@ function Resolve-Dependency {
|
|||||||
|
|
||||||
process {
|
process {
|
||||||
$SelectedDependency = $Dependency.Optional | Where-Object {$_.Name -match $Name}
|
$SelectedDependency = $Dependency.Optional | Where-Object {$_.Name -match $Name}
|
||||||
|
# return true if there is no dependency defined
|
||||||
|
if ($null -eq $SelectedDependency) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
$res = @()
|
$res = @()
|
||||||
foreach ($Module in $SelectedDependency.Modules) {
|
foreach ($Module in $SelectedDependency.Modules) {
|
||||||
$res += Test-Module -Name $Module
|
$res += Test-Module -Name $Module
|
||||||
|
@ -59,19 +59,23 @@ function New-CredentialStore {
|
|||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$Path,
|
[System.IO.FileInfo]$Path,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$Force,
|
[Switch]$Force,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[switch]$PassThru,
|
[Switch]$PassThru,
|
||||||
|
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
[Switch]$SkipPFXCertCreation
|
[Switch]$SkipPFXCertCreation,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false, ParameterSetName = "Private")]
|
||||||
|
[Parameter(Mandatory = $false, ParameterSetName = "Shared")]
|
||||||
|
[Switch]$UseCertStore
|
||||||
)
|
)
|
||||||
|
|
||||||
begin {
|
begin {
|
||||||
@ -80,6 +84,28 @@ function New-CredentialStore {
|
|||||||
|
|
||||||
# Set latest Credential Store version
|
# Set latest Credential Store version
|
||||||
# Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope
|
# Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope
|
||||||
|
|
||||||
|
# test if the path input is a valid file path
|
||||||
|
if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Path')) {
|
||||||
|
if ($Path.Attributes -contains 'Directory') {
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.IO.InvalidDataException]::new(
|
||||||
|
'Please provide a full path containing the credential store file name with the .json extension!'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
elseif ( ($null -eq $Path.Extension) -or ($Path.Extension -ne '.json')) {
|
||||||
|
$ErrorParams = @{
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
Exception = [System.IO.InvalidDataException]::new(
|
||||||
|
'Your provided path does not conain the required file extension .json !'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Write-Error @ErrorParams
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
process {
|
process {
|
||||||
@ -112,8 +138,8 @@ function New-CredentialStore {
|
|||||||
State = 'PSCredentialStore'
|
State = 'PSCredentialStore'
|
||||||
City = 'PSCredentialStore'
|
City = 'PSCredentialStore'
|
||||||
Organization = 'PSCredentialStore'
|
Organization = 'PSCredentialStore'
|
||||||
OrganizationalUnitName = ' '
|
OrganizationalUnitName = $PSCmdlet.ParameterSetName
|
||||||
CommonName = 'PrivateStore'
|
CommonName = 'PSCredentialStore'
|
||||||
}
|
}
|
||||||
$CRTAttribute = New-CRTAttribute @CRTParams
|
$CRTAttribute = New-CRTAttribute @CRTParams
|
||||||
|
|
||||||
@ -133,6 +159,7 @@ function New-CredentialStore {
|
|||||||
Confirm = $false
|
Confirm = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# test if there is already a cert
|
||||||
if ((Test-Path $PfxParams.CertName) -and (! $Force.IsPresent)) {
|
if ((Test-Path $PfxParams.CertName) -and (! $Force.IsPresent)) {
|
||||||
$ErrorParams = @{
|
$ErrorParams = @{
|
||||||
Exception = [System.IO.InvalidDataException]::new(
|
Exception = [System.IO.InvalidDataException]::new(
|
||||||
@ -176,8 +203,15 @@ function New-CredentialStore {
|
|||||||
Type = $null
|
Type = $null
|
||||||
}
|
}
|
||||||
if (! $SkipPFXCertCreation.IsPresent) {
|
if (! $SkipPFXCertCreation.IsPresent) {
|
||||||
$ObjProperties.PfXCertificate = $PfxParams.CertName
|
|
||||||
$ObjProperties.Thumbprint = $FreshCert.Thumbprint
|
$ObjProperties.Thumbprint = $FreshCert.Thumbprint
|
||||||
|
|
||||||
|
if (!$UseCertStore.IsPresent) {
|
||||||
|
$ObjProperties.PfxCertificate = $PfxParams.CertName
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose 'Importing new PFX certificate file...'
|
||||||
|
Import-CSCertificate -Path $PfxParams.CertName -StoreName My -StoreLocation CurrentUser
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($PSCmdlet.ParameterSetName -eq "Shared") {
|
if ($PSCmdlet.ParameterSetName -eq "Shared") {
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
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 {
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ Describe "New-CredentialStoreItem" {
|
|||||||
# Creat a fresh CredentialStore first
|
# Creat a fresh CredentialStore first
|
||||||
New-CredentialStore -Force
|
New-CredentialStore -Force
|
||||||
|
|
||||||
[String]$tmp = (65..90) + (97..122) | Get-Random -Count 5 | % {[char]$_}
|
[String]$tmp = (65..90) + (97..122) | Get-Random -Count 5 | ForEach-Object { [char]$_ }
|
||||||
$tmp = $tmp.Replace(' ', '')
|
$tmp = $tmp.Replace(' ', '')
|
||||||
$tmpUser = "MyUser"
|
$tmpUser = "MyUser"
|
||||||
$tmpPwd = "fooobarysdfsfs" | ConvertTo-SecureString -AsPlainText -Force
|
$tmpPwd = "fooobarysdfsfs" | ConvertTo-SecureString -AsPlainText -Force
|
||||||
@ -65,7 +65,7 @@ Describe "New-CredentialStoreItem" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
Context "General Exception handling" {
|
Context "General Exception handling" {
|
||||||
Mock Test-CredentialStore {return $false}
|
Mock Test-CredentialStore { return $false }
|
||||||
It "Missing CredentialStore should throw" {
|
It "Missing CredentialStore should throw" {
|
||||||
{ New-CredentialStoreItem -Shared -Path 'C:\missingStore.json' -RemoteHost 'notrelevant' } | Should -Throw "Could not add anything"
|
{ New-CredentialStoreItem -Shared -Path 'C:\missingStore.json' -RemoteHost 'notrelevant' } | Should -Throw "Could not add anything"
|
||||||
}
|
}
|
||||||
@ -81,5 +81,29 @@ Describe "New-CredentialStoreItem" {
|
|||||||
(Get-CredentialStoreItem -RemoteHost 'PipeHost').UserName | Should -Be 'pipeUser'
|
(Get-CredentialStoreItem -RemoteHost 'PipeHost').UserName | Should -Be 'pipeUser'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Context "Testing items with certficiate store" {
|
||||||
|
It "Create item in new store with cert store link" {
|
||||||
|
New-CredentialStore -UseCertStore -Force
|
||||||
|
|
||||||
|
$Path = Get-DefaultCredentialStorePath
|
||||||
|
$StoreHome = Split-Path -Path $Path -Parent
|
||||||
|
$CertFile = Join-Path -Path $StoreHome -ChildPath 'PSCredentialStore.pfx'
|
||||||
|
$Cert = Get-PfxCertificate -FilePath $CertFile
|
||||||
|
|
||||||
|
$myStore = [System.Security.Cryptography.X509Certificates.X509Store]::new('My')
|
||||||
|
$myStore.Open("ReadWrite")
|
||||||
|
$myStore.Add($Cert)
|
||||||
|
$MyStore.Close()
|
||||||
|
|
||||||
|
$UserName = 'testuser'
|
||||||
|
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
|
||||||
|
|
||||||
|
[PSCredential]::new($UserName, $Password) | New-CredentialStoreItem -RemoteHost 'foobarcerts'
|
||||||
|
|
||||||
|
$writtenItem = Get-CredentialStoreItem -RemoteHost 'foobarcerts'
|
||||||
|
$writtenItem.UserName | Should -Be "testuser"
|
||||||
|
$writtenItem.GetNetworkCredential().Password | Should -Be 'mypasswd'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ Describe "Resolve-Dependency" {
|
|||||||
{ Resolve-Dependency -Name 'awesome'} | Should -Not -Throw
|
{ Resolve-Dependency -Name 'awesome'} | Should -Not -Throw
|
||||||
}
|
}
|
||||||
|
|
||||||
It "Missing dependency file should return false" {
|
It "Missing dependency file should return true" {
|
||||||
Resolve-Dependency -Name 'awesome' | Should -Be $false
|
Resolve-Dependency -Name 'awesome' | Should -Be $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Context "Testing input variations" {
|
Context "Testing input variations" {
|
||||||
|
@ -46,7 +46,7 @@ Describe "New-CredentialStore" {
|
|||||||
Test-Path -Path $sCS | Should -Be $true
|
Test-Path -Path $sCS | Should -Be $true
|
||||||
}
|
}
|
||||||
It "Test2: Try to override existing shared CS" {
|
It "Test2: Try to override existing shared CS" {
|
||||||
{New-CredentialStore -Shared -Confirm:$false} | Should -Throw
|
{ New-CredentialStore -Shared -Confirm:$false } | Should -Throw
|
||||||
}
|
}
|
||||||
It "Test3: Reset shared CredentialStore" {
|
It "Test3: Reset shared CredentialStore" {
|
||||||
$now = Get-Date
|
$now = Get-Date
|
||||||
@ -59,19 +59,40 @@ Describe "New-CredentialStore" {
|
|||||||
Context "Custom Shared CS tests" {
|
Context "Custom Shared CS tests" {
|
||||||
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
|
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
|
||||||
It "Test1: Create new custom shared" {
|
It "Test1: Create new custom shared" {
|
||||||
{New-CredentialStore -Path $cCS -Shared -Confirm:$false} | Should -Not -Throw
|
{ New-CredentialStore -Path $cCS -Shared -Confirm:$false } | Should -Not -Throw
|
||||||
}
|
}
|
||||||
It "Test2: Try to override exiting one" {
|
It "Test2: Try to override exiting one" {
|
||||||
{New-CredentialStore -Path $cCS -Shared -Confirm:$false} | Should -Throw
|
{ New-CredentialStore -Path $cCS -Shared -Confirm:$false } | Should -Throw
|
||||||
}
|
}
|
||||||
It "Test3: Reset existing custom CredentialStore" {
|
It "Test3: Reset existing custom CredentialStore" {
|
||||||
{New-CredentialStore -Path $cCS -Shared -Force -Confirm:$false} | Should -Not -Throw
|
{ New-CredentialStore -Path $cCS -Shared -Force -Confirm:$false } | Should -Not -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Context "Test exception handling" {
|
Context "Test exception handling" {
|
||||||
Mock Out-File {throw "foobar exception"}
|
Mock Out-File { throw "foobar exception" }
|
||||||
It "JSON Conversion should fail and throw" {
|
It "JSON Conversion should fail and throw" {
|
||||||
{ New-CredentialStore -Path (Join-Path -Path (Get-TempDir) -ChildPath '/dummy.json') -Shared -Confirm:$false} | Should -Throw
|
{ New-CredentialStore -Path (Join-Path -Path (Get-TempDir) -ChildPath '/dummy.json') -Shared -Confirm:$false } | Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "Tests for Windows certificate store" {
|
||||||
|
It "Create new private store and skip certificate linking" {
|
||||||
|
{ New-CredentialStore -UseCertStore -Force } | Should -Not -Throw
|
||||||
|
$CS = Get-CredentialStore
|
||||||
|
$CS.PfxCertificate | Should -Be $null
|
||||||
|
$CS.Thumbprint | Should -Not -Be $null
|
||||||
|
$res = Test-CSCertificate -Thumbprint $CS.Thumbprint -StoreName My -StoreLocation CurrentUser
|
||||||
|
#Write-Verbose -Message ('res: {0}' -f $res) -Verbose
|
||||||
|
$res | Should -Be $true
|
||||||
|
|
||||||
|
}
|
||||||
|
It "Create new shared store and skipt certificate linking" {
|
||||||
|
{ New-CredentialStore -Shared -UseCertStore -Force } | Should -Not -Throw
|
||||||
|
$CS = Get-CredentialStore -Shared
|
||||||
|
$CS.PfxCertificate | Should -Be $null
|
||||||
|
$CS.Thumbprint | Should -Not -Be $null
|
||||||
|
$res = Test-CSCertificate -Thumbprint $CS.Thumbprint -StoreName My -StoreLocation CurrentUser
|
||||||
|
#Write-Verbose -Message ('res: {0}' -f $res) -Verbose
|
||||||
|
$res | Should -Be $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ Function Invoke-InstallDependencies() {
|
|||||||
Import-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force
|
Import-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force
|
||||||
Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.4.2' -Force -SkipPublisherCheck -AllowClobber
|
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 'posh-git' -Scope CurrentUser -RequiredVersion '1.0.0-beta2' -Force -SkipPublisherCheck -AllowClobber -AllowPrerelease
|
||||||
# Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber
|
Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber -RequiredVersion '1.0.78'
|
||||||
Import-Module -Name 'Pester', 'posh-git' #, 'PSCoverage'
|
Import-Module -Name 'Pester', 'posh-git' , 'PSCoverage'
|
||||||
}
|
}
|
||||||
Catch {
|
Catch {
|
||||||
$MsgParams = @{
|
$MsgParams = @{
|
||||||
|
@ -1,178 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user