fix lint (PSScriptAnalyzer) issues (#62)
All checks were successful
continuous-integration/drone/push Build is passing

#### 📖 Summary

<!-- Provide a summary of your changes. Describe the why and not how. -->

#### 📑 Test Plan

> 💡 Select your test plan for the code changes.

- [x] Tested via Drone.io pipeline
- [ ] Custom test
- [ ] No test plan

##### Details / Justification

<!-- Add your test details or justification for missing tests here. -->

#### 📚 Additional Notes

<!-- A place for additional detail notes. -->

Co-authored-by: OCram85 <marco.blessing@googlemail.com>
Reviewed-on: #62
This commit is contained in:
OCram85 2022-07-15 10:59:56 +02:00
parent d0b7e53c80
commit 3d90d912ee
16 changed files with 163 additions and 43 deletions

View File

@ -23,7 +23,7 @@ steps:
pwsh -NonInteractive -c "& {
Install-Module -Name 'DroneHelper' -Repository 'PSGallery' -ErrorAction 'Stop' -AllowPrerelease -Force;
Import-Module 'DroneHelper' -ErrorAction 'Stop';
Invoke-FileLinter -Verbose -Debug
Invoke-FileLinter
}"
- name: "ScriptAnalyzer"

View File

@ -34,10 +34,23 @@ function New-CSCertAttribute {
[PSCredentialStore.Certificate.CSRDetails]
.EXAMPLE
New-CSCertAttribute -Country 'DE' -State 'BW' -City 'Karlsruhe' -Organization 'AwesomeIT' -OrganizationalUnitName '' -CommonName 'MyPrivateCert'
$AttribParams = @{
Country = 'DE'
State = 'BW'
City = 'Karlsruhe'
Organization ='AwesomeIT'
OrganizationalUnitName ='PSCredentialStore'
CommonName ='MyPrivateCert'
}
New-CSCertAttribute @AttribParams
#>
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseShouldProcessForStateChangingFunctions',
'',
Justification = 'Returns a new object and does not change data'
)]
[OutputType('PSCredentialStore.Certificate.Attribute')]
param (
[Parameter(Mandatory = $true)]

View File

@ -26,6 +26,11 @@ function New-CSCertificate {
#>
[CmdletBinding(SupportsShouldProcess = $true)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidUsingInvokeExpression',
'',
Justification = 'needed for openssl wrapping'
)]
[OutputType()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
@ -57,7 +62,10 @@ function New-CSCertificate {
Write-Error @ErrorParams
}
}
elseif (($PSVersionTable.PSEdition -eq 'Desktop' -and $PSVersionTable.PSVersion.Major -lt 6) -or ($IsWindows -eq $true)) {
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'
}
@ -77,7 +85,9 @@ function New-CSCertificate {
$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'
$ExpPattern = (
'& ''{0}'' req -x509 -sha256 -nodes -days {1} -newkey rsa:2048 -keyout {2} -out {3} -subj "{4}" *>$null'
)
$ExpValues = @(
$openssl,
$CRTAttribute.Days

View File

@ -35,7 +35,10 @@ function Test-CSCertificate {
$CS = Get-CredentialStore -Shared
}
if ($null -ne $CS.PfxCertificate) {
Write-Warning 'There is a Pfx certificate file linked in the store. Certificates saved in the Cert store will be ignored!'
Write-Warning -Message (
'There is a Pfx certificate file linked in the store. ' +
'Certificates saved in the Cert store will be ignored!'
)
}
}
@ -47,13 +50,28 @@ function Test-CSCertificate {
if ( $isLinux) {
$cert = Get-CSPfxCertificate -Thumbprint $CS.Thumbprint -StoreName 'My' -StoreLocation 'CurrentUser'
if ($null -eq $cert) {
$cert = Get-CSPfxCertificate -Thumbprint $CS.Thumbprint -StoreName 'Root' -StoreLocation 'LocalMachine'
$PFXParams = @{
Thumbprint = $CS.Thumbprint
StoreName = 'Root'
StoreLocation = 'LocalMachine'
}
$cert = Get-CSPfxCertificate @PFXParams
}
}
elseif ( (! $isLinux) -or ($isWindows) ) {
$cert = Get-CSPfxCertificate -Thumbprint $CS.Thumbprint -StoreName 'My' -StoreLocation 'LocalMachine'
$PFXParams = @{
Thumbprint = $CS.Thumbprint
StoreName = 'My'
StoreLocation = 'LocalMachine'
}
$cert = Get-CSPfxCertificate @PFXParams
if ($null -eq $cert) {
$cert = Get-CSPfxCertificate -Thumbprint $CS.Thumbprint -StoreName 'Root' -StoreLocation 'LocalMachine'
$PFXParams = @{
Thumbprint = $CS.Thumbprint
StoreName = 'Root'
StoreLocation = 'LocalMachine'
}
$cert = Get-CSPfxCertificate @PFXParams
}
}
}

View File

@ -61,6 +61,11 @@ function Connect-To {
#>
[CmdletBinding(DefaultParameterSetName = 'Private')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidGlobalVars',
'',
Justification = 'Wrapping existing var from WinSCP module.'
)]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $true, ParameterSetName = 'Private')]
@ -114,7 +119,9 @@ function Connect-To {
# 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'
Write-Error -Message (
"Could not resolve the optional dependencies defined for {0}" -f $Type
) -ErrorAction 'Stop'
}
switch ($Type) {
"VMware" {
@ -146,7 +153,10 @@ function Connect-To {
catch {
$MessageParams = @{
Message = "Unable to look up credential store item for RemoteHost {0}/Identifier {1}!" -f $RemoteHost, $Identifier
Message = (
"Unable to look up credential store item for RemoteHost " +
("{0}/Identifier {1}!" -f $RemoteHost, $Identifier)
)
ErrorAction = 'Stop'
}
Write-Error @MessageParams
@ -198,7 +208,10 @@ function Connect-To {
if (!($WinSCPSession.Opened)) {
# Check the connection state and find out if the session is still open.
$MessageParams = @{
Message = "Connection to {0} using Type {1} was established. But now it seems to be lost!" -f $RemoteHost, $Type
Message = (
("Connection to {0} using Type {1} " -f $RemoteHost, $Type) +
"was established. But now it seems to be lost!"
)
ErrorAction = 'Stop'
}
Write-Error @MessageParams
@ -261,6 +274,8 @@ function Connect-To {
ErrorAction = 'Stop'
}
$Global:PSExchangeRemote = New-PSSession @ConnectionParams
# ScriptAnalyzer issue (unused var) workaround.
$null = $Global:PSExchangeRemote
}
catch {
# Write a error message to the log.
@ -300,7 +315,9 @@ function Connect-To {
try {
$SessionOption = New-WinSCPSessionOption @WinSCPSessionParams
$Global:WinSCPSession = New-WinSCPSession -SessionOption $SessionOption
Write-Verbose -Message ("SCP Connection established with {0}" -f $Global:WinSCPSession.Hostname)
Write-Verbose -Message (
"SCP Connection established with {0}" -f $Global:WinSCPSession.Hostname
)
}
catch {
# Write a error message to the log.
@ -314,7 +331,10 @@ function Connect-To {
if (!($WinSCPSession.Opened)) {
# Check the connection state and find out if the session is still open.
$MessageParams = @{
Message = "Connection to {0} using Type {1} was established. But now it seems to be lost!" -f $RemoteHost, $Type
Message = (
("Connection to {0} using Type {1} was established. " -f $RemoteHost, $Type) +
"But now it seems to be lost!"
)
ErrorAction = 'Stop'
}
Write-Error @MessageParams

View File

@ -52,6 +52,11 @@ function Disconnect-From {
#>
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidGlobalVars',
'',
Justification = 'Wrapping existing global vars from external modules'
)]
param (
[Parameter(Mandatory = $true)]
[string]$RemoteHost,
@ -133,7 +138,9 @@ function Disconnect-From {
"NetAppFAS" {
try {
$MessageParams = @{
Message = "Setting {0} to `$null, which will disconnect NetAppFAS" -f $Global:CurrentNcController
Message = (
"Setting {0} to `$null, which will disconnect NetAppFAS" -f $Global:CurrentNcController
)
ErrorAction = 'Continue'
}
Write-Verbose @MessageParams

View File

@ -36,6 +36,11 @@ function New-CredentialStoreItem {
#>
[CmdletBinding(DefaultParameterSetName = 'Private')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseShouldProcessForStateChangingFunctions',
'',
Justification = 'Adds data into an existing object/file'
)]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $true, ParameterSetName = 'Private')]
@ -109,7 +114,7 @@ function New-CredentialStoreItem {
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
}
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
if (Get-Member -InputObject $CSContent -Name $CredentialName -MemberType Properties) {
$MessageParams = @{
Message = 'The given host already exists. Nothing to do here.'
}
@ -123,9 +128,20 @@ function New-CredentialStoreItem {
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))
EncryptedKey = [Convert]::ToBase64String(
$Cert.PublicKey.Key.Encrypt(
$RSAKey,
[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1
)
)
}
Add-Member -InputObject $CSContent -Name $CredentialName -MemberType NoteProperty -Value $CredentialHash
$MemberParams = @{
InputObject = $CSContent
Name = $CredentialName
MemberType = 'NoteProperty'
Value = $CredentialHash
}
Add-Member @MemberParams
try {
ConvertTo-Json -InputObject $CSContent | Out-File -FilePath $Path
}

View File

@ -40,6 +40,11 @@ function Remove-CredentialStoreItem {
#>
[CmdletBinding(DefaultParameterSetName = 'Private')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseShouldProcessForStateChangingFunctions',
'',
Justification = 'Removes data from existing store.'
)]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
@ -90,7 +95,7 @@ function Remove-CredentialStoreItem {
$CredentialName = $RemoteHost
}
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype NoteProperty) {
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 -Depth 5 | Out-File -FilePath $Path -Encoding utf8

View File

@ -37,6 +37,11 @@ function Set-CredentialStoreItem {
#>
[CmdletBinding(DefaultParameterSetName = 'Private')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseShouldProcessForStateChangingFunctions',
'',
Justification = 'Updates existing credential object.'
)]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
@ -105,10 +110,14 @@ function Set-CredentialStoreItem {
$Cert = Get-PfxCertificate -FilePath $CSContent.PfxCertificate -ErrorAction Stop
}
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
if (Get-Member -InputObject $CSContent -Name $CredentialName -MemberType Properties) {
$RSAKey = Get-RandomAESKey
$CSContent.$CredentialName.User = $Credential.UserName
$CSContent.$CredentialName.Password = ConvertFrom-SecureString -SecureString $Credential.Password -Key $RSAKey
$ConvertParams = @{
SecureString = $Credential.Password
Key = $RSAKey
}
$CSContent.$CredentialName.Password = ConvertFrom-SecureString @ConvertParams
$CSContent.$CredentialName.LastChange = $CurrentDate
$CSContent.$CredentialName.EncryptedKey = [Convert]::ToBase64String(
$Cert.PublicKey.Key.Encrypt(

View File

@ -19,7 +19,7 @@
CompanyName = ''
# Copyright statement for this module
Copyright = '(c) 2022 OCram85. All rights reserved.'
Copyright = '(c) OCram85. All rights reserved.'
# Description of the functionality provided by this module
Description = 'A simple cross-platform credential manager for PSCredential objects.'
@ -33,10 +33,12 @@
# 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.
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the
# PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for
# the PowerShell Desktop edition only.
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
@ -63,7 +65,8 @@
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# 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 = @(
# Certificate
'Get-CSCertificate',
@ -92,13 +95,15 @@
'Test-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.
CmdletsToExport = @()
# Variables to export from this module
VariablesToExport = '*'
# Aliases 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 aliases to export.
# Aliases 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 aliases to export.
AliasesToExport = @()
# DSC resources to export from this module
@ -110,7 +115,8 @@
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData
# hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
@ -125,7 +131,7 @@
ProjectUri = 'https://gitea.ocram85.com/OCram85/PSCredentialStore'
# A URL to an icon representing this module.
IconUri = 'https://gitea.ocram85.com/OCram85/PSCredentialStore/raw/branch/master/assets/logo256.png'
IconUri = 'https://gitea.ocram85.com/OCram85/PSCredentialStore/raw/branch/master/assets/logo256.png'
# ReleaseNotes of this module
ReleaseNotes = 'See https://gitea.ocram85.com/OCram85/PSCredentialStore/releases page for details.'
@ -146,7 +152,8 @@
# HelpInfo URI of this module
HelpInfoURI = 'https://gitea.ocram85.com/OCram85/PSCredentialStore'
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# Default prefix for commands exported from this module. Override the default prefix
# using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}

View File

@ -33,7 +33,11 @@ function Get-DefaultCredentialStorePath {
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')) {
elseif (
($isWindows) -or
($PSVersionTable.PSVersion.Major -lt 6) -or
($PSVersionTable.PSEdition -eq 'Desktop')
) {
return Join-Path -Path $env:ProgramData -ChildPath 'PSCredentialStore/CredentialStore.json'
}
}
@ -44,7 +48,11 @@ function Get-DefaultCredentialStorePath {
if ($IsMacOS) {
return Join-Path -Path $Env:HOME -ChildPath 'CredentialStore.json'
}
elseif (($isWindows) -or ($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop')) {
elseif (
($isWindows) -or
($PSVersionTable.PSVersion.Major -lt 6) -or
($PSVersionTable.PSEdition -eq 'Desktop')
) {
return Join-Path -Path $env:AppData -ChildPath 'CredentialStore.json'
}
}

View File

@ -5,8 +5,8 @@ function Import-CSPfxCertificate {
.DESCRIPTION
This function is used to import existing pfx certificate files. The Import-PFXCertificate cmdlet from the
PKI module imports the certificate into a deprecated store. Thus you can't read the private key afterwards or
using it for decrypting data.
PKI module imports the certificate 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.
@ -83,7 +83,9 @@ function Import-CSPfxCertificate {
)
if (Test-CSPfxCertificate -Thumbprint $cert.Thumbprint) {
Write-Warning -Message ('The certificate with thumbprint {0} is already present!' -f $cert.Thumbprint)
Write-Warning -Message (
'The certificate with thumbprint {0} is already present!' -f $cert.Thumbprint
)
}
else {
$Store.Add($cert)

View File

@ -36,7 +36,9 @@ function Resolve-Dependency {
.EXAMPLE
If (-not (Resolve-Dependency -Name 'VMware')) {
Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f 'VMware') -ErrorAction 'Stop'
Write-Error -Message (
"Could not resolve the optional dependencies defined for {0}" -f 'VMware'
) -ErrorAction 'Stop'
}
#>
@ -60,6 +62,8 @@ function Resolve-Dependency {
}
process {
# ScriptAnalyzer issue workaround (unused var)
$null = $Name
$SelectedDependency = $Dependency.Optional | Where-Object { $_.Name -match $Name }
# return true if there is no dependency defined
if ($null -eq $SelectedDependency) {

View File

@ -64,6 +64,8 @@ function Test-CSPfxCertificate {
}
process {
# Script analyzer issue (unused var) workaround
$null = $Thumbprint
$Cert = $Store.Certificates | Where-Object { $_.Thumbprint -eq $Thumbprint }
if ($null -eq $Cert) {

View File

@ -14,8 +14,6 @@ BeforeAll {
Describe "Get-CredentialStore" {
Context "Basic logic tests" {
It "Read CS without params" {
$TestCredentialStore = './resources/cs/CredentialStore.json'
$TestPfxCert = './resources/cs/PSCredentialStore.pfx'
if (! (Test-Path -Path (Get-DefaultCredentialStorePath)) ) {
{ New-CredentialStore -Force } | Should -Not -Throw
}

View File

@ -19,13 +19,13 @@ function New-CredentialStore {
Use this switch to reset an existing store. The complete content will be wiped.
.PARAMETER SkipPFXCertCreation
You can skip the pfx certificate creation process. This makes sense if you have a previously created cert or want to
import a cert in cross-platform environments.
You can skip the pfx certificate creation process. This makes sense if you have a previously created cert
or want to import a cert in cross-platform environments.
.Parameter UseCertStore
Instead of using a plain pfx file beside your CredentialStore file you can import it into the user or machine
certificate store. In this case the system itself secures the cert and you don't hat to set custom NTFS
permissions so secure your shared certificate.
Instead of using a plain pfx file beside your CredentialStore file you can import it into the user or
machine certificate store. In this case the system itself secures the cert and you don't hat to set custom
NTFS permissions so secure your shared certificate.
.INPUTS
[None]
@ -88,7 +88,8 @@ function New-CredentialStore {
$ErrorParams = @{
ErrorAction = 'Stop'
Exception = [System.IO.InvalidDataException]::new(
'Please provide a full path containing the credential store file name with the .json extension!'
'Please provide a full path containing the ' +
'credential store file name with the .json extension!'
)
}
Write-Error @ErrorParams