diff --git a/.drone.yml b/.drone.yml index 8e876df..8cebccb 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,32 +1,46 @@ ---- -kind: pipeline -type: docker -name: Linux_PWSH7_Build - -platform: - os: linux - arch: amd64 - -steps: - - name: Environments - image: mcr.microsoft.com/powershell:latest - commands: - - pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1' -Verbose; Invoke-ShowEnv -Verbose}" - - pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1' -Verbose; Invoke-InstallDependencies -Verbose}" - - name: LintTests - image: mcr.microsoft.com/powershell:latest - commands: - - pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-InstallDependencies}" - - pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-Linter}" - - name: UnitTests - image: mcr.microsoft.com/powershell:latest - commands: - - pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-InstallDependencies}" - - pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-UnitTests}" - - name: coverage - image: plugins/codecov - settings: - token: - from_secret: CodeCovToken - files: - - coverage.xml +--- +kind: pipeline +type: docker +name: Linux_PWSH7_Build + +platform: + os: linux + arch: amd64 + +steps: + - name: Environments + image: mcr.microsoft.com/powershell:latest + commands: + - | + pwsh -NonInteractive -c "& { + Import-Module './tools/DroneIO.psm1' -Verbose; + Invoke-ShowEnv -Verbose + }" + + - name: LintTests + image: mcr.microsoft.com/powershell:latest + commands: + - | + pwsh -NonInteractive -c "& { + Import-Module './tools/DroneIO.psm1'; + Invoke-InstallDependencies; + Invoke-Linter + }" + + - name: UnitTests + image: mcr.microsoft.com/powershell:latest + commands: + - | + pwsh -NonInteractive -c "& { + Import-Module './tools/DroneIO.psm1'; + Invoke-InstallDependencies; + Invoke-UnitTest + }" + + - name: coverage + image: plugins/codecov + settings: + token: + from_secret: CodeCovToken + files: + - coverage.xml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b09ffcf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,31 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + + +[*.yml] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{.gitattributes,.gitignore,.gitkeep}] +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.gitattributes b/.gitattributes index 5520579..48c4df2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,24 @@ -src/Vendor/libressl255/* filter=lfs diff=lfs merge=lfs -text -*.pfx filter=lfs diff=lfs merge=lfs -text +# images +*.jpg binary +*.jpeg binary +*.bmp binary +*.tiff binary +*.png binary +*.svg binary +*.ico binary + +# binary files +*.exe binary +*.dll binary + +# PowerShell specific +*.ps1 working-tree-encoding=UTF-8 +*.psm1 working-tree-encoding=UTF-8 +*.psd1 working-tree-encoding=UTF-8 + +# set markdown to lf for online editing +*.md working-tree-encoding=UTF-8 + +# Vendor resources config +src/Vendor/libressl255/* filter=lfs diff=lfs merge=lfs -text +*.pfx filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 45b36c1..18af3f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,18 @@ -# Don't local track test builds -bin/PSCredentialStore.zip -bin/PSCredentialStore/* +# Don't local track test builds +bin/PSCredentialStore.zip +bin/PSCredentialStore/* + +# Basic ignore patterns +*.log +*.secret + +# data dir related prod files +data/*.csv + +# Ignore templ build artifacts +/bin/* +!bin/.gitkeep + +# Ignore Unit Test result files +coverage.xml +testResults.xml diff --git a/.vscode/cSpell.json b/.vscode/cSpell.json index 40cc042..b4e5b04 100644 --- a/.vscode/cSpell.json +++ b/.vscode/cSpell.json @@ -1,40 +1,22 @@ -// cSpell Settings -{ - // Version of the setting file. Always 0.1 - "version": "0.1", - // language - current active spelling language - "language": "en", - // words - list of words to be always considered correct - "words": [ - "Cmdlet", - "Cmdlets", - "GUID", - "Hashtable", - "Httpclient", - "Multipart", - "NTFS", - "Params", - "Ponduit", - "Repo", - "Veyor", - "appveyor", - "callsign", - "choco", - "chocolatey", - "codecoverage", - "creds", - "formdata", - "googlemail", - "notlike", - "notmatch", - "powershellgallery", - "testresults", - "wildcards" - ], - // flagWords - list of words to be always considered incorrect - // This is useful for offensive words and common spelling errors. - // For example "hte" should be "the" - "flagWords": [ - "hte" - ] -} \ No newline at end of file +// cSpell Settings +{ + // Version of the setting file. Always 0.1 + "version": "0.2", + // language - current active spelling language + "language": "en,de,de-DE", + // words - list of words to be always considered correct + "words": [], + // flagWords - list of words to be always considered incorrect + // This is useful for offensive words and common spelling errors. + // For example "hte" should be "the" + "flagWords": [], + "dictionaryDefinitions": [ + { + "name": "default", + "path": "./dictionaries/default.txt" + } + ], + "dictionaries": [ + "default" + ] +} diff --git a/.vscode/dictionaries/default.txt b/.vscode/dictionaries/default.txt new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..073c578 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + "recommendations": [ + "streetsidesoftware.code-spell-checker", + "streetsidesoftware.code-spell-checker-german", + "hediet.vscode-drawio", + "editorconfig.editorconfig", + "eamodio.gitlens", + "vscode-icons-team.vscode-icons", + "redhat.vscode-xml", + "redhat.vscode-yaml", + "ryanluker.vscode-coverage-gutters" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json index affb74a..de0c692 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -42,7 +42,7 @@ "type": "PowerShell", "request": "launch", "name": "PowerShell Interactive Session", - "cwd": "" + "cwd": "${workspaceRoot}" } ] } diff --git a/.vscode/pwsh.code-snippets b/.vscode/pwsh.code-snippets new file mode 100644 index 0000000..563cf11 --- /dev/null +++ b/.vscode/pwsh.code-snippets @@ -0,0 +1,31 @@ +{ + // Place your PowerShell-Module workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + // PSScriptAnalyzder Rule Suppression + "Rule Suppression": { + "scope": "powershell", + "prefix": "[Diag", + "description": "Suppresses Scriptanalyzer Rules", + "body": [ + "[Diagnostics.CodeAnalysis.SuppressMessageAttribute(", + " '${1|PSProvideCommentHelp,PSAvoidLongLines,PSAvoidUsingWriteHost,PSUseShouldProcessForStateChangingFunctions|}',", + " '',", + " Justification = '${justification}'", + ")]" + ] + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 39b2319..56b9a63 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,51 +1,52 @@ -// Place your settings in this file to overwrite default and user settings. -{ - // Set basic file related options: - "files.encoding": "utf8", - "files.eol": "\r\n", - "files.trimTrailingWhitespace": true, - "files.insertFinalNewline": true, - // Formation and editor options - "editor.renderWhitespace": "boundary", - "editor.formatOnSave": true, - "editor.formatOnType": true, - "editor.rulers": [ - 116 - ], - // powershell general - "powershell.startAutomatically": true, - "powershell.useX86Host": false, - "powershell.enableProfileLoading": true, - "powershell.scriptAnalysis.enable": true, - // powershell code Formatting - "powershell.codeFormatting.openBraceOnSameLine": true, - "powershell.codeFormatting.newLineAfterOpenBrace": true, - "powershell.codeFormatting.newLineAfterCloseBrace": true, - "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, - "powershell.codeFormatting.whitespaceBeforeOpenParen": true, - "powershell.codeFormatting.whitespaceAroundOperator": true, - "powershell.codeFormatting.whitespaceAfterSeparator": true, - "powershell.codeFormatting.ignoreOneLineBlock": true, - "powershell.codeFormatting.alignPropertyValuePairs": true, - "powershell.codeFormatting.preset": "Custom", - // cspell spellchecker options - "cSpell.enabledLanguageIds": [ - "c", - "cpp", - "csharp", - "go", - "javascript", - "javascriptreact", - "json", - "latex", - "markdown", - "php", - "plaintext", - "powershell", - "python", - "text", - "typescript", - "typescriptreact", - "yml" - ] -} +{ + "files.encoding": "utf8", + "files.eol": "auto", + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "editor.renderWhitespace": "boundary", + "editor.formatOnSave": true, + "editor.formatOnType": true, + "editor.rulers": [ + 116 + ], + "cSpell.enabled": true, + "cSpell.enabledLanguageIds": [ + "c", + "cpp", + "csharp", + "go", + "javascript", + "javascriptreact", + "json", + "latex", + "markdown", + "php", + "plaintext", + "powershell", + "python", + "text", + "typescript", + "typescriptreact", + "yaml", + "yml" + ], + "cSpell.language": "en,de,de-DE", + // powershell general + "powershell.startAutomatically": true, + "powershell.useX86Host": false, + "powershell.enableProfileLoading": true, + "powershell.scriptAnalysis.enable": true, + // powershell code Formatting + "powershell.codeFormatting.openBraceOnSameLine": true, + "powershell.codeFormatting.newLineAfterOpenBrace": true, + "powershell.codeFormatting.newLineAfterCloseBrace": true, + "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, + "powershell.codeFormatting.whitespaceBeforeOpenParen": true, + "powershell.codeFormatting.whitespaceAroundOperator": true, + "powershell.codeFormatting.whitespaceAfterSeparator": true, + "powershell.codeFormatting.ignoreOneLineBlock": true, + "powershell.codeFormatting.alignPropertyValuePairs": true, + "powershell.scriptAnalysis.settingsPath": "./tools/PSScriptAnalyzerSettings.psd1", + "coverage-gutters.showGutterCoverage": false, + "coverage-gutters.showLineCoverage": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d8fd688..e781fe6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,56 +1,121 @@ +// A task runner that invokes Pester to run all Pester tests under the +// current workspace folder. +// NOTE: This Test task runner requires an updated version of Pester (>=4.0.3) +// in order for the problemMatcher to find failed test information (message, line, file). +// If you don't have that version, you can update Pester from the PowerShell Gallery +// with this command: +// +// PS C:\> Update-Module Pester +// +// If that gives an error like: +// "Module 'Pester' was not installed by using Install-Module, so it cannot be updated." +// then execute: +// +// PS C:\> Install-Module Pester -Scope CurrentUser -Force +// +// NOTE: The Clean, Build and Publish tasks require PSake. PSake can be installed +// from the PowerShell Gallery with this command: +// +// PS C:\> Install-Module PSake -Scope CurrentUser -Force +// +// Available variables which can be used inside of strings: +// ${workspaceFolder} the path of the workspace folder that contains the tasks.json file +// ${workspaceFolderBasename} the name of the workspace folder that contains the tasks.json file without any slashes (/) +// ${file} the current opened file +// ${relativeFile} the current opened file relative to the workspace folder containing the file +// ${fileBasename} the current opened file's basename +// ${fileBasenameNoExtension} the current opened file's basename without the extension +// ${fileDirname} the current opened file's dirname +// ${fileExtname} the current opened file's extension +// ${cwd} the task runner's current working directory on startup +// ${lineNumber} the current selected line number in the active file { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format "version": "2.0.0", - // Start PowerShell - "windows": { - "command": "${env:windir}/System32/WindowsPowerShell/v1.0/powershell.exe", - "args": [ - "-NoProfile", - "-ExecutionPolicy", - "Bypass" - ] - }, + //"windows": { + // "options": { + // "shell": { + // // switch back to windows powershell 5.1 + // // "executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + // "executable": "pwsh.exe", + // "args": [ + // "-NoProfile", + // "-ExecutionPolicy", + // "Bypass", + // "-Command" + // ] + // } + // } + //}, "linux": { - "command": "/usr/bin/powershell", - "args": [ - "-NoProfile" - ] - }, - "osx": { - "command": "/usr/local/bin/powershell", - "args": [ - "-NoProfile" - ] + "options": { + "shell": { + "executable": "/usr/bin/pwsh", + "args": [ + "-NoProfile", + "-Command" + ] + } + } }, + //"osx": { + // "options": { + // "shell": { + // "executable": "/usr/local/bin/pwsh", + // "args": [ + // "-NoProfile", + // "-Command" + // ] + // } + // } + //}, "tasks": [ { - "taskName": "Test", - "suppressTaskName": true, - "args": [ - "Write-Host 'Invoking Pester...'; $ProgressPreference = 'SilentlyContinue'; Invoke-Pester -Script ( Get-ChildItem -Path '.\\tests\\*.Tests.ps1' -Recurse | Sort-Object -Property Name ) -EnableExit $flase -PesterOption @{IncludeVSCodeMarker=$true};", - "Invoke-Command { Write-Host 'Completed Test task in task runner.' }" + "label": "DroneIO: Invoke-Linter", + "type": "shell", + "command": [ + "Import-Module ./tools/DroneIO.psm1;", + "Invoke-Linterq | Format-Table -AutoSize" ], - "problemMatcher": "$pester", - "group": { - "kind": "test", - "isDefault": true - } + "group": "test", + "problemMatcher": [ + "$pester" + ] }, { - "taskName": "DebugBuild", - "suppressTaskName": true, - "args": [ - "Write-Host 'Invoking Build...';", - "Write-Host -Object 'Test previous builds.' -ForegroundColor Blue;", - "If (Test-Path -Path '.\\bin\\PSCredentialStore.zip') { Remove-Item -Path '.\\bin\\PSCredentialStore.zip' -Verbose};", - "Copy-Item -Path '.\\src\\' -Destination '.\\bin\\PSCredentialStore' -Recurse -Verbose -Force;", - "Compress-Archive -Path '.\\src\\*' -DestinationPath '.\\bin\\PSCredentialStore.zip' -Update -Verbose;" + "label": "DroneIO: Invoke-UnitTest", + "type": "shell", + "command": [ + "Remove-Item ./coverage.xml -ErrorAction 'SilentlyContinue';", + "Remove-Item ./testResults.xml -ErrorAction 'SilentlyContinue';", + "Import-Module ./tools/DroneIO.psm1;", + "Invoke-UnitTest -CoverageFormat 'CoverageGutters' -Verbosity 'Debug'" ], - "group": { - "kind": "build", - "isDefault": true - } + "group": "test", + "problemMatcher": [ + "$pester" + ] + }, + { + "label": "Add dictionary item", + "type": "shell", + "command": [ + "$DefaultFile = Get-ChildItem -Path './.vscode/dictionaries/default.txt';", + "$Content = Get-Content -Path $DefaultFile;", + "$Content += '${input:DictionaryItem}';", + "$Content = $Content | Sort-Object -Unique;", + "Set-Content -Value $Content -Path $DefaultFile" + ], + "group": "none", + "problemMatcher": [ + "$pester" + ] + } + ], + "inputs": [ + { + "id": "DictionaryItem", + "type": "promptString", + "description": "Input for dictionary file default.txt" } ] } diff --git a/README.md b/README.md index 864d043..d518ebb 100644 --- a/README.md +++ b/README.md @@ -1,166 +1,181 @@ -[![AppVeyor branch](https://img.shields.io/appveyor/ci/OCram85/PSCredentialStore/master.svg?style=plastic "Master Branch Build Status")](https://ci.appveyor.com/project/OCram85/pscredentialstore/branch/master) -[![AppVeyor tests branch](https://img.shields.io/appveyor/tests/OCram85/PSCredentialStore/master.svg?style=plastic "Pester Tests Results")](https://ci.appveyor.com/project/OCram85/pscredentialstore/branch/master/tests) -[![Coveralls github](https://img.shields.io/coveralls/github/OCram85/PSCredentialStore.svg?style=plastic "Coveralls.io Coverage Report")](https://coveralls.io/github/OCram85/PSCredentialStore?branch=master) -[![codecov](https://codecov.io/gh/OCram85/PSCredentialStore/branch/master/graph/badge.svg)](https://codecov.io/gh/OCram85/PSCredentialStore) -[![PowerShell Gallery](https://img.shields.io/powershellgallery/v/PSCredentialStore.svg?style=plastic "PowershellGallery Published Version")](https://www.powershellgallery.com/packages/PSCredentialStore) -[![PowerShell Gallery](https://img.shields.io/powershellgallery/vpre/PSCredentialStore.svg?label=latest%20preview&style=plastic "PowershellGallery Latest Preview Version")](https://www.powershellgallery.com/packages/PSCredentialStore) -[![PowerShell Gallery](https://img.shields.io/powershellgallery/dt/PSCredentialStore.svg?style=plastic "PowershellGallery Downloads")](https://www.powershellgallery.com/packages/PSCredentialStore) - -![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg) -![forthebadge](http://forthebadge.com/images/badges/for-you.svg) - -![social-logo](/assets/social-logo.png) - -:key: General -======= - -The PSCredentialStore is a simple credential manager for `PSCredential` objects. It stores PSCredentials in a simple json -file. You can choose between a private and shared credential store. The private one exists in your profile and can -ony accessed by your account on the same machine. The shared store enables you to use different credentials for your -scripts without exposing them as plain text. - -PSCredentialStore was developed to simplify the delegation of complex powershell scripts. In this case you often -need to store credentials for non interactive usage like in scheduled tasks. - -Starting with version `1.0.0` PSCredential uses Pfx certificates fo encryption. You can use Pfx certificate files -or certificates stored in the certificate store. - -For more details read the [about_PSCredentialStore](/docs/about_PSCredentialStore.md) page on github or via CLI with -`Get-Help about_PSCredentialStore`. - -You can find the [reference](/docs/PSCredentialStore.md) in the /docs/ path as well. - -:vulcan_salute: Requirements -============ - -- PowerShell >= `5.1` -- .NET Framework >= `4.6` or .NET Core >= `1.0` - -:bomb: About Security -============ - ->This section explains some security topics and the the design decisions we made to balance the usage and security needs. - -To be able to delegate `PSCredentials` objects we can't exclusively rely on the `SecureString` cmdlets. You can't -decrypt and reuse such credentials from a different user account or even machine. This is caused by automatically -generated encryption key which, is used create a `Secure String` based encrypted string. - -In order to delegate a password, while still using the underlying security framework, we have to provide a custom -encryption key. This leads to the fact, that everyone who has access to the key could encrypt or decrypt your data. - -So we decided to use the public and private keys from valid certificates as part of the custom encryption keys to encrypt your data. - -This means clearly: Everyone who has access to the `CredentialStore` needs also access to the certificate file to work with it. - -Keep in mind you need to secure the access with your NTFS file permissions to avoid unwanted usage. Another option is -to import the certificate into your certification vaults of you operating system. In this case you can grand the -permission to the certificates itself. - -Here is s brief hierarchy description of the certificate location: *(First match wins)* - -| CredentialStore Type | Certificate Location | -| -------------------- | ---------------------- | -| Private | `CurrentUser`\\`My` | -| Shared (Windows) | `CurrentUser`\\`My` | -| | `LocalMachine`\\`Root` | -| Shared (Linux) | `LocalMachine`\\`My` | -| | `LocalMachine`\\`Root` | - - - -:hammer_and_wrench: Installation -============ - -:artificial_satellite: PowerShellGallery.com (Recommended Way) ---------------------------------------- - -* 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` - -:building_construction: Manual Way ----------- - -* Take a look at the [Latest Release](https://github.com/OCram85/PSCredentialStore/releases/latest) page. -* Download the `PSCredentialStore.zip`. -* Unpack the zip file and put it in your Powershell module path. - * Don't forget to change the NTFS permission flag in the context menu. -* Start with `Import-Module PSCredentialStore` - -:sparkles: Quick Start ------------ - -**1.** First we need a blank credential store. You can decide between a *private* or *shared* store. The private -Credential Store can only be accessed with your profile on the machine you created it. - -Starting with version `1.0.0` you can decide the storage type of your fresh created certificate. As default -PSCredentialStore creates a new pfx certificate file beside the credential store itself. Optionally you can provide -the parameter `-UseCertStore`. This imports the new certificate in the user or machine certificate store as well. - -```powershell -# Private credential store -New-CredentialStore - -# Private credential store with certificate store usage -New-CredentialStore -UseCertStore - -# Shared credential store -New-CredentialStore -Shared - -#Shared credential store in custom location -New-CredentialStore -Shared -Path 'C:\CredentialStore.json' -``` - -**2.** Now you can manage your credential store items: -```powershell -# This will prompt for credentials and stores it in a private store -New-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD' - -# You can now use it in other scripts like this: -$DCCreds = Get-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD' -Invoke-Command -ComputerName 'dc01.myside.local' -Credential $DCCreds -ScripBlock {Get-Process} -``` - -The credential store contains also a simple function to establish a connection with several systems or protocols. -If you have already installed the underlying framework / modules, you can connect these endpoints: - -* **CiscoUcs** - Establish a connection to a Cisco UCS fabric interconnect. - * Required Modules: [`Cisco.UCS.Core`, `Cisco.UCSManager`](https://software.cisco.com/download/release.html?i=!y&mdfid=286305108&softwareid=284574017&release=2.1.1) -* **FTP** - Establish a connection to a FTP host. - * Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP) -* **NetAppFAS** - Establish a connection to a NetApp Clustered ONTAP filer. - * Required Modules: [`DataONTAP`](http://mysupport.netapp.com/tools/info/ECMLP2310788I.html?productID=61926) -* **VMware** - Establish a connection to a VMware vCenter or ESXi host. - * Required Modules: [`VMware.VimAutomation.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI) -* **CisServer** - Establish a connection to the CisServer Service on vCenter Host. - * Required Modules: [`VMware.VimAutomation.Cis.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI) -* **ExchangeHTTP** - Establish a remote connection with an Exchange endpoint via http. - * Requires PowerShell remoting -* **ExchangeHTTPS** - Establish a remote connection with an Exchange endpoint via https. - * Requires PowerShell remoting -* **SCP** - Establish a SCP connection. - * Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP) - -Here are some basic examples: - -```powershell -Connect-To -RemoteHost "ucs.myside.local" -Type CiscoUcs -Connect-To -RemoteHost "ftp.myside.local" -Type FTP -Connect-To -RemoteHost "fas.myside.local" -Type NetAppFAS -Connect-To -RemoteHost "esx01.myside.local" -Type VMware -Connect-To -RemoteHost "vcr.myside.local" -Type CisServer -Connect-To -RemoteHost "exchange1.myside.local" -Type ExchangeHTTP -Connect-To -RemoteHost "exchange1.myside.local" -Type ExchangeHTTPS -Connect-To -RemoteHost "ubuntu.myside.local" -Type SCP -``` - -:pushpin: 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 Dave Wyatt ([@dlwyatt](https://github.com/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)! +

+ + +

+ +

+ + PSCredentialStore + +

+ +

+ PSCredentialStore +

+ +

+ 🔐 A simple credential manager to store and reuse multiple PSCredential objects. +

+ +

+ + Master Branch Build Status + + + CodeCov + + + PowershellGallery Published Version + + + + + + + +

+ + +## :key: General + +The PSCredentialStore is a simple credential manager for `PSCredential` objects. It stores PSCredentials in a simple json +file. You can choose between a private and shared credential store. The private one exists in your profile and can +ony accessed by your account on the same machine. The shared store enables you to use different credentials for your +scripts without exposing them as plain text. + +PSCredentialStore was developed to simplify the delegation of complex powershell scripts. In this case you often +need to store credentials for non interactive usage like in scheduled tasks. + +Starting with version `1.0.0` PSCredential uses Pfx certificates fo encryption. You can use Pfx certificate files +or certificates stored in the certificate store. + +For more details read the [about_PSCredentialStore](/docs/about_PSCredentialStore.md) page on github or via CLI with +`Get-Help about_PSCredentialStore`. + +You can find the [reference](/docs/PSCredentialStore.md) in the /docs/ path as well. + +## :vulcan_salute: Requirements + +- PowerShell >= `5.1` +- .NET Framework >= `4.6` or .NET Core >= `1.0` + +## :bomb: About Security + +>This section explains some security topics and the the design decisions we made to balance the usage and security needs. + +To be able to delegate `PSCredentials` objects we can't exclusively rely on the `SecureString` cmdlets. You can't +decrypt and reuse such credentials from a different user account or even machine. This is caused by automatically +generated encryption key which, is used create a `Secure String` based encrypted string. + +In order to delegate a password, while still using the underlying security framework, we have to provide a custom +encryption key. This leads to the fact, that everyone who has access to the key could encrypt or decrypt your data. + +So we decided to use the public and private keys from valid certificates as part of the custom encryption keys to encrypt your data. + +This means clearly: Everyone who has access to the `CredentialStore` needs also access to the certificate file to work with it. + +Keep in mind you need to secure the access with your NTFS file permissions to avoid unwanted usage. Another option is +to import the certificate into your certification vaults of you operating system. In this case you can grand the +permission to the certificates itself. + +Here is s brief hierarchy description of the certificate location: *(First match wins)* + +| CredentialStore Type | Certificate Location | +| -------------------- | ---------------------- | +| Private | `CurrentUser`\\`My` | +| Shared (Windows) | `CurrentUser`\\`My` | +| | `LocalMachine`\\`Root` | +| Shared (Linux) | `LocalMachine`\\`My` | +| | `LocalMachine`\\`Root` | + +## :hammer_and_wrench: Installation + +### :artificial_satellite: PowerShellGallery.com (Recommended Way) + +* 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` + +### :building_construction: Manual Way + +* Take a look at the [Latest Release](https://github.com/OCram85/PSCredentialStore/releases/latest) page. +* Download the `PSCredentialStore.zip`. +* Unpack the zip file and put it in your Powershell module path. + * Don't forget to change the NTFS permission flag in the context menu. +* Start with `Import-Module PSCredentialStore` + +### :sparkles: Quick Start + +**1.** First we need a blank credential store. You can decide between a *private* or *shared* store. The private +Credential Store can only be accessed with your profile on the machine you created it. + +Starting with version `1.0.0` you can decide the storage type of your fresh created certificate. As default +PSCredentialStore creates a new pfx certificate file beside the credential store itself. Optionally you can provide +the parameter `-UseCertStore`. This imports the new certificate in the user or machine certificate store as well. + +```powershell +# Private credential store +New-CredentialStore + +# Private credential store with certificate store usage +New-CredentialStore -UseCertStore + +# Shared credential store +New-CredentialStore -Shared + +#Shared credential store in custom location +New-CredentialStore -Shared -Path 'C:\CredentialStore.json' +``` + +**2.** Now you can manage your credential store items: +```powershell +# This will prompt for credentials and stores it in a private store +New-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD' + +# You can now use it in other scripts like this: +$DCCreds = Get-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD' +Invoke-Command -ComputerName 'dc01.myside.local' -Credential $DCCreds -ScripBlock {Get-Process} +``` + +The credential store contains also a simple function to establish a connection with several systems or protocols. +If you have already installed the underlying framework / modules, you can connect these endpoints: + +* **CiscoUcs** - Establish a connection to a Cisco UCS fabric interconnect. + * Required Modules: [`Cisco.UCS.Core`, `Cisco.UCSManager`](https://software.cisco.com/download/release.html?i=!y&mdfid=286305108&softwareid=284574017&release=2.1.1) +* **FTP** - Establish a connection to a FTP host. + * Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP) +* **NetAppFAS** - Establish a connection to a NetApp Clustered ONTAP filer. + * Required Modules: [`DataONTAP`](http://mysupport.netapp.com/tools/info/ECMLP2310788I.html?productID=61926) +* **VMware** - Establish a connection to a VMware vCenter or ESXi host. + * Required Modules: [`VMware.VimAutomation.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI) +* **CisServer** - Establish a connection to the CisServer Service on vCenter Host. + * Required Modules: [`VMware.VimAutomation.Cis.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI) +* **ExchangeHTTP** - Establish a remote connection with an Exchange endpoint via http. + * Requires PowerShell remoting +* **ExchangeHTTPS** - Establish a remote connection with an Exchange endpoint via https. + * Requires PowerShell remoting +* **SCP** - Establish a SCP connection. + * Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP) + +Here are some basic examples: + +```powershell +Connect-To -RemoteHost "ucs.myside.local" -Type CiscoUcs +Connect-To -RemoteHost "ftp.myside.local" -Type FTP +Connect-To -RemoteHost "fas.myside.local" -Type NetAppFAS +Connect-To -RemoteHost "esx01.myside.local" -Type VMware +Connect-To -RemoteHost "vcr.myside.local" -Type CisServer +Connect-To -RemoteHost "exchange1.myside.local" -Type ExchangeHTTP +Connect-To -RemoteHost "exchange1.myside.local" -Type ExchangeHTTPS +Connect-To -RemoteHost "ubuntu.myside.local" -Type SCP +``` + +### :pushpin: 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 Dave Wyatt ([@dlwyatt](https://github.com/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)! diff --git a/_.travis.yml b/_.travis.yml deleted file mode 100644 index 2a043d4..0000000 --- a/_.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ - -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: ./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 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 5b9615d..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,74 +0,0 @@ -# pre release version: -version: 1.0.{build} - -#cache: - -#branches: -# only: -# - master -# - dev -# - debug - -skip_tags: true - -image: Visual Studio 2019 - -# Install pester module and init the Appveyor support. - -# Enable RDP connection for debugging -#init: -# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - -install: - - ps: Import-Module .\tools\AppVeyor.psm1 - - ps: Invoke-InstallDependencies - -environment: - NuGetToken: - secure: 835qfZIkC9mE7QhkYfOZVAdR8rZhPvxG8BO4CbeaelRQOhlqmaSr8G1DWRJzZ/bS - CoverallsToken: - secure: eTjWqHL48MBr8wp1rSgLrXHdtpfDV/uClacP3svlWJfCvn/zVokpuaMnWM5RoyIY - CodeCovToken: - secure: LJOvamWIlVORDE7120KcmWVkHxOFYBSN99linyICXXmXLtYm81K/31YeMGiPlgTm - -build: false - -before_build: - - ps: Invoke-AppVeyorBumpVersion - -build_script: - - ps: Invoke-AppVeyorBuild - -test_script: - - ps: | - $CodeCoverage = Invoke-AppVeyorTests - if ($null -ne $Env:CoverallsToken) { - Invoke-CoverageReport -PesterCoverageReport $CodeCoverage - } - else { - Write-Warning "No CoverallsToken found. This build seems to be triggered by a PR. Skipping this step..." - } - -deploy: - #- provider: GitHub - # auth_token: - # secure: M+bBX5/nKdJB0eViP7xtrLVTwf3vGDUA9N2MMprZp2i+9ZR3CBVcJnSzJWUmalhB - # artifact: PSCredentialStore.zip # upload all NuGet packages to release assets - # draft: true - # prerelease: true - # on: - # branch: dev - - provider: GitHub - auth_token: - secure: M+bBX5/nKdJB0eViP7xtrLVTwf3vGDUA9N2MMprZp2i+9ZR3CBVcJnSzJWUmalhB - artifact: PSCredentialStore.zip # upload all NuGet packages to release assets - draft: false - prerelease: false - on: - branch: master # build release on master branch changes - -after_deploy: - - ps: Invoke-AppVeyorPSGallery -OnBranch 'master' -# Pause build until `lock` on desktop is deleted. -#on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/src/Certificate/Get-CSCertificate.ps1 b/src/Certificate/Get-CSCertificate.ps1 index 5bb654b..7db89f1 100644 --- a/src/Certificate/Get-CSCertificate.ps1 +++ b/src/Certificate/Get-CSCertificate.ps1 @@ -20,18 +20,11 @@ function Get-CSCertificate { .EXAMPLE Get-CSCertificate -Type 'Shared' -Thumbprint '12334456' - - .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( + param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Private', 'Shared')] @@ -42,8 +35,8 @@ function Get-CSCertificate { [string]$Thumbprint ) - begin { - } + begin {} + process { if ($Type -eq 'Private') { Get-CSPfXCertificate -Thumbprint $Thumbprint -StoreName 'My' -StoreLocation 'CurrentUser' @@ -69,6 +62,5 @@ function Get-CSCertificate { } } } - end { - } + end {} } diff --git a/src/Certificate/Import-CSCertificate.ps1 b/src/Certificate/Import-CSCertificate.ps1 index 244eb63..fc391c2 100644 --- a/src/Certificate/Import-CSCertificate.ps1 +++ b/src/Certificate/Import-CSCertificate.ps1 @@ -21,18 +21,10 @@ function Import-CSCertificate { .EXAMPLE Import-CSCertificate -Type 'Private' -Path (Join-Path -Path $Env:APPDATA -ChildItem 'PfxCertificate.pfx') - - .NOTES - - File Name : Import-CSCertificate.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding()] - [OutputType()] - param( + param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Private', 'Shared')] diff --git a/src/Certificate/New-CSCertAttribute.ps1 b/src/Certificate/New-CSCertAttribute.ps1 index e199a83..ab77fd6 100644 --- a/src/Certificate/New-CSCertAttribute.ps1 +++ b/src/Certificate/New-CSCertAttribute.ps1 @@ -35,18 +35,11 @@ function New-CSCertAttribute { .EXAMPLE New-CSCertAttribute -Country 'DE' -State 'BW' -City 'Karlsruhe' -Organization 'AwesomeIT' -OrganizationalUnitName '' -CommonName 'MyPrivateCert' - - .NOTES - - File Name : New-CSCertAttribute.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding()] [OutputType('PSCredentialStore.Certificate.Attribute')] - param( + param ( [Parameter(Mandatory = $true)] [ValidateLength(2, 2)] [ValidateNotNull()] @@ -76,9 +69,8 @@ function New-CSCertAttribute { [ValidateNotNull()] [int]$Days = 365 ) - begin { + begin {} - } process { return [PSCustomObject]@{ PSTypeName = 'PSCredentialStore.Certificate.Attribute' @@ -94,6 +86,5 @@ function New-CSCertAttribute { Days = $Days } } - end { - } + end {} } diff --git a/src/Certificate/New-CSCertificate.ps1 b/src/Certificate/New-CSCertificate.ps1 index 91d5554..6e93ef0 100644 --- a/src/Certificate/New-CSCertificate.ps1 +++ b/src/Certificate/New-CSCertificate.ps1 @@ -23,18 +23,11 @@ function New-CSCertificate { .EXAMPLE New-CSCertificate -CRTAttribute $CRTAttribute -KeyName './myprivate.key' -CertName './mycert.pfx' - - .NOTES - - File Name : New-CSCertificate.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding(SupportsShouldProcess = $true)] [OutputType()] - param( + param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [PSTypeName('PSCredentialStore.Certificate.Attribute')]$CRTAttribute, @@ -70,6 +63,7 @@ function New-CSCertificate { $Env:OPENSSL_CONF = Join-Path $ModuleBase -ChildPath '/openssl.conf' } + process { $SubjPattern = "/C={0}/ST={1}/L={2}/O={3}/OU={4}/CN={5}" $SubjValues = @( diff --git a/src/Certificate/Test-CSCertificate.ps1 b/src/Certificate/Test-CSCertificate.ps1 index 4ef34f6..ed9b45f 100644 --- a/src/Certificate/Test-CSCertificate.ps1 +++ b/src/Certificate/Test-CSCertificate.ps1 @@ -17,18 +17,11 @@ function Test-CSCertificate { .EXAMPLE Test-CSCertificate -Type 'Shared' - - .NOTES - - File Name : Test-CSCertificate.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding()] [OutputType([bool])] - param( + param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Private', 'Shared')] diff --git a/src/Certificate/Use-CSCertificate.ps1 b/src/Certificate/Use-CSCertificate.ps1 index 76f0f40..0bd993b 100644 --- a/src/Certificate/Use-CSCertificate.ps1 +++ b/src/Certificate/Use-CSCertificate.ps1 @@ -26,36 +26,28 @@ function Use-CSCertificate { .EXAMPLE Use-CSCertificate -Path 'C:\cert.pfx' - - .NOTES - File Name : Use-CSCertificate.ps1 - Author : Marco Blessing - marco.blessing@googlemail.com - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - [OutputType()] + + [CmdletBinding(DefaultParameterSetName = 'Private')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Private")] - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$Path, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$CredentialStore, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $false, ParameterSetName = "Private")] - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Switch]$UseCertStore + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [switch]$UseCertStore ) - begin { } + begin {} process { try { @@ -74,11 +66,11 @@ function Use-CSCertificate { } try { - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $StorePath = Get-DefaultCredentialStorePath $CS = Get-CredentialStore } - elseif ($PSCmdlet.ParameterSetName -eq "Shared" ) { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared' ) { if (!($PSBoundParameters.ContainsKey('CredentialStore'))) { $StorePath = Get-DefaultCredentialStorePath -Shared $CS = Get-CredentialStore -Shared @@ -117,5 +109,5 @@ Make sure you used the same AES keys for encrypting! $CS | ConvertTo-Json -Depth 5 | Out-File -FilePath $StorePath -Force -Encoding utf8 } - end { } + end {} } diff --git a/src/Connection/Connect-To.ps1 b/src/Connection/Connect-To.ps1 index b7e1abb..815cd08 100644 --- a/src/Connection/Connect-To.ps1 +++ b/src/Connection/Connect-To.ps1 @@ -58,28 +58,20 @@ function Connect-To { .EXAMPLE Connect-To -RemoteHost "exchange01.myside.local" -Type ExchangeHTTPS - - .NOTES - - File Name : Connect-To.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] - [Parameter(Mandatory = $true, ParameterSetName = "Private")] + [CmdletBinding(DefaultParameterSetName = 'Private')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] [string]$RemoteHost, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Parameter(Mandatory = $false, ParameterSetName = "Private")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] [string]$Identifier, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] - [Parameter(Mandatory = $true, ParameterSetName = "Private")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] [ValidateSet( 'CiscoUcs', 'FTP', @@ -92,29 +84,29 @@ function Connect-To { )] [string]$Type, - [Parameter(Mandatory = $False, ParameterSetName = "Shared")] - [Parameter(Mandatory = $False, ParameterSetName = "Private")] + [Parameter(Mandatory = $False, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $False, ParameterSetName = 'Private')] [PSCredential]$Credentials, - [Parameter(Mandatory = $true, ParameterSetNAme = "Shared")] + [Parameter(Mandatory = $true, ParameterSetNAme = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $False, ParameterSetName = "Shared")] + [Parameter(Mandatory = $False, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$Path, - [Parameter(Mandatory = $False, ParameterSetName = "Private")] - [Parameter(Mandatory = $False, ParameterSetName = "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") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -155,7 +147,7 @@ function Connect-To { catch { $MessageParams = @{ Message = "Unable to look up credential store item for RemoteHost {0}/Identifier {1}!" -f $RemoteHost, $Identifier - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -164,10 +156,10 @@ function Connect-To { $creds = $Credentials } - if ($creds.UserName -eq "" -or $creds.Password.GetType().Name -ne "SecureString") { + if ($creds.UserName -eq "" -or $creds.Password.GetType().Name -ne 'SecureString') { $MessageParams = @{ Message = "Please provide valid credentials for RemoteHost {0}!" -f $RemoteHost - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -176,13 +168,13 @@ function Connect-To { "CiscoUcs" { try { $handle = Connect-Ucs -Name $RemoteHost -Credential $creds -ErrorAction Stop - $ExecutionContext.SessionState.PSVariable.Set("DefaultUcs", $handle) + $ExecutionContext.SessionState.PSVariable.Set('DefaultUcs', $handle) } catch { $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -207,7 +199,7 @@ function Connect-To { # 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 - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -221,7 +213,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -235,7 +227,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -255,7 +247,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -274,7 +266,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -293,7 +285,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -314,7 +306,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -323,7 +315,7 @@ function Connect-To { # 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 - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -332,7 +324,7 @@ function Connect-To { # Write a error message to the log. $MessageParams = @{ Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } diff --git a/src/Connection/Disconnect-From.ps1 b/src/Connection/Disconnect-From.ps1 index 57139b9..509ef4b 100644 --- a/src/Connection/Disconnect-From.ps1 +++ b/src/Connection/Disconnect-From.ps1 @@ -49,18 +49,10 @@ function Disconnect-From { .EXAMPLE Disconnect-From -RemoteHost "exchange01.myside.local" -Type ExchangeHTTPS - - .NOTES - - File Name : Disconnect-From.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> [CmdletBinding()] - param( + param ( [Parameter(Mandatory = $true)] [string]$RemoteHost, @@ -81,126 +73,132 @@ function Disconnect-From { [switch]$Force ) - switch -Regex ($Type) { - "VMware" { - try { - if ($Force) { - Disconnect-VIServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop -Force:$true + begin {} + + process { + switch -Regex ($Type) { + "VMware" { + try { + if ($Force) { + Disconnect-VIServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop -Force:$true + } + else { + Disconnect-VIServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop + } + } + + catch { + # Write a error message to the log. + $MessageParams = @{ + Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type + ErrorAction = 'Stop' + } + Write-Error @MessageParams + } + } + "CisServer" { + try { + if ($Force) { + Disconnect-CisServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop -Force:$true + } + else { + Disconnect-CisServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop + } + } + + catch { + # Write a error message to the log. + $MessageParams = @{ + Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type + ErrorAction = 'Stop' + } + Write-Error @MessageParams + } + } + # Check for an existing WinSCP Session var + "FTP" { + if ($Global:WinSCPSession.Opened) { + Remove-WinSCPSession -WinSCPSession $Global:WinSCPSession } else { - Disconnect-VIServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop + $MessageParams = @{ + Message = 'There is no open WinSCP Session' + ErrorAction = 'Stop' + } + Write-Error @MessageParams } } + # DataONTAP doesn't have a CmdLet `Disconnect-NcController`. + # So we go ahead and clear the CurrentNcController variable. + "NetAppFAS" { + try { + $MessageParams = @{ + Message = "Setting {0} to `$null, which will disconnect NetAppFAS" -f $Global:CurrentNcController + ErrorAction = 'Continue' + } + Write-Verbose @MessageParams + $Global:CurrentNcController = $null + } - catch { - # Write a error message to the log. - $MessageParams = @{ - Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + catch { + # Write a error message to the log. + $MessageParams = @{ + Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type + ErrorAction = 'Stop' + } + Write-Error @MessageParams } - Write-Error @MessageParams + } - } - "CisServer" { - try { - if ($Force) { - Disconnect-CisServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop -Force:$true + "CiscoUcs" { + try { + Disconnect-Ucs -Ucs $RemoteHost + } + + catch { + # Write a error message to the log. + $MessageParams = @{ + Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type + ErrorAction = 'Stop' + } + Write-Error @MessageParams + } + } + "ExchangeHTTP*" { + try { + Get-Variable -Name 'PSExchangeRemote' -Scope Global -ErrorAction Stop + Remove-PSSession -Session $Global:PSExchangeRemote -ErrorAction Stop + } + catch { + $MessageParams = @{ + Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type + ErrorAction = 'Stop' + } + Write-Error @MessageParams + } + } + "SCP" { + if ($Global:WinSCPSession.Opened) { + Remove-WinSCPSession -WinSCPSession $Global:WinSCPSession } else { - Disconnect-CisServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop + $MessageParams = @{ + Message = 'There is no open WinSCP Session' + ErrorAction = 'Stop' + } + Write-Error @MessageParams } } - - catch { + default { # Write a error message to the log. $MessageParams = @{ Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" + ErrorAction = 'Stop' } Write-Error @MessageParams } } - # Check for an existing WinSCP Session var - "FTP" { - if ($Global:WinSCPSession.Opened) { - Remove-WinSCPSession -WinSCPSession $Global:WinSCPSession - } - else { - $MessageParams = @{ - Message = "There is no open WinSCP Session" - ErrorAction = "Stop" - } - Write-Error @MessageParams - } - } - # DataONTAP doesn't have a CmdLet `Disconnect-NcController`. - # So we go ahead and clear the CurrentNcController variable. - "NetAppFAS" { - try { - $MessageParams = @{ - Message = "Setting {0} to `$null, which will disconnect NetAppFAS" -f $Global:CurrentNcController - ErrorAction = "Continue" - } - Write-Verbose @MessageParams - $Global:CurrentNcController = $null - } - - catch { - # Write a error message to the log. - $MessageParams = @{ - Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" - } - Write-Error @MessageParams - } - - } - "CiscoUcs" { - try { - Disconnect-Ucs -Ucs $RemoteHost - } - - catch { - # Write a error message to the log. - $MessageParams = @{ - Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" - } - Write-Error @MessageParams - } - } - "ExchangeHTTP*" { - try { - Get-Variable -Name 'PSExchangeRemote' -Scope Global -ErrorAction Stop - Remove-PSSession -Session $Global:PSExchangeRemote -ErrorAction Stop - } - catch { - $MessageParams = @{ - Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" - } - Write-Error @MessageParams - } - } - "SCP" { - if ($Global:WinSCPSession.Opened) { - Remove-WinSCPSession -WinSCPSession $Global:WinSCPSession - } - else { - $MessageParams = @{ - Message = "There is no open WinSCP Session" - ErrorAction = "Stop" - } - Write-Error @MessageParams - } - } - default { - # Write a error message to the log. - $MessageParams = @{ - Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type - ErrorAction = "Stop" - } - Write-Error @MessageParams - } } + + end {} } diff --git a/src/Connection/Test-CSConnection.ps1 b/src/Connection/Test-CSConnection.ps1 index 08b483e..f33f14f 100644 --- a/src/Connection/Test-CSConnection.ps1 +++ b/src/Connection/Test-CSConnection.ps1 @@ -21,24 +21,16 @@ function Test-CSConnection { .EXAMPLE Test-CMConnection -RemoteHost "vcr01.internal.net" -Type VMware - - .NOTES - - File Name : Test-CSConnection.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> [CmdletBinding()] [OutputType([bool])] - param( + param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$RemoteHost, - [Parameter(Mandatory = $True)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet("CiscoUcs", "FTP", "NetAppFAS", "VMware")] [string]$Type diff --git a/src/Item/Get-CredentialStoreItem.ps1 b/src/Item/Get-CredentialStoreItem.ps1 index bf32e1a..db0e63f 100644 --- a/src/Item/Get-CredentialStoreItem.ps1 +++ b/src/Item/Get-CredentialStoreItem.ps1 @@ -29,33 +29,25 @@ function Get-CredentialStoreItem { .EXAMPLE $myCreds = Get-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" - - .NOTES - - File Name : Get-CredentialStoreItem.ps1 - - Author : Messing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] + [CmdletBinding(DefaultParameterSetName = 'Private')] [OutputType([PSCredential])] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] - [Parameter(Mandatory = $true, ParameterSetName = "Private")] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] [ValidateNotNullOrEmpty()] [string]$RemoteHost, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Parameter(Mandatory = $false, ParameterSetName = "Private")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] [ValidateNotNullOrEmpty()] [string]$Identifier, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$Path ) @@ -63,10 +55,10 @@ function Get-CredentialStoreItem { begin { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -85,7 +77,7 @@ function Get-CredentialStoreItem { $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 -contains $CredentialName)) { + if (($CSMembers.MemberType -eq 'NoteProperty') -and ($CSMembers.Name -contains $CredentialName)) { if ($null -eq $CS.PfxCertificate) { $Cert = Get-CSCertificate -Type $CS.Type -Thumbprint $CS.Thumbprint } @@ -106,16 +98,16 @@ function Get-CredentialStoreItem { } else { $MsgParams = @{ - ErrorAction = "Stop" - Message = "Could not find credentials for the given remote host: {0}" -f $RemoteHost + ErrorAction = 'Stop' + Message = 'Could not find credentials for the given remote host: {0}' -f $RemoteHost } Write-Error @MsgParams } } else { $MsgParams = @{ - ErrorAction = "Stop" - Message = "The given credential store ({0}) does not exist!" -f $Path + ErrorAction = 'Stop' + Message = 'The given credential store ({0}) does not exist!' -f $Path } Write-Error @MsgParams } diff --git a/src/Item/New-CredentialStoreItem.ps1 b/src/Item/New-CredentialStoreItem.ps1 index a95c2d4..a01d417 100644 --- a/src/Item/New-CredentialStoreItem.ps1 +++ b/src/Item/New-CredentialStoreItem.ps1 @@ -33,25 +33,17 @@ function New-CredentialStoreItem { .EXAMPLE New-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" - - .NOTES - - File Name : New-CredentialStoreItem.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] - [Parameter(Mandatory = $true, ParameterSetName = "Private")] + [CmdletBinding(DefaultParameterSetName = 'Private')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] [ValidateNotNullOrEmpty()] [string]$RemoteHost, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Parameter(Mandatory = $false, ParameterSetName = "Private")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] [ValidateNotNullOrEmpty()] [string]$Identifier, @@ -59,10 +51,10 @@ function New-CredentialStoreItem { [ValidateNotNullOrEmpty()] [PSCredential]$Credential, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$Path @@ -72,10 +64,10 @@ function New-CredentialStoreItem { begin { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -96,7 +88,7 @@ function New-CredentialStoreItem { $CSContent = Get-CredentialStore -Shared -Path $Path - $CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" + $CurrentDate = Get-Date -Format 'u' if ($Identifier -ne "") { $CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost @@ -119,7 +111,7 @@ function New-CredentialStoreItem { if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) { $MessageParams = @{ - Message = "The given host already exists. Nothing to do here." + Message = 'The given host already exists. Nothing to do here.' } Write-Warning @MessageParams } @@ -139,8 +131,8 @@ function New-CredentialStoreItem { } catch { $MessageParams = @{ - Message = "Couldn't add item into credential store!" - ErrorAction = "Stop" + Message = 'Could not add item into credential store!' + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -148,15 +140,13 @@ function New-CredentialStoreItem { } else { $MessageParams = @{ - Message = "Please Provide at least a valid user!" - ErrorAction = "Stop" + Message = 'Please Provide at least a valid user!' + ErrorAction = 'Stop' } Write-Error @MessageParams } } - end { - - } + end {} } diff --git a/src/Item/Remove-CredentialStoreItem.ps1 b/src/Item/Remove-CredentialStoreItem.ps1 index f3296b7..253d501 100644 --- a/src/Item/Remove-CredentialStoreItem.ps1 +++ b/src/Item/Remove-CredentialStoreItem.ps1 @@ -37,30 +37,22 @@ function Remove-CredentialStoreItem { .EXAMPLE Remove-CredentialStoreItem -RemoteHost "esx01.myside.local" -Identifier svc - - .NOTES - - File Name : Remove-CredentialStoreItem.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Private")] - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [CmdletBinding(DefaultParameterSetName = 'Private')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [string]$RemoteHost, - [Parameter(Mandatory = $false, ParameterSetName = "Private")] - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [string]$Identifier, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$Path ) @@ -68,10 +60,10 @@ function Remove-CredentialStoreItem { begin { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -82,8 +74,8 @@ function Remove-CredentialStoreItem { # Lets do a quick test on the given CredentialStore. if (-not(Test-CredentialStore -Shared -Path $Path)) { $MessageParams = @{ - Message = "Could not add anything into the given CredentialStore." - ErrorAction = "Stop" + Message = 'Could not add anything into the given CredentialStore.' + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -105,7 +97,7 @@ function Remove-CredentialStoreItem { } else { $MessageParams = @{ - Message = "The given CredentialStoreItem does not exist." + Message = 'The given CredentialStoreItem does not exist.' } Write-Warning @MessageParams } diff --git a/src/Item/Set-CredentialStoreItem.ps1 b/src/Item/Set-CredentialStoreItem.ps1 index 3194d58..73c87cf 100644 --- a/src/Item/Set-CredentialStoreItem.ps1 +++ b/src/Item/Set-CredentialStoreItem.ps1 @@ -34,34 +34,26 @@ function Set-CredentialStoreItem { .EXAMPLE Set-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" -Identifier svc - - .NOTES - - File Name : Set-CredentialStoreItem.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Private")] - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [CmdletBinding(DefaultParameterSetName = 'Private')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Private')] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [string]$RemoteHost, - [Parameter(Mandatory = $false, ParameterSetName = "Private")] - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [string]$Identifier, [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [PSCredential]$Credential, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [string]$Path ) @@ -69,10 +61,10 @@ function Set-CredentialStoreItem { begin { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -83,8 +75,8 @@ function Set-CredentialStoreItem { # Lets do a quick test on the given CredentialStore. if (-not(Test-CredentialStore -Shared -Path $Path)) { $MessageParams = @{ - Message = "Could not add anything into the given CredentailStore." - ErrorAction = "Stop" + Message = 'Could not add anything into the given CredentailStore.' + ErrorAction = 'Stop' } Write-Error @MessageParams } @@ -92,7 +84,7 @@ function Set-CredentialStoreItem { # Read the file content based on the given ParameterSetName $CSContent = Get-CredentialStore -Shared -Path $Path - $CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" + $CurrentDate = Get-Date -Format 'u' if ($Identifier -ne "") { $CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost @@ -129,8 +121,8 @@ function Set-CredentialStoreItem { } Else { $MessageParams = @{ - Message = "Please Provide at least a valid user!" - ErrorAction = "Stop" + Message = 'Please Provide at least a valid user!' + ErrorAction = 'Stop' } Write-Error @MessageParams } diff --git a/src/Item/Test-CredentialStoreItem.ps1 b/src/Item/Test-CredentialStoreItem.ps1 index a248f0e..d516f6f 100644 --- a/src/Item/Test-CredentialStoreItem.ps1 +++ b/src/Item/Test-CredentialStoreItem.ps1 @@ -29,25 +29,18 @@ function Test-CredentialStoreItem { [None] .EXAMPLE - If (Test-CredentialStoreItem -RemoteHost "Default") { + if (Test-CredentialStoreItem -RemoteHost "Default") { Get-CredentialStoreItem -RemoteHost "Default" } - Else { + else { Write-Warning ("The given Remote Host {0} does not exist in the credential Store!" -f $RemoteHost) } - - .NOTES - - File Name : Test-CredentialStoreItem.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - [OutputType([Boolean])] - param( - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + + [CmdletBinding(DefaultParameterSetName = 'Private')] + [OutputType([bool])] + param ( + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData, [Parameter(Mandatory = $true)] @@ -58,17 +51,17 @@ function Test-CredentialStoreItem { [ValidateNotNullOrEmpty()] [string]$Identifier, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [switch]$Shared ) begin { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -86,7 +79,7 @@ function Test-CredentialStoreItem { 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 -contains $CredentialName)) { + if (($CSMembers.MemberType -eq 'NoteProperty') -and ($CSMembers.Name -contains $CredentialName)) { return $true } else { @@ -95,15 +88,13 @@ function Test-CredentialStoreItem { } else { $MsgParams = @{ - ErrorAction = "Stop" + ErrorAction = 'Stop' Message = "The given credential store ({0}) does not exist!" -f $Path } Write-Error @MsgParams } } - end { - - } + end {} } diff --git a/src/PSCredentialStore.psd1 b/src/PSCredentialStore.psd1 index e77283e..6947b23 100644 --- a/src/PSCredentialStore.psd1 +++ b/src/PSCredentialStore.psd1 @@ -19,7 +19,7 @@ CompanyName = '' # Copyright statement for this module - Copyright = '(c) 2020 OCram85. All rights reserved.' + Copyright = '(c) 2022 OCram85. All rights reserved.' # Description of the functionality provided by this module Description = 'A simple credential manager to store and reuse multiple credential objects.' diff --git a/src/PSCredentialStore.psm1 b/src/PSCredentialStore.psm1 index 21ddd38..978d81d 100644 --- a/src/PSCredentialStore.psm1 +++ b/src/PSCredentialStore.psm1 @@ -3,8 +3,6 @@ #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. diff --git a/src/PSModule.Tests.ps1 b/src/PSModule.Tests.ps1 new file mode 100644 index 0000000..2338087 --- /dev/null +++ b/src/PSModule.Tests.ps1 @@ -0,0 +1,14 @@ +Describe 'Test module meta' { + It 'Test manifest file' { + $ManifestFile = (Get-Item -Path "./src/*.psd1").FullName + Test-ModuleManifest -Path $ManifestFile | Should -Be $true + } + It 'Import Module' { + $ManifestFile = (Get-Item -Path "./src/*.psd1").FullName + { Import-Module $ManifestFile } | Should -Not -Throw + } + # Dummy test to force pester error + #It 'Force Pester Error' { + # $true | Should -BeFalse + #} +} diff --git a/src/Private/Get-CSPfxCertificate.ps1 b/src/Private/Get-CSPfxCertificate.ps1 index 9afe659..e3e384b 100644 --- a/src/Private/Get-CSPfxCertificate.ps1 +++ b/src/Private/Get-CSPfxCertificate.ps1 @@ -23,18 +23,11 @@ function Get-CSPfxCertificate { .EXAMPLE Get-CSPfxCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser' - - .NOTES - - File Name : Get-CSPfxCertificate.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding()] [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])] - param( + param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string[]]$Thumbprint, diff --git a/src/Private/Get-DefaultCredentialStorePath.ps1 b/src/Private/Get-DefaultCredentialStorePath.ps1 index 2ee5dc5..f235ce3 100644 --- a/src/Private/Get-DefaultCredentialStorePath.ps1 +++ b/src/Private/Get-DefaultCredentialStorePath.ps1 @@ -14,23 +14,16 @@ function Get-DefaultCredentialStorePath { .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( + param ( [Parameter(Mandatory = $false)] [switch]$Shared ) - begin { } + begin {} process { if ($Shared.IsPresent) { @@ -57,5 +50,5 @@ function Get-DefaultCredentialStorePath { } } - end { } + end {} } diff --git a/src/Private/Get-ModuleBase.ps1 b/src/Private/Get-ModuleBase.ps1 index acb2451..9f8392c 100644 --- a/src/Private/Get-ModuleBase.ps1 +++ b/src/Private/Get-ModuleBase.ps1 @@ -6,24 +6,16 @@ function Get-ModuleBase { .DESCRIPTION This is just a wrapper for enabling pester tests. - .OUTPUTS Returns the base path as string + #> - .NOTES - - File Name : Get-ModuleBase.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore -#> [CmdletBinding()] - [OutputType()] - param() - begin { } + [OutputType([string])] + param () + begin {} process { return $MyInvocation.MyCommand.Module.ModuleBase } - end { } + end {} } diff --git a/src/Private/Get-RandomAESKey.ps1 b/src/Private/Get-RandomAESKey.ps1 index aff07b5..868300d 100644 --- a/src/Private/Get-RandomAESKey.ps1 +++ b/src/Private/Get-RandomAESKey.ps1 @@ -14,21 +14,13 @@ function Get-RandomAESKey { .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() + param () - begin { } + begin {} process { $key = [byte[]]::new(32) @@ -40,5 +32,5 @@ function Get-RandomAESKey { } } - end { } + end {} } diff --git a/src/Private/Get-TempDir.ps1 b/src/Private/Get-TempDir.ps1 index b3db4d9..59a7311 100644 --- a/src/Private/Get-TempDir.ps1 +++ b/src/Private/Get-TempDir.ps1 @@ -13,21 +13,14 @@ function Get-TempDir { .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 { + param () + + begin {} - } process { if ($IsLinux) { return (Resolve-Path -Path '/tmp/').Path @@ -35,10 +28,14 @@ function Get-TempDir { if ($IsMacOS) { return (Resolve-Path -Path '/tmp/').Path } - 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 (Resolve-Path -Path $env:TEMP).Path } } - end { - } + + end {} } diff --git a/src/Private/Import-CSPfxCertificate.ps1 b/src/Private/Import-CSPfxCertificate.ps1 index b261c49..f1decc3 100644 --- a/src/Private/Import-CSPfxCertificate.ps1 +++ b/src/Private/Import-CSPfxCertificate.ps1 @@ -22,18 +22,10 @@ function Import-CSPfxCertificate { .EXAMPLE Import-CSPfxCertificate -Path (Join-Path -Path $Env:APPDATA -ChildPath '/PSCredentialStore.pfx') - - .NOTES - File Name : Import-CSPfxCertificate.ps1 - Author : Marco Blessing - marco.blessing@googlemail.com - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding()] - [OutputType()] - param( + param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Path, @@ -68,6 +60,7 @@ function Import-CSPfxCertificate { )] [string]$OpenFlags = 'ReadWrite' ) + begin { $Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation) try { @@ -77,6 +70,7 @@ function Import-CSPfxCertificate { $_.Exception.Message | Write-Error -ErrorAction Stop } } + process { try { $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new( diff --git a/src/Private/Resolve-Dependency.ps1 b/src/Private/Resolve-Dependency.ps1 index 4b82922..8b7cc77 100644 --- a/src/Private/Resolve-Dependency.ps1 +++ b/src/Private/Resolve-Dependency.ps1 @@ -38,15 +38,8 @@ function Resolve-Dependency { If (-not (Resolve-Dependency -Name 'VMware')) { Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f 'VMware') -ErrorAction 'Stop' } - - .NOTES - - File Name : ResolveDependency.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [OutputType([bool])] [CmdletBinding()] param ( @@ -86,6 +79,5 @@ function Resolve-Dependency { } } - end { - } + end {} } diff --git a/src/Private/Test-CSPfxCertificate.ps1 b/src/Private/Test-CSPfxCertificate.ps1 index d03fdf5..64c427b 100644 --- a/src/Private/Test-CSPfxCertificate.ps1 +++ b/src/Private/Test-CSPfxCertificate.ps1 @@ -23,18 +23,11 @@ function Test-CSPfxCertificate { .EXAMPLE Test-CSPfxCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser' - - .NOTES - File Name : Test-CSPfxCertificate.ps1 - Author : Marco Blessing - marco.blessing@googlemail.com - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [CmdletBinding()] [OutputType([bool])] - param( + param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string]$Thumbprint, diff --git a/src/Private/Test-Module.ps1 b/src/Private/Test-Module.ps1 index ab68198..67cbba1 100644 --- a/src/Private/Test-Module.ps1 +++ b/src/Private/Test-Module.ps1 @@ -32,18 +32,11 @@ function Test-Module { .EXAMPLE .\Test-Dependency -Name 'VMware.PowerCLI' -Type 'Module' -StopIfFails - - .NOTES - - File Name : Test-Module.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> + [OutputType([bool])] [CmdletBinding()] - param( + param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Name, @@ -56,7 +49,8 @@ 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 @@ -73,5 +67,5 @@ Could not find the required {0} called {1}. Please install the required {0} to r } } - end { } + end {} } diff --git a/src/Store/Get-CredentialStore.ps1 b/src/Store/Get-CredentialStore.ps1 index a30de5f..9966875 100644 --- a/src/Store/Get-CredentialStore.ps1 +++ b/src/Store/Get-CredentialStore.ps1 @@ -23,35 +23,28 @@ function Get-CredentialStore { .EXAMPLE $CSContent = Get-CredentialStore -Path "C:\TMP\mystore.json" - - .NOTES - - File Name : Get-CredentialStore.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - [OutputType("PSCredentialStore.Store")] - param( - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [CmdletBinding(DefaultParameterSetName = 'Private')] + [OutputType('PSCredentialStore.Store')] + param ( + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [string]$Path, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared ) - begin { } + begin {} process { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -61,26 +54,26 @@ function Get-CredentialStore { try { $FileContent = Get-Content -Path $Path -Raw $CS = ConvertFrom-Json $FileContent - $CS.PSObject.TypeNames.Insert(0, "PSCredentialStore.Store") - return $CS + $CS.PSObject.TypeNames.Insert(0, 'PSCredentialStore.Store') + Write-Output $CS } catch [System.Exception] { $MessageParams = @{ - Message = "Unknown CredentialStore format. Invalid JSON file." - ErrorAction = "Stop" + Message = 'Unknown CredentialStore format. Invalid JSON file.' + ErrorAction = 'Stop' } Write-Error @MessageParams } } else { $MessageParams = @{ - Message = "Could not find the CredentialStore." - ErrorAction = "Stop" + Message = 'Could not find the CredentialStore.' + ErrorAction = 'Stop' } Write-Error @MessageParams } } - end { } + end {} } diff --git a/src/Store/New-CredentialStore.ps1 b/src/Store/New-CredentialStore.ps1 index cfa1ce2..d18433a 100644 --- a/src/Store/New-CredentialStore.ps1 +++ b/src/Store/New-CredentialStore.ps1 @@ -49,49 +49,38 @@ function New-CredentialStore { .EXAMPLE New-CredentialStore -Shared -Path "C:\TMP\CredentialStore.json" # Creates a new shared CredentialStore in the given location. - - .NOTES - - File Name : New-CredentialStore.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = "Private")] - [OutputType("PSCredentialStore.Store")] - param( - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Private')] + [OutputType('PSCredentialStore.Store')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared, - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [ValidateNotNullOrEmpty()] [System.IO.FileInfo]$Path, - [Parameter(Mandatory = $false, ParameterSetName = "Private")] - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Switch]$Force, + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [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]$PassThru, - [Parameter(Mandatory = $false, ParameterSetName = "Private")] - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Switch]$SkipPFXCertCreation, + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [switch]$SkipPFXCertCreation, - [Parameter(Mandatory = $false, ParameterSetName = "Private")] - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] - [Switch]$UseCertStore + [Parameter(Mandatory = $false, ParameterSetName = 'Private')] + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] + [switch]$UseCertStore ) 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 "2.0.0" -Option Constant -Scope + $CurrentDate = Get-Date -Format 'u' # test if the path input is a valid file path if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Path')) { @@ -108,7 +97,7 @@ function New-CredentialStore { $ErrorParams = @{ ErrorAction = 'Stop' Exception = [System.IO.InvalidDataException]::new( - 'Your provided path does not contain the required file extension .json !' + 'Your provided path does not contain the required file extension .json!' ) } Write-Error @ErrorParams @@ -119,17 +108,17 @@ function New-CredentialStore { process { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } } # Test if in the CredentialStore already exists. - Write-Verbose "Test if there is already a credential store." + Write-Verbose 'Test if there is already a credential store.' if ((Test-Path -Path $Path) -and ($Force -ne $true)) { $ErrorParams = @{ ErrorAction = 'Stop' @@ -211,11 +200,11 @@ function New-CredentialStore { Type = $null } - if ($PSCmdlet.ParameterSetName -eq "Shared") { - $ObjProperties.Type = "Shared" + if ($PSCmdlet.ParameterSetName -eq 'Shared') { + $ObjProperties.Type = 'Shared' } else { - $ObjProperties.Type = "Private" + $ObjProperties.Type = 'Private' } if (! $SkipPFXCertCreation.IsPresent) { @@ -253,6 +242,5 @@ function New-CredentialStore { } } - end { - } + end {} } diff --git a/src/Store/Test-CredentialStore.ps1 b/src/Store/Test-CredentialStore.ps1 index afbc429..e535b06 100644 --- a/src/Store/Test-CredentialStore.ps1 +++ b/src/Store/Test-CredentialStore.ps1 @@ -16,36 +16,27 @@ function Test-CredentialStore { .EXAMPLE Test-CredentialStore -eq $true - - .NOTES - - File Name : Test-CredentialStore.ps1 - - Author : Marco Blessing - marco.blessing@googlemail.com - - Requires : - - .LINK - https://github.com/OCram85/PSCredentialStore #> - [CmdletBinding(DefaultParameterSetName = "Private")] - param( - [Parameter(Mandatory = $false, ParameterSetName = "Shared")] + + [CmdletBinding(DefaultParameterSetName = 'Private')] + [OutputType([bool])] + param ( + [Parameter(Mandatory = $false, ParameterSetName = 'Shared')] [string]$Path, - [Parameter(Mandatory = $true, ParameterSetName = "Shared")] + [Parameter(Mandatory = $true, ParameterSetName = 'Shared')] [switch]$Shared ) - begin { - # Set latest Credential Store version - #Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant - } + begin {} process { # Set the CredentialStore for private, shared or custom mode. Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) - if ($PSCmdlet.ParameterSetName -eq "Private") { + if ($PSCmdlet.ParameterSetName -eq 'Private') { $Path = Get-DefaultCredentialStorePath } - elseif ($PSCmdlet.ParameterSetName -eq "Shared") { + elseif ($PSCmdlet.ParameterSetName -eq 'Shared') { if (!($PSBoundParameters.ContainsKey('Path'))) { $Path = Get-DefaultCredentialStorePath -Shared } @@ -53,15 +44,15 @@ function Test-CredentialStore { Write-Verbose -Message ("Path is: {0}" -f $Path) if (Test-Path $Path) { - Write-Verbose "CredentialStore in given path found." - return $true + Write-Verbose 'CredentialStore in given path found.' + Write-Output $true } else { - Write-Verbose "The given CredentialStore does not exist!" - return $false + Write-Verbose 'The given CredentialStore does not exist!' + Write-Output $false } } - end { } + end {} } diff --git a/tools/AppVeyor.psm1 b/tools/AppVeyor.psm1 deleted file mode 100644 index 3ea9c45..0000000 --- a/tools/AppVeyor.psm1 +++ /dev/null @@ -1,249 +0,0 @@ -<# - Define the callsign of you PowerShell Module. - Callsign is used to identity: - - Module Manifest file name - - Artifact File - - Git repository name - - Module name -#> -$CALLSIGN = 'PSCredentialStore' -Write-Host ("Callsign is: {0}" -f $CALLSIGN) -ForegroundColor Black -BackgroundColor Yellow - - -Function Invoke-InstallDependencies() { - [CmdletBinding()] - Param() - - Process { - Try { - Write-Host 'Available PS modules are:' -ForegroundColor Green -BackgroundColor Black - Get-Module -ListAvailable -Name Pester | Format-Table | Out-String - Get-PackageProvider -ListAvailable - Install-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force -Verbose - Import-PackageProvider -Name NuGet -RequiredVersion '2.8.5.208' -Force - Write-Host 'Installing build deps...' -ForegroundColor Red -BackgroundColor Black - Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.10.1' -Force -SkipPublisherCheck -AllowClobber -Verbose - Install-Module -Name 'posh-git' -Scope CurrentUser -RequiredVersion '0.7.3' -Force -SkipPublisherCheck -AllowClobber - Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber -RequiredVersion '1.2.108' -Verbose - Import-Module -Name 'posh-git' - Remove-Module -Name 'Pester' -Force -ErrorAction SilentlyContinue - Import-Module -Name 'Pester' -RequiredVersion '4.10.1' -Verbose -Force - Import-Module -Name 'PSCoverage' -RequiredVersion '1.2.108' -Verbose -Force - } - Catch { - $MsgParams = @{ - Message = 'Could not install the required dependencies!' - Category = 'Error' - Details = $_.Exception.Message - } - Add-AppveyorMessage @MsgParams - Throw $MsgParams.Message - } - Write-Host 'Loaded PS modules are:' -ForegroundColor Green -BackgroundColor Black - Get-Module -Name Pester | Format-Table | Out-String - } -} -Function Invoke-AppVeyorBumpVersion() { - [CmdletBinding()] - Param() - - 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|CodeCovToken)" } | Sort-Object -Property Name | Format-Table - - Try { - $ModManifest = Get-Content -Path (".\src\{0}.psd1" -f $CALLSIGN) - $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 - } - Catch { - $MsgParams = @{ - Message = 'Could not bump current version into module manifest.' - Category = 'Error' - Details = $_.Exception.Message - } - Add-AppveyorMessage @MsgParams - Throw $MsgParams.Message - } -} - -Function Invoke-AppVeyorBuild() { - [CmdletBinding()] - [OutputType([PsCustomObject])] - Param() - $MsgParams = @{ - Message = 'Creating build artifacts' - Category = 'Information' - Details = 'Extracting source files and compressing them into zip file.' - } - Add-AppveyorMessage @MsgParams - $CompParams = @{ - Path = "{0}\src\*" -f $env:APPVEYOR_BUILD_FOLDER - DestinationPath = "{0}\bin\{1}.zip" -f $env:APPVEYOR_BUILD_FOLDER, $CALLSIGN - Update = $True - Verbose = $True - } - Compress-Archive @CompParams - $MsgParams = @{ - Message = 'Pushing artifacts' - Category = 'Information' - Details = 'Pushing artifacts to AppVeyor store.' - } - Add-AppveyorMessage @MsgParams - $ArtifactPath = Join-Path -Path '.' -ChildPath ('bin/{0}.zip' -f $CALLSIGN) - Push-AppveyorArtifact $ArtifactPath -} - -Function Invoke-AppVeyorTests() { - [CmdletBinding()] - Param() - - $MsgParams = @{ - Message = 'Starting Pester tests' - Category = 'Information' - Details = 'Now running all test found in .\tests\ dir.' - } - Add-AppveyorMessage @MsgParams - - 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) - } - } - Write-Host '===== Preload done. =====' -ForegroundColor Black -BackgroundColor Yellow - } - 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 -CodeCoverageOutputFile ".\coverage.xml" -CodeCoverageOutputFileEncoding ascii -CodeCoverageOutputFileFormat JaCoCo - ForEach ($Item in $TestResults.TestResult) { - Switch ($Item.Result) { - "Passed" { - $TestParams = @{ - Name = "{0}: {1}" -f $Item.Context, $Item.Name - Framework = "NUnit" - Filename = $Item.Describe - Outcome = "Passed" - Duration = $Item.Time.Milliseconds - } - Add-AppveyorTest @TestParams - } - "Failed" { - $TestParams = @{ - Name = "{0}: {1}" -f $Item.Context, $Item.Name - Framework = "NUnit" - Filename = $Item.Describe - Outcome = "Failed" - Duration = $Item.Time.Milliseconds - ErrorMessage = $Item.FailureMessage - ErrorStackTrace = $Item.StackTrace - } - Add-AppveyorTest @TestParams - } - Default { - $TestParams = @{ - Name = "{0}: {1}" -f $Item.Context, $Item.Name - Framework = "NUnit" - Filename = $Item.Describe - Outcome = "None" - Duration = $Item.Time.Milliseconds - ErrorMessage = $Item.FailureMessage - ErrorStackTrace = $Item.StackTrace - } - Add-AppveyorTest @TestParams - } - } - } - If ($TestResults.FailedCount -gt 0) { - $MsgParams = @{ - Message = 'Pester Tests failed.' - Category = 'Error' - Details = "$($TestResults.FailedCount) tests failed." - } - Add-AppveyorMessage @MsgParams - Throw $MsgParams.Message - } - - return $TestResults.CodeCoverage - -} - -Function Invoke-CoverageReport() { - [CmdletBinding()] - Param( - [Parameter(Mandatory = $False)] - [ValidateNotNullOrEmpty()] - [String]$RepoToken = $Env:CoverallsToken, - - [Parameter(Mandatory = $True)] - [ValidateNotNullOrEmpty()] - [PSCustomObject]$PesterCoverageReport - ) - - #$CoverageReport | Format-Custom -Depth 5 | Out-String | Write-Verbose - $CoverageReport = New-CoverageReport -CodeCoverage $PesterCoverageReport -RepoToken $RepoToken - Write-Host "CoverageReport JSON:" -ForegroundColor Yellow - #$CoverageReport | ConvertTo-Json -Depth 5 | Out-String | Write-Verbose - Publish-CoverageReport -CoverageReport $CoverageReport -} - - -Function Invoke-AppVeyorPSGallery() { - [CmdletBinding()] - Param( - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [String]$OnBranch - ) - 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 Black -BackgroundColor Yellow - Get-PackageProvider -ListAvailable - Write-Host "Available Package Sources:" -ForegroundColor Black -BackgroundColor Yellow - Get-PackageSource - Try { - Write-Host "Try to get NuGet Provider:" -ForegroundColor Black -BackgroundColor Yellow - Get-PackageProvider -Name NuGet -ErrorAction Stop - } - Catch { - 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 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 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 - } - } - Catch { - $MsgParams = @{ - Message = 'Could not deploy module to PSGallery.' - Category = 'Error' - Details = $_.Exception.Message - } - $_.Exception.Message | Write-Error - Add-AppveyorMessage @MsgParams - Throw $MsgParams.Message - } -} diff --git a/tools/DroneIO.psm1 b/tools/DroneIO.psm1 index f696923..4d7a579 100644 --- a/tools/DroneIO.psm1 +++ b/tools/DroneIO.psm1 @@ -1,25 +1,70 @@ $Global:ProgressPreference = 'SilentlyContinue' +$ErrorActionPreference = 'Stop' -function Invoke-ShowEnv() { +function Invoke-ShowEnv { [CmdletBinding()] - param() + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSProvideCommentHelp', + '', + Justification = 'internal function' + )] + param () process { Get-ChildItem -Path 'Env:' | Format-Table | Out-String } } -function Invoke-InstallDependencies() { +function Invoke-InstallDependencies { [CmdletBinding()] - [OutputType()] - param() + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSProvideCommentHelp', + '', + Justification = 'internal function' + )] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseSingularNouns', + '', + Justification = 'internal function' + )] + param () process { + $ErrorActionPreference = 'Stop' try { - Install-Module -Name 'PSScriptAnalyzer' -Scope CurrentUser -RequiredVersion '1.19.1' -Force -SkipPublisherCheck -AllowClobber -Verbose:$VerbosePreference -ErrorAction 'Stop' - Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.10.1' -Force -SkipPublisherCheck -AllowClobber -Verbose:$VerbosePreference -ErrorAction 'Stop' - Install-Module -Name 'posh-git' -Scope CurrentUser -RequiredVersion '0.7.3' -Force -SkipPublisherCheck -AllowClobber -Verbose:$VerbosePreference -ErrorAction 'Stop' - Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber -RequiredVersion '1.2.108' -Verbose:$VerbosePreference -ErrorAction 'Stop' + $ParamsPSScript = @{ + Name = 'PSScriptAnalyzer' + Scope = 'CurrentUser' + RequiredVersion = '1.20.0' + Force = $true + SkipPublisherCheck = $true + AllowClobber = $true + Verbose = $VerbosePreference + } + Install-Module @ParamsPSScript + + $ParamsPester = @{ + Name = 'Pester' + Scope = 'CurrentUser' + RequiredVersion = '5.3.3' + Force = $true + SkipPublisherCheck = $true + AllowClobber = $true + Verbose = $VerbosePreference + } + Install-Module @ParamsPester + + $ParamsPosh = @{ + Name = 'posh-git' + Scope = 'CurrentUser' + RequiredVersion = '1.1.0' + Force = $true + SkipPublisherCheck = $true + AllowClobber = $true + Verbose = $VerbosePreference + #ErrorAction = 'Stop' + } + Install-Module @ParamsPosh } catch { $ExceParams = @{ @@ -35,47 +80,80 @@ function Invoke-InstallDependencies() { } } -function Invoke-Linter () { +function Invoke-Linter { [CmdletBinding()] - param() + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSProvideCommentHelp', + '', + Justification = 'internal function' + )] + param () process { - Invoke-ScriptAnalyzer -Path './src/' -Recurse + Import-Module -Name PSScriptAnalyzer + $AnalyzerSettings = @{ + Path = './src/' + Recurse = $true + Settings = './tools/PSScriptAnalyzerSettings.psd1' + ReportSummary = $true + } + Invoke-ScriptAnalyzer @AnalyzerSettings } } -function Invoke-UnitTests { +function Invoke-UnitTest { [CmdletBinding()] - Param() + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSProvideCommentHelp', + '', + Justification = 'internal function' + )] + + param ( + [Parameter( Mandatory = $false )] + [ValidateSet('JaCoCo', 'CoverageGutters')] + [string]$CoverageFormat = 'JaCoCo', + + [Parameter(Mandatory = $false)] + [ValidateSet('None', 'Normal', 'Detailed', 'Diagnostic')] + [string]$Verbosity = 'Normal', + + [Parameter(Mandatory = $false)] + [switch]$PassThru, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string[]]$Tag, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string[]]$ExcludeTag + ) process { - - try { - Write-Host '===== Preload internal private functions =====' -ForegroundColor Black -BackgroundColor Yellow - - $Privates = Get-ChildItem -Path (Join-Path -Path $Env:DRONE_WORKSPACE -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) - } - } + Write-Verbose -Message '===== Running Pester =====' -Verbose:$VerbosePreference + $PesterConf = New-PesterConfiguration + $PesterConf.Run.Path = (Resolve-Path -Path './src').Path + $PesterConf.Run.Exit = $false + $PesterConf.Run.PassThru = $true + $PesterConf.CodeCoverage.Enabled = $true + $PesterConf.CodeCoverage.OutputFormat = $CoverageFormat + $PesterConf.TestResult.Enabled = $true + $CovFiles = Get-ChildItem -Path "./src/*.ps1" -Recurse | Where-Object { + $_.BaseName -notmatch '.Tests' + } | Select-Object -ExpandProperty 'FullName' + $PesterConf.CodeCoverage.Path = $CovFiles + $PesterConf.Output.Verbosity = $Verbosity + # Set Tags if given + if ($Tag) { + $PesterConf.Filter.Tag = $Tag } - catch { - $_.Exception.Message | Write-Error - throw 'Could not load required private functions!' + if ($ExcludeTag) { + $PesterConf.Filter.ExcludeTag = $ExcludeTag } - - Write-Host '===== Running Pester =====' -ForegroundColor Black -BackgroundColor Yellow - $srcFiles = Get-ChildItem -Path "./src/*.ps1" -Recurse | Sort-Object -Property 'Name' | Select-Object -ExpandProperty 'FullName' - $TestFiles = Get-ChildItem -Path (Join-Path -Path '.' -ChildPath './tests/*.Tests.ps1') -Recurse | Sort-Object -Property Name - $TestResults = Invoke-Pester -Path $testFiles -CodeCoverage $srcFiles -PassThru -CodeCoverageOutputFile "./coverage.xml" -CodeCoverageOutputFileEncoding ascii -CodeCoverageOutputFileFormat JaCoCo - - if ($TestResults.FailedCount -gt 0) { - throw ('{0} tests failed!' -f $TestResults.FailedCount) + $TestResults = Invoke-Pester -Configuration $PesterConf -ErrorAction 'Stop' + if ($PassThru.IsPresent) { + Write-Output -InputObject $TestResults } } } diff --git a/tools/PSScriptAnalyzerSettings.psd1 b/tools/PSScriptAnalyzerSettings.psd1 new file mode 100644 index 0000000..8ba8ac8 --- /dev/null +++ b/tools/PSScriptAnalyzerSettings.psd1 @@ -0,0 +1,141 @@ +@{ + Severity = 'Error', 'Warning', 'Information' + + IncludeRules = @( + 'PSAlignAssignmentStatement', + 'PSAvoidAssignmentToAutomaticVariable', + 'PSAvoidDefaultValueForMandatoryParameter', + 'PSAvoidDefaultValueSwitchParameter', + 'PSAvoidGlobalAliases', + 'PSAvoidGlobalFunctions', + 'PSAvoidGlobalVars', + 'PSAvoidInvokingEmptyMembers', + 'PSAvoidLongLines', + 'PSAvoidNullOrEmptyHelpMessageAttribute', + 'PSAvoidOverwritingBuiltInCmdlets', + 'PSAvoidShouldContinueWithoutForce', + 'PSAvoidTrailingWhitespace', + 'PSAvoidUsingCmdletAliases', + 'PSAvoidUsingComputerNameHardcoded', + 'PSAvoidUsingConvertToSecureStringWithPlainText', + 'PSAvoidUsingDeprecatedManifestFields', + 'PSAvoidUsingDoubleQuotesForConstantString', + 'PSAvoidUsingEmptyCatchBlock', + 'PSAvoidUsingInvokeExpression', + 'PSAvoidUsingPlainTextForPassword', + 'PSAvoidUsingPositionalParameters', + 'PSAvoidUsingUsernameAndPasswordParams', + 'PSAvoidUsingWMICmdlet', + 'PSAvoidUsingWriteHost', + 'PSMisleadingBacktick', + 'PSMissingModuleManifestField', + 'PSPlaceCloseBrace', + 'PSPlaceOpenBrace', + 'PSPossibleIncorrectComparisonWithNull', + 'PSPossibleIncorrectUsageOfAssignmentOperator', + 'PSPossibleIncorrectUsageOfRedirectionOperator', + 'PSProvideCommentHelp', + 'PSReservedCmdletChar', + 'PSReservedParams', + 'PSReviewUnusedParameter', + 'PSShouldProcess', + 'PSUseApprovedVerbs', + 'PSUseBOMForUnicodeEncodedFile', + 'PSUseCmdletCorrectly', + # There is no predefined set for Pwsh7 Cmdlets + 'PSUseCompatibleCmdlets', + #'PSUseCompatibleCommands', + 'PSUseCompatibleSyntax', + #'PSUseCompatibleTypes', + 'PSUseConsistentIndentation', + # Disable if bug in 1.19.1 version occurs. + 'PSUseConsistentWhitespace', + 'PSUseCorrectCasing', + 'PSUseDeclaredVarsMoreThanAssignments', + 'PSUseLiteralInitializerForHashtable', + 'PSUseOutputTypeCorrectly', + 'PSUsePSCredentialType', + 'PSUseProcessBlockForPipelineCommand', + 'PSUseShouldProcessForStateChangingFunctions', + 'PSUseSingularNouns', + 'PSUseSupportsShouldProcess', + 'PSUseToExportFieldsInManifest', + 'PSUseUTF8EncodingForHelpFile', + 'PSUseUsingScopeModifierInNewRunspaces' + ) + + Rules = @{ + + PSAvoidLongLines = @{ + Enable = $true + MaximumLineLength = 116 + } + + PSPlaceOpenBrace = @{ + Enable = $true + OnSameLine = $true + NewLineAfter = $true + IgnoreOneLineBlock = $true + } + + PSPlaceCloseBrace = @{ + Enable = $true + NewLineAfter = $true + IgnoreOneLineBlock = $true + NoEmptyLineBefore = $false + } + + PSProvideCommentHelp = @{ + Enable = $true + ExportedOnly = $false + BlockComment = $true + VSCodeSnippetCorrection = $false + Placement = "begin" + } + + PSUseCompatibleCmdlets = @{ + compatibility = @( + "desktop-5.1.14393.206-windows", + "core-6.1.0-windows" + ) + } + + PSUseCompatibleSyntax = @{ + Enable = $true + TargetVersions = @( + "7.0", + "5.1" + ) + } + + PSUseConsistentIndentation = @{ + Enable = $true + Kind = 'space' + PipelineIndentation = 'IncreaseIndentationForFirstPipeline' + IndentationSize = 4 + } + + PSUseConsistentWhitespace = @{ + Enable = $true + CheckInnerBrace = $true + CheckOpenBrace = $true + CheckOpenParen = $true + CheckOperator = $true + CheckPipe = $true + CheckPipeForRedundantWhitespace = $false + CheckSeparator = $true + CheckParameter = $false + IgnoreAssignmentOperatorInsideHashTable = $true + } + + PSAlignAssignmentStatement = @{ + Enable = $true + CheckHashtable = $false + } + + PSUseCorrectCasing = @{ + Enable = $true + } + } + +} diff --git a/tools/Travis.psm1 b/tools/Travis.psm1 deleted file mode 100644 index d4a37f6..0000000 --- a/tools/Travis.psm1 +++ /dev/null @@ -1,66 +0,0 @@ -$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) - } - } -} diff --git a/tools/travis.sh b/tools/travis.sh deleted file mode 100644 index 029896a..0000000 --- a/tools/travis.sh +++ /dev/null @@ -1,14 +0,0 @@ -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