Update pwsh style to latest community standards #52

Merged
OCram85 merged 19 commits from rework2022 into master 2022-06-28 08:56:33 +02:00
48 changed files with 1138 additions and 1358 deletions

View File

@ -1,32 +1,46 @@
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: Linux_PWSH7_Build name: Linux_PWSH7_Build
platform: platform:
os: linux os: linux
arch: amd64 arch: amd64
steps: steps:
- name: Environments - name: Environments
image: mcr.microsoft.com/powershell:latest image: mcr.microsoft.com/powershell:latest
commands: 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}" pwsh -NonInteractive -c "& {
- name: LintTests Import-Module './tools/DroneIO.psm1' -Verbose;
image: mcr.microsoft.com/powershell:latest Invoke-ShowEnv -Verbose
commands: }"
- pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-InstallDependencies}"
- pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-Linter}" - name: LintTests
- name: UnitTests image: mcr.microsoft.com/powershell:latest
image: mcr.microsoft.com/powershell:latest commands:
commands: - |
- pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-InstallDependencies}" pwsh -NonInteractive -c "& {
- pwsh -NonInteractive -c "& {Import-Module './tools/DroneIO.psm1'; Invoke-UnitTests}" Import-Module './tools/DroneIO.psm1';
- name: coverage Invoke-InstallDependencies;
image: plugins/codecov Invoke-Linter
settings: }"
token:
from_secret: CodeCovToken - name: UnitTests
files: image: mcr.microsoft.com/powershell:latest
- coverage.xml 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

31
.editorconfig Normal file
View File

@ -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

26
.gitattributes vendored
View File

@ -1,2 +1,24 @@
src/Vendor/libressl255/* filter=lfs diff=lfs merge=lfs -text # images
*.pfx filter=lfs diff=lfs merge=lfs -text *.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

21
.gitignore vendored
View File

@ -1,3 +1,18 @@
# Don't local track test builds # Don't local track test builds
bin/PSCredentialStore.zip bin/PSCredentialStore.zip
bin/PSCredentialStore/* 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

62
.vscode/cSpell.json vendored
View File

@ -1,40 +1,22 @@
// cSpell Settings // cSpell Settings
{ {
// Version of the setting file. Always 0.1 // Version of the setting file. Always 0.1
"version": "0.1", "version": "0.2",
// language - current active spelling language // language - current active spelling language
"language": "en", "language": "en,de,de-DE",
// words - list of words to be always considered correct // words - list of words to be always considered correct
"words": [ "words": [],
"Cmdlet", // flagWords - list of words to be always considered incorrect
"Cmdlets", // This is useful for offensive words and common spelling errors.
"GUID", // For example "hte" should be "the"
"Hashtable", "flagWords": [],
"Httpclient", "dictionaryDefinitions": [
"Multipart", {
"NTFS", "name": "default",
"Params", "path": "./dictionaries/default.txt"
"Ponduit", }
"Repo", ],
"Veyor", "dictionaries": [
"appveyor", "default"
"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"
]
}

0
.vscode/dictionaries/default.txt vendored Normal file
View File

13
.vscode/extensions.json vendored Normal file
View File

@ -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"
]
}

2
.vscode/launch.json vendored
View File

@ -42,7 +42,7 @@
"type": "PowerShell", "type": "PowerShell",
"request": "launch", "request": "launch",
"name": "PowerShell Interactive Session", "name": "PowerShell Interactive Session",
"cwd": "" "cwd": "${workspaceRoot}"
} }
] ]
} }

31
.vscode/pwsh.code-snippets vendored Normal file
View File

@ -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}'",
")]"
]
}
}

103
.vscode/settings.json vendored
View File

@ -1,51 +1,52 @@
// Place your settings in this file to overwrite default and user settings. {
{ "files.encoding": "utf8",
// Set basic file related options: "files.eol": "auto",
"files.encoding": "utf8", "files.trimTrailingWhitespace": true,
"files.eol": "\r\n", "files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true, "editor.renderWhitespace": "boundary",
"files.insertFinalNewline": true, "editor.formatOnSave": true,
// Formation and editor options "editor.formatOnType": true,
"editor.renderWhitespace": "boundary", "editor.rulers": [
"editor.formatOnSave": true, 116
"editor.formatOnType": true, ],
"editor.rulers": [ "cSpell.enabled": true,
116 "cSpell.enabledLanguageIds": [
], "c",
// powershell general "cpp",
"powershell.startAutomatically": true, "csharp",
"powershell.useX86Host": false, "go",
"powershell.enableProfileLoading": true, "javascript",
"powershell.scriptAnalysis.enable": true, "javascriptreact",
// powershell code Formatting "json",
"powershell.codeFormatting.openBraceOnSameLine": true, "latex",
"powershell.codeFormatting.newLineAfterOpenBrace": true, "markdown",
"powershell.codeFormatting.newLineAfterCloseBrace": true, "php",
"powershell.codeFormatting.whitespaceBeforeOpenBrace": true, "plaintext",
"powershell.codeFormatting.whitespaceBeforeOpenParen": true, "powershell",
"powershell.codeFormatting.whitespaceAroundOperator": true, "python",
"powershell.codeFormatting.whitespaceAfterSeparator": true, "text",
"powershell.codeFormatting.ignoreOneLineBlock": true, "typescript",
"powershell.codeFormatting.alignPropertyValuePairs": true, "typescriptreact",
"powershell.codeFormatting.preset": "Custom", "yaml",
// cspell spellchecker options "yml"
"cSpell.enabledLanguageIds": [ ],
"c", "cSpell.language": "en,de,de-DE",
"cpp", // powershell general
"csharp", "powershell.startAutomatically": true,
"go", "powershell.useX86Host": false,
"javascript", "powershell.enableProfileLoading": true,
"javascriptreact", "powershell.scriptAnalysis.enable": true,
"json", // powershell code Formatting
"latex", "powershell.codeFormatting.openBraceOnSameLine": true,
"markdown", "powershell.codeFormatting.newLineAfterOpenBrace": true,
"php", "powershell.codeFormatting.newLineAfterCloseBrace": true,
"plaintext", "powershell.codeFormatting.whitespaceBeforeOpenBrace": true,
"powershell", "powershell.codeFormatting.whitespaceBeforeOpenParen": true,
"python", "powershell.codeFormatting.whitespaceAroundOperator": true,
"text", "powershell.codeFormatting.whitespaceAfterSeparator": true,
"typescript", "powershell.codeFormatting.ignoreOneLineBlock": true,
"typescriptreact", "powershell.codeFormatting.alignPropertyValuePairs": true,
"yml" "powershell.scriptAnalysis.settingsPath": "./tools/PSScriptAnalyzerSettings.psd1",
] "coverage-gutters.showGutterCoverage": false,
} "coverage-gutters.showLineCoverage": true
}

151
.vscode/tasks.json vendored
View File

@ -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", "version": "2.0.0",
// Start PowerShell //"windows": {
"windows": { // "options": {
"command": "${env:windir}/System32/WindowsPowerShell/v1.0/powershell.exe", // "shell": {
"args": [ // // switch back to windows powershell 5.1
"-NoProfile", // // "executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"-ExecutionPolicy", // "executable": "pwsh.exe",
"Bypass" // "args": [
] // "-NoProfile",
}, // "-ExecutionPolicy",
// "Bypass",
// "-Command"
// ]
// }
// }
//},
"linux": { "linux": {
"command": "/usr/bin/powershell", "options": {
"args": [ "shell": {
"-NoProfile" "executable": "/usr/bin/pwsh",
] "args": [
}, "-NoProfile",
"osx": { "-Command"
"command": "/usr/local/bin/powershell", ]
"args": [ }
"-NoProfile" }
]
}, },
//"osx": {
// "options": {
// "shell": {
// "executable": "/usr/local/bin/pwsh",
// "args": [
// "-NoProfile",
// "-Command"
// ]
// }
// }
//},
"tasks": [ "tasks": [
{ {
"taskName": "Test", "label": "DroneIO: Invoke-Linter",
"suppressTaskName": true, "type": "shell",
"args": [ "command": [
"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};", "Import-Module ./tools/DroneIO.psm1;",
"Invoke-Command { Write-Host 'Completed Test task in task runner.' }" "Invoke-Linterq | Format-Table -AutoSize"
], ],
"problemMatcher": "$pester", "group": "test",
"group": { "problemMatcher": [
"kind": "test", "$pester"
"isDefault": true ]
}
}, },
{ {
"taskName": "DebugBuild", "label": "DroneIO: Invoke-UnitTest",
"suppressTaskName": true, "type": "shell",
"args": [ "command": [
"Write-Host 'Invoking Build...';", "Remove-Item ./coverage.xml -ErrorAction 'SilentlyContinue';",
"Write-Host -Object 'Test previous builds.' -ForegroundColor Blue;", "Remove-Item ./testResults.xml -ErrorAction 'SilentlyContinue';",
"If (Test-Path -Path '.\\bin\\PSCredentialStore.zip') { Remove-Item -Path '.\\bin\\PSCredentialStore.zip' -Verbose};", "Import-Module ./tools/DroneIO.psm1;",
"Copy-Item -Path '.\\src\\' -Destination '.\\bin\\PSCredentialStore' -Recurse -Verbose -Force;", "Invoke-UnitTest -CoverageFormat 'CoverageGutters' -Verbosity 'Debug'"
"Compress-Archive -Path '.\\src\\*' -DestinationPath '.\\bin\\PSCredentialStore.zip' -Update -Verbose;"
], ],
"group": { "group": "test",
"kind": "build", "problemMatcher": [
"isDefault": true "$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"
} }
] ]
} }

347
README.md
View File

@ -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) <p align="right">
[![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) <img src="http://forthebadge.com/images/badges/built-with-love.svg">
[![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) <img src="http://forthebadge.com/images/badges/for-you.svg">
[![codecov](https://codecov.io/gh/OCram85/PSCredentialStore/branch/master/graph/badge.svg)](https://codecov.io/gh/OCram85/PSCredentialStore) </p>
[![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) <p align="center">
[![PowerShell Gallery](https://img.shields.io/powershellgallery/dt/PSCredentialStore.svg?style=plastic "PowershellGallery Downloads")](https://www.powershellgallery.com/packages/PSCredentialStore) <a href="https://github.com/OCram85/PSCredentialStore/">
<img src="https://raw.githubusercontent.com/OCram85/PSCredentialStore/master/assets/social-logo.png" alt="PSCredentialStore" />
![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg) </a>
![forthebadge](http://forthebadge.com/images/badges/for-you.svg) </p>
![social-logo](/assets/social-logo.png) <h1 align="center">
PSCredentialStore
:key: General </h1>
=======
<p align="center">
The PSCredentialStore is a simple credential manager for `PSCredential` objects. It stores PSCredentials in a simple json 🔐 A simple credential manager to store and reuse multiple PSCredential objects.
file. You can choose between a private and shared credential store. The private one exists in your profile and can </p>
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. <p align="center">
<a href="https://cloud.drone.io/OCram85/PSCredentialStore">
PSCredentialStore was developed to simplify the delegation of complex powershell scripts. In this case you often <img src="https://cloud.drone.io/api/badges/OCram85/PSCredentialStore/status.svg" alt="Master Branch Build Status">
need to store credentials for non interactive usage like in scheduled tasks. </a>
<a href="https://codecov.io/gh/OCram85/PSCredentialStore">
Starting with version `1.0.0` PSCredential uses Pfx certificates fo encryption. You can use Pfx certificate files <img src="https://codecov.io/gh/OCram85/PSCredentialStore/branch/master/graph/badge.svg" alt="CodeCov">
or certificates stored in the certificate store. </a>
<a href="https://www.powershellgallery.com/packages/PSCredentialStore">
For more details read the [about_PSCredentialStore](/docs/about_PSCredentialStore.md) page on github or via CLI with <img src="https://img.shields.io/powershellgallery/v/PSCredentialStore.svg?style=plastic" alt="PowershellGallery Published Version">
`Get-Help about_PSCredentialStore`. </a>
<a href="https://www.powershellgallery.com/packages/PSCredentialStore">
You can find the [reference](/docs/PSCredentialStore.md) in the /docs/ path as well. <img src="https://img.shields.io/powershellgallery/vpre/PSCredentialStore.svg?label=latest%20preview&style=plastic" />
</a>
:vulcan_salute: Requirements <a href="https://www.powershellgallery.com/packages/PSCredentialStore">
============ <img src="https://img.shields.io/powershellgallery/dt/PSCredentialStore.svg?style=plastic" />
</a>
- PowerShell >= `5.1` </p>
- .NET Framework >= `4.6` or .NET Core >= `1.0`
:bomb: About Security ## :key: General
============
The PSCredentialStore is a simple credential manager for `PSCredential` objects. It stores PSCredentials in a simple json
>This section explains some security topics and the the design decisions we made to balance the usage and security needs. 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
To be able to delegate `PSCredentials` objects we can't exclusively rely on the `SecureString` cmdlets. You can't scripts without exposing them as plain text.
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. 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.
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. 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.
So we decided to use the public and private keys from valid certificates as part of the custom encryption keys to encrypt your data.
For more details read the [about_PSCredentialStore](/docs/about_PSCredentialStore.md) page on github or via CLI with
This means clearly: Everyone who has access to the `CredentialStore` needs also access to the certificate file to work with it. `Get-Help about_PSCredentialStore`.
Keep in mind you need to secure the access with your NTFS file permissions to avoid unwanted usage. Another option is You can find the [reference](/docs/PSCredentialStore.md) in the /docs/ path as well.
to import the certificate into your certification vaults of you operating system. In this case you can grand the
permission to the certificates itself. ## :vulcan_salute: Requirements
Here is s brief hierarchy description of the certificate location: *(First match wins)* - PowerShell >= `5.1`
- .NET Framework >= `4.6` or .NET Core >= `1.0`
| CredentialStore Type | Certificate Location |
| -------------------- | ---------------------- | ## :bomb: About Security
| Private | `CurrentUser`\\`My` |
| Shared (Windows) | `CurrentUser`\\`My` | >This section explains some security topics and the the design decisions we made to balance the usage and security needs.
| | `LocalMachine`\\`Root` |
| Shared (Linux) | `LocalMachine`\\`My` | To be able to delegate `PSCredentials` objects we can't exclusively rely on the `SecureString` cmdlets. You can't
| | `LocalMachine`\\`Root` | 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
:hammer_and_wrench: Installation 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.
:artificial_satellite: PowerShellGallery.com (Recommended Way)
--------------------------------------- This means clearly: Everyone who has access to the `CredentialStore` needs also access to the certificate file to work with it.
* Make sure you use PowerShell 5.1 or higher with `$PSVersionTable`. Keep in mind you need to secure the access with your NTFS file permissions to avoid unwanted usage. Another option is
* Use the builtin PackageManagement and install with: `Import-Module PowerShellGet; Install-Module 'PSCredentialStore' -Repository 'PSGallery'` to import the certificate into your certification vaults of you operating system. In this case you can grand the
* Additionally use the `-AllowPrerelease` switch until we publish the final release! permission to the certificates itself.
* Done. Start exploring the Module with `Import-Module PSCredentialStore ; Get-Command -Module PSCredentialStore`
Here is s brief hierarchy description of the certificate location: *(First match wins)*
:building_construction: Manual Way
---------- | CredentialStore Type | Certificate Location |
| -------------------- | ---------------------- |
* Take a look at the [Latest Release](https://github.com/OCram85/PSCredentialStore/releases/latest) page. | Private | `CurrentUser`\\`My` |
* Download the `PSCredentialStore.zip`. | Shared (Windows) | `CurrentUser`\\`My` |
* Unpack the zip file and put it in your Powershell module path. | | `LocalMachine`\\`Root` |
* Don't forget to change the NTFS permission flag in the context menu. | Shared (Linux) | `LocalMachine`\\`My` |
* Start with `Import-Module PSCredentialStore` | | `LocalMachine`\\`Root` |
:sparkles: Quick Start ## :hammer_and_wrench: Installation
-----------
### :artificial_satellite: PowerShellGallery.com (Recommended Way)
**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. * 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'`
Starting with version `1.0.0` you can decide the storage type of your fresh created certificate. As default * Additionally use the `-AllowPrerelease` switch until we publish the final release!
PSCredentialStore creates a new pfx certificate file beside the credential store itself. Optionally you can provide * Done. Start exploring the Module with `Import-Module PSCredentialStore ; Get-Command -Module PSCredentialStore`
the parameter `-UseCertStore`. This imports the new certificate in the user or machine certificate store as well.
### :building_construction: Manual Way
```powershell
# Private credential store * Take a look at the [Latest Release](https://github.com/OCram85/PSCredentialStore/releases/latest) page.
New-CredentialStore * Download the `PSCredentialStore.zip`.
* Unpack the zip file and put it in your Powershell module path.
# Private credential store with certificate store usage * Don't forget to change the NTFS permission flag in the context menu.
New-CredentialStore -UseCertStore * Start with `Import-Module PSCredentialStore`
# Shared credential store ### :sparkles: Quick Start
New-CredentialStore -Shared
**1.** First we need a blank credential store. You can decide between a *private* or *shared* store. The private
#Shared credential store in custom location Credential Store can only be accessed with your profile on the machine you created it.
New-CredentialStore -Shared -Path 'C:\CredentialStore.json'
``` 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
**2.** Now you can manage your credential store items: the parameter `-UseCertStore`. This imports the new certificate in the user or machine certificate store as well.
```powershell
# This will prompt for credentials and stores it in a private store ```powershell
New-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD' # Private credential store
New-CredentialStore
# You can now use it in other scripts like this:
$DCCreds = Get-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD' # Private credential store with certificate store usage
Invoke-Command -ComputerName 'dc01.myside.local' -Credential $DCCreds -ScripBlock {Get-Process} New-CredentialStore -UseCertStore
```
# Shared credential store
The credential store contains also a simple function to establish a connection with several systems or protocols. New-CredentialStore -Shared
If you have already installed the underlying framework / modules, you can connect these endpoints:
#Shared credential store in custom location
* **CiscoUcs** - Establish a connection to a Cisco UCS fabric interconnect. New-CredentialStore -Shared -Path 'C:\CredentialStore.json'
* 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) **2.** Now you can manage your credential store items:
* **NetAppFAS** - Establish a connection to a NetApp Clustered ONTAP filer. ```powershell
* Required Modules: [`DataONTAP`](http://mysupport.netapp.com/tools/info/ECMLP2310788I.html?productID=61926) # This will prompt for credentials and stores it in a private store
* **VMware** - Establish a connection to a VMware vCenter or ESXi host. New-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD'
* Required Modules: [`VMware.VimAutomation.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI)
* **CisServer** - Establish a connection to the CisServer Service on vCenter Host. # You can now use it in other scripts like this:
* Required Modules: [`VMware.VimAutomation.Cis.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI) $DCCreds = Get-CredentialStoreItem -RemoteHost 'dc01.myside.local' -Identifier 'AD'
* **ExchangeHTTP** - Establish a remote connection with an Exchange endpoint via http. Invoke-Command -ComputerName 'dc01.myside.local' -Credential $DCCreds -ScripBlock {Get-Process}
* Requires PowerShell remoting ```
* **ExchangeHTTPS** - Establish a remote connection with an Exchange endpoint via https.
* Requires PowerShell remoting The credential store contains also a simple function to establish a connection with several systems or protocols.
* **SCP** - Establish a SCP connection. If you have already installed the underlying framework / modules, you can connect these endpoints:
* Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP)
* **CiscoUcs** - Establish a connection to a Cisco UCS fabric interconnect.
Here are some basic examples: * 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.
```powershell * Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP)
Connect-To -RemoteHost "ucs.myside.local" -Type CiscoUcs * **NetAppFAS** - Establish a connection to a NetApp Clustered ONTAP filer.
Connect-To -RemoteHost "ftp.myside.local" -Type FTP * Required Modules: [`DataONTAP`](http://mysupport.netapp.com/tools/info/ECMLP2310788I.html?productID=61926)
Connect-To -RemoteHost "fas.myside.local" -Type NetAppFAS * **VMware** - Establish a connection to a VMware vCenter or ESXi host.
Connect-To -RemoteHost "esx01.myside.local" -Type VMware * Required Modules: [`VMware.VimAutomation.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI)
Connect-To -RemoteHost "vcr.myside.local" -Type CisServer * **CisServer** - Establish a connection to the CisServer Service on vCenter Host.
Connect-To -RemoteHost "exchange1.myside.local" -Type ExchangeHTTP * Required Modules: [`VMware.VimAutomation.Cis.Core`](https://www.powershellgallery.com/packages/VMware.PowerCLI)
Connect-To -RemoteHost "exchange1.myside.local" -Type ExchangeHTTPS * **ExchangeHTTP** - Establish a remote connection with an Exchange endpoint via http.
Connect-To -RemoteHost "ubuntu.myside.local" -Type SCP * Requires PowerShell remoting
``` * **ExchangeHTTPS** - Establish a remote connection with an Exchange endpoint via https.
* Requires PowerShell remoting
:pushpin: Credits * **SCP** - Establish a SCP connection.
------- * Required Modules: [`WinSCP`](https://www.powershellgallery.com/packages/WinSCP)
A huge thanks to all the people who helped with their projects and indirect contributions which made this possible! Here are some basic examples:
- This module is inspired by the awesome work of Dave Wyatt ([@dlwyatt](https://github.com/dlwyatt)) with articles like these: ```powershell
- https://powershell.org/2013/11/24/saving-passwords-and-preventing-other-processes-from-decrypting-them/ Connect-To -RemoteHost "ucs.myside.local" -Type CiscoUcs
- https://powershell.org/2014/02/01/revisited-powershell-and-encryption/ Connect-To -RemoteHost "ftp.myside.local" -Type FTP
- The awesome people from [LibreSSL](http://www.libressl.org/) which publishes the [portable openssl/libressl binaries](https://github.com/libressl-portable/portable)! 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)!

View File

@ -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

View File

@ -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'))

View File

@ -20,18 +20,11 @@ function Get-CSCertificate {
.EXAMPLE .EXAMPLE
Get-CSCertificate -Type 'Shared' -Thumbprint '12334456' 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()] [CmdletBinding()]
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])] [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])]
param( param (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[ValidateSet('Private', 'Shared')] [ValidateSet('Private', 'Shared')]
@ -42,8 +35,8 @@ function Get-CSCertificate {
[string]$Thumbprint [string]$Thumbprint
) )
begin { begin {}
}
process { process {
if ($Type -eq 'Private') { if ($Type -eq 'Private') {
Get-CSPfXCertificate -Thumbprint $Thumbprint -StoreName 'My' -StoreLocation 'CurrentUser' Get-CSPfXCertificate -Thumbprint $Thumbprint -StoreName 'My' -StoreLocation 'CurrentUser'
@ -69,6 +62,5 @@ function Get-CSCertificate {
} }
} }
} }
end { end {}
}
} }

View File

@ -21,18 +21,10 @@ function Import-CSCertificate {
.EXAMPLE .EXAMPLE
Import-CSCertificate -Type 'Private' -Path (Join-Path -Path $Env:APPDATA -ChildItem 'PfxCertificate.pfx') 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()] [CmdletBinding()]
[OutputType()] param (
param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[ValidateSet('Private', 'Shared')] [ValidateSet('Private', 'Shared')]

View File

@ -35,18 +35,11 @@ function New-CSCertAttribute {
.EXAMPLE .EXAMPLE
New-CSCertAttribute -Country 'DE' -State 'BW' -City 'Karlsruhe' -Organization 'AwesomeIT' -OrganizationalUnitName '' -CommonName 'MyPrivateCert' 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()] [CmdletBinding()]
[OutputType('PSCredentialStore.Certificate.Attribute')] [OutputType('PSCredentialStore.Certificate.Attribute')]
param( param (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateLength(2, 2)] [ValidateLength(2, 2)]
[ValidateNotNull()] [ValidateNotNull()]
@ -76,9 +69,8 @@ function New-CSCertAttribute {
[ValidateNotNull()] [ValidateNotNull()]
[int]$Days = 365 [int]$Days = 365
) )
begin { begin {}
}
process { process {
return [PSCustomObject]@{ return [PSCustomObject]@{
PSTypeName = 'PSCredentialStore.Certificate.Attribute' PSTypeName = 'PSCredentialStore.Certificate.Attribute'
@ -94,6 +86,5 @@ function New-CSCertAttribute {
Days = $Days Days = $Days
} }
} }
end { end {}
}
} }

View File

@ -23,18 +23,11 @@ function New-CSCertificate {
.EXAMPLE .EXAMPLE
New-CSCertificate -CRTAttribute $CRTAttribute -KeyName './myprivate.key' -CertName './mycert.pfx' 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)] [CmdletBinding(SupportsShouldProcess = $true)]
[OutputType()] [OutputType()]
param( param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[PSTypeName('PSCredentialStore.Certificate.Attribute')]$CRTAttribute, [PSTypeName('PSCredentialStore.Certificate.Attribute')]$CRTAttribute,
@ -70,6 +63,7 @@ function New-CSCertificate {
$Env:OPENSSL_CONF = Join-Path $ModuleBase -ChildPath '/openssl.conf' $Env:OPENSSL_CONF = Join-Path $ModuleBase -ChildPath '/openssl.conf'
} }
process { process {
$SubjPattern = "/C={0}/ST={1}/L={2}/O={3}/OU={4}/CN={5}" $SubjPattern = "/C={0}/ST={1}/L={2}/O={3}/OU={4}/CN={5}"
$SubjValues = @( $SubjValues = @(

View File

@ -17,18 +17,11 @@ function Test-CSCertificate {
.EXAMPLE .EXAMPLE
Test-CSCertificate -Type 'Shared' 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()] [CmdletBinding()]
[OutputType([bool])] [OutputType([bool])]
param( param (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[ValidateSet('Private', 'Shared')] [ValidateSet('Private', 'Shared')]

View File

@ -26,36 +26,28 @@ function Use-CSCertificate {
.EXAMPLE .EXAMPLE
Use-CSCertificate -Path 'C:\cert.pfx' 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", "")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path, [string]$Path,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$CredentialStore, [string]$CredentialStore,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Switch]$UseCertStore [switch]$UseCertStore
) )
begin { } begin {}
process { process {
try { try {
@ -74,11 +66,11 @@ function Use-CSCertificate {
} }
try { try {
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$StorePath = Get-DefaultCredentialStorePath $StorePath = Get-DefaultCredentialStorePath
$CS = Get-CredentialStore $CS = Get-CredentialStore
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared" ) { elseif ($PSCmdlet.ParameterSetName -eq 'Shared' ) {
if (!($PSBoundParameters.ContainsKey('CredentialStore'))) { if (!($PSBoundParameters.ContainsKey('CredentialStore'))) {
$StorePath = Get-DefaultCredentialStorePath -Shared $StorePath = Get-DefaultCredentialStorePath -Shared
$CS = Get-CredentialStore -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 $CS | ConvertTo-Json -Depth 5 | Out-File -FilePath $StorePath -Force -Encoding utf8
} }
end { } end {}
} }

View File

@ -58,28 +58,20 @@ function Connect-To {
.EXAMPLE .EXAMPLE
Connect-To -RemoteHost "exchange01.myside.local" -Type ExchangeHTTPS 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")] [CmdletBinding(DefaultParameterSetName = 'Private')]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[string]$RemoteHost, [string]$RemoteHost,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[string]$Identifier, [string]$Identifier,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[ValidateSet( [ValidateSet(
'CiscoUcs', 'CiscoUcs',
'FTP', 'FTP',
@ -92,29 +84,29 @@ function Connect-To {
)] )]
[string]$Type, [string]$Type,
[Parameter(Mandatory = $False, ParameterSetName = "Shared")] [Parameter(Mandatory = $False, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $False, ParameterSetName = "Private")] [Parameter(Mandatory = $False, ParameterSetName = 'Private')]
[PSCredential]$Credentials, [PSCredential]$Credentials,
[Parameter(Mandatory = $true, ParameterSetNAme = "Shared")] [Parameter(Mandatory = $true, ParameterSetNAme = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $False, ParameterSetName = "Shared")] [Parameter(Mandatory = $False, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path, [string]$Path,
[Parameter(Mandatory = $False, ParameterSetName = "Private")] [Parameter(Mandatory = $False, ParameterSetName = 'Private')]
[Parameter(Mandatory = $False, ParameterSetName = "Shared")] [Parameter(Mandatory = $False, ParameterSetName = 'Shared')]
[switch]$PassThru [switch]$PassThru
) )
begin { begin {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -155,7 +147,7 @@ function Connect-To {
catch { catch {
$MessageParams = @{ $MessageParams = @{
Message = "Unable to look up credential store item for RemoteHost {0}/Identifier {1}!" -f $RemoteHost, $Identifier Message = "Unable to look up credential store item for RemoteHost {0}/Identifier {1}!" -f $RemoteHost, $Identifier
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -164,10 +156,10 @@ function Connect-To {
$creds = $Credentials $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 = @{ $MessageParams = @{
Message = "Please provide valid credentials for RemoteHost {0}!" -f $RemoteHost Message = "Please provide valid credentials for RemoteHost {0}!" -f $RemoteHost
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -176,13 +168,13 @@ function Connect-To {
"CiscoUcs" { "CiscoUcs" {
try { try {
$handle = Connect-Ucs -Name $RemoteHost -Credential $creds -ErrorAction Stop $handle = Connect-Ucs -Name $RemoteHost -Credential $creds -ErrorAction Stop
$ExecutionContext.SessionState.PSVariable.Set("DefaultUcs", $handle) $ExecutionContext.SessionState.PSVariable.Set('DefaultUcs', $handle)
} }
catch { catch {
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -207,7 +199,7 @@ function Connect-To {
# Check the connection state and find out if the session is still open. # Check the connection state and find out if the session is still open.
$MessageParams = @{ $MessageParams = @{
Message = "Connection to {0} using Type {1} was established. But now it seems to be lost!" -f $RemoteHost, $Type Message = "Connection to {0} using Type {1} was established. But now it seems to be lost!" -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -221,7 +213,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -235,7 +227,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -255,7 +247,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -274,7 +266,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -293,7 +285,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -314,7 +306,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -323,7 +315,7 @@ function Connect-To {
# Check the connection state and find out if the session is still open. # Check the connection state and find out if the session is still open.
$MessageParams = @{ $MessageParams = @{
Message = "Connection to {0} using Type {1} was established. But now it seems to be lost!" -f $RemoteHost, $Type Message = "Connection to {0} using Type {1} was established. But now it seems to be lost!" -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -332,7 +324,7 @@ function Connect-To {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to connect to {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }

View File

@ -49,18 +49,10 @@ function Disconnect-From {
.EXAMPLE .EXAMPLE
Disconnect-From -RemoteHost "exchange01.myside.local" -Type ExchangeHTTPS 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()] [CmdletBinding()]
param( param (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$RemoteHost, [string]$RemoteHost,
@ -81,126 +73,132 @@ function Disconnect-From {
[switch]$Force [switch]$Force
) )
switch -Regex ($Type) { begin {}
"VMware" {
try { process {
if ($Force) { switch -Regex ($Type) {
Disconnect-VIServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop -Force:$true "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 { 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 { catch {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
}
Write-Error @MessageParams
} }
Write-Error @MessageParams
} }
} "CiscoUcs" {
"CisServer" { try {
try { Disconnect-Ucs -Ucs $RemoteHost
if ($Force) { }
Disconnect-CisServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop -Force:$true
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 { else {
Disconnect-CisServer -Server $RemoteHost -Confirm:$false -ErrorAction Stop $MessageParams = @{
Message = 'There is no open WinSCP Session'
ErrorAction = 'Stop'
}
Write-Error @MessageParams
} }
} }
default {
catch {
# Write a error message to the log. # Write a error message to the log.
$MessageParams = @{ $MessageParams = @{
Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type Message = "Unable to disconnect from {0} using Type {1}." -f $RemoteHost, $Type
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams 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 {}
} }

View File

@ -21,24 +21,16 @@ function Test-CSConnection {
.EXAMPLE .EXAMPLE
Test-CMConnection -RemoteHost "vcr01.internal.net" -Type VMware 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()] [CmdletBinding()]
[OutputType([bool])] [OutputType([bool])]
param( param (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$RemoteHost, [string]$RemoteHost,
[Parameter(Mandatory = $True)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[ValidateSet("CiscoUcs", "FTP", "NetAppFAS", "VMware")] [ValidateSet("CiscoUcs", "FTP", "NetAppFAS", "VMware")]
[string]$Type [string]$Type

View File

@ -29,33 +29,25 @@ function Get-CredentialStoreItem {
.EXAMPLE .EXAMPLE
$myCreds = Get-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" $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])] [OutputType([PSCredential])]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$RemoteHost, [string]$RemoteHost,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Identifier, [string]$Identifier,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path [string]$Path
) )
@ -63,10 +55,10 @@ function Get-CredentialStoreItem {
begin { begin {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -85,7 +77,7 @@ function Get-CredentialStoreItem {
$CS = Get-CredentialStore -Shared -Path $Path $CS = Get-CredentialStore -Shared -Path $Path
$CSMembers = Get-Member -InputObject $CS $CSMembers = Get-Member -InputObject $CS
# Let's first check if the given remote host exists as object property # Let's first check if the given remote host exists as object property
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) { if (($CSMembers.MemberType -eq 'NoteProperty') -and ($CSMembers.Name -contains $CredentialName)) {
if ($null -eq $CS.PfxCertificate) { if ($null -eq $CS.PfxCertificate) {
$Cert = Get-CSCertificate -Type $CS.Type -Thumbprint $CS.Thumbprint $Cert = Get-CSCertificate -Type $CS.Type -Thumbprint $CS.Thumbprint
} }
@ -106,16 +98,16 @@ function Get-CredentialStoreItem {
} }
else { else {
$MsgParams = @{ $MsgParams = @{
ErrorAction = "Stop" ErrorAction = 'Stop'
Message = "Could not find credentials for the given remote host: {0}" -f $RemoteHost Message = 'Could not find credentials for the given remote host: {0}' -f $RemoteHost
} }
Write-Error @MsgParams Write-Error @MsgParams
} }
} }
else { else {
$MsgParams = @{ $MsgParams = @{
ErrorAction = "Stop" ErrorAction = 'Stop'
Message = "The given credential store ({0}) does not exist!" -f $Path Message = 'The given credential store ({0}) does not exist!' -f $Path
} }
Write-Error @MsgParams Write-Error @MsgParams
} }

View File

@ -33,25 +33,17 @@ function New-CredentialStoreItem {
.EXAMPLE .EXAMPLE
New-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" 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")] [CmdletBinding(DefaultParameterSetName = 'Private')]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$RemoteHost, [string]$RemoteHost,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Identifier, [string]$Identifier,
@ -59,10 +51,10 @@ function New-CredentialStoreItem {
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[PSCredential]$Credential, [PSCredential]$Credential,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path [string]$Path
@ -72,10 +64,10 @@ function New-CredentialStoreItem {
begin { begin {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -96,7 +88,7 @@ function New-CredentialStoreItem {
$CSContent = Get-CredentialStore -Shared -Path $Path $CSContent = Get-CredentialStore -Shared -Path $Path
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" $CurrentDate = Get-Date -Format 'u'
if ($Identifier -ne "") { if ($Identifier -ne "") {
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost $CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
@ -119,7 +111,7 @@ function New-CredentialStoreItem {
if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) { if (Get-Member -InputObject $CSContent -Name $CredentialName -Membertype Properties) {
$MessageParams = @{ $MessageParams = @{
Message = "The given host already exists. Nothing to do here." Message = 'The given host already exists. Nothing to do here.'
} }
Write-Warning @MessageParams Write-Warning @MessageParams
} }
@ -139,8 +131,8 @@ function New-CredentialStoreItem {
} }
catch { catch {
$MessageParams = @{ $MessageParams = @{
Message = "Couldn't add item into credential store!" Message = 'Could not add item into credential store!'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -148,15 +140,13 @@ function New-CredentialStoreItem {
} }
else { else {
$MessageParams = @{ $MessageParams = @{
Message = "Please Provide at least a valid user!" Message = 'Please Provide at least a valid user!'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
} }
end { end {}
}
} }

View File

@ -37,30 +37,22 @@ function Remove-CredentialStoreItem {
.EXAMPLE .EXAMPLE
Remove-CredentialStoreItem -RemoteHost "esx01.myside.local" -Identifier svc 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")] [CmdletBinding(DefaultParameterSetName = 'Private')]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[string]$RemoteHost, [string]$RemoteHost,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[string]$Identifier, [string]$Identifier,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path [string]$Path
) )
@ -68,10 +60,10 @@ function Remove-CredentialStoreItem {
begin { begin {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -82,8 +74,8 @@ function Remove-CredentialStoreItem {
# Lets do a quick test on the given CredentialStore. # Lets do a quick test on the given CredentialStore.
if (-not(Test-CredentialStore -Shared -Path $Path)) { if (-not(Test-CredentialStore -Shared -Path $Path)) {
$MessageParams = @{ $MessageParams = @{
Message = "Could not add anything into the given CredentialStore." Message = 'Could not add anything into the given CredentialStore.'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -105,7 +97,7 @@ function Remove-CredentialStoreItem {
} }
else { else {
$MessageParams = @{ $MessageParams = @{
Message = "The given CredentialStoreItem does not exist." Message = 'The given CredentialStoreItem does not exist.'
} }
Write-Warning @MessageParams Write-Warning @MessageParams
} }

View File

@ -34,34 +34,26 @@ function Set-CredentialStoreItem {
.EXAMPLE .EXAMPLE
Set-CredentialStoreItem -Path "C:\TMP\mystore.json" -RemoteHost "esx01.myside.local" -Identifier svc 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")] [CmdletBinding(DefaultParameterSetName = 'Private')]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Private")] [Parameter(Mandatory = $true, ParameterSetName = 'Private')]
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[string]$RemoteHost, [string]$RemoteHost,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[string]$Identifier, [string]$Identifier,
[Parameter(Mandatory = $false, ValueFromPipeline = $true)] [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[PSCredential]$Credential, [PSCredential]$Credential,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path [string]$Path
) )
@ -69,10 +61,10 @@ function Set-CredentialStoreItem {
begin { begin {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -83,8 +75,8 @@ function Set-CredentialStoreItem {
# Lets do a quick test on the given CredentialStore. # Lets do a quick test on the given CredentialStore.
if (-not(Test-CredentialStore -Shared -Path $Path)) { if (-not(Test-CredentialStore -Shared -Path $Path)) {
$MessageParams = @{ $MessageParams = @{
Message = "Could not add anything into the given CredentailStore." Message = 'Could not add anything into the given CredentailStore.'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
@ -92,7 +84,7 @@ function Set-CredentialStoreItem {
# Read the file content based on the given ParameterSetName # Read the file content based on the given ParameterSetName
$CSContent = Get-CredentialStore -Shared -Path $Path $CSContent = Get-CredentialStore -Shared -Path $Path
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" $CurrentDate = Get-Date -Format 'u'
if ($Identifier -ne "") { if ($Identifier -ne "") {
$CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost $CredentialName = $RemoteHost = "{0}/{1}" -f $Identifier, $RemoteHost
@ -129,8 +121,8 @@ function Set-CredentialStoreItem {
} }
Else { Else {
$MessageParams = @{ $MessageParams = @{
Message = "Please Provide at least a valid user!" Message = 'Please Provide at least a valid user!'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }

View File

@ -29,25 +29,18 @@ function Test-CredentialStoreItem {
[None] [None]
.EXAMPLE .EXAMPLE
If (Test-CredentialStoreItem -RemoteHost "Default") { if (Test-CredentialStoreItem -RemoteHost "Default") {
Get-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) 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])] [CmdletBinding(DefaultParameterSetName = 'Private')]
param( [OutputType([bool])]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] param (
[Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData, [string]$Path = "{0}\PSCredentialStore\CredentialStore.json" -f $env:ProgramData,
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
@ -58,17 +51,17 @@ function Test-CredentialStoreItem {
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Identifier, [string]$Identifier,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[switch]$Shared [switch]$Shared
) )
begin { begin {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -86,7 +79,7 @@ function Test-CredentialStoreItem {
if (Test-CredentialStore -Shared -Path $Path) { if (Test-CredentialStore -Shared -Path $Path) {
$CS = Get-CredentialStore -Shared -Path $Path $CS = Get-CredentialStore -Shared -Path $Path
$CSMembers = Get-Member -InputObject $CS $CSMembers = Get-Member -InputObject $CS
if (($CSMembers.MemberType -eq "NoteProperty") -and ($CSMembers.Name -contains $CredentialName)) { if (($CSMembers.MemberType -eq 'NoteProperty') -and ($CSMembers.Name -contains $CredentialName)) {
return $true return $true
} }
else { else {
@ -95,15 +88,13 @@ function Test-CredentialStoreItem {
} }
else { else {
$MsgParams = @{ $MsgParams = @{
ErrorAction = "Stop" ErrorAction = 'Stop'
Message = "The given credential store ({0}) does not exist!" -f $Path Message = "The given credential store ({0}) does not exist!" -f $Path
} }
Write-Error @MsgParams Write-Error @MsgParams
} }
} }
end { end {}
}
} }

View File

@ -19,7 +19,7 @@
CompanyName = '' CompanyName = ''
# Copyright statement for this module # 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 of the functionality provided by this module
Description = 'A simple credential manager to store and reuse multiple credential objects.' Description = 'A simple credential manager to store and reuse multiple credential objects.'

View File

@ -3,8 +3,6 @@
#endregion module-definition #endregion module-definition
Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope 'Script' -ErrorAction Stop Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope 'Script' -ErrorAction Stop
#region dot-sourcing #region dot-sourcing
# dot-sourcing all module functions. The export is handled via manifest file. # dot-sourcing all module functions. The export is handled via manifest file.

14
src/PSModule.Tests.ps1 Normal file
View File

@ -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
#}
}

View File

@ -23,18 +23,11 @@ function Get-CSPfxCertificate {
.EXAMPLE .EXAMPLE
Get-CSPfxCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser' 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()] [CmdletBinding()]
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])] [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])]
param( param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string[]]$Thumbprint, [string[]]$Thumbprint,

View File

@ -14,23 +14,16 @@ function Get-DefaultCredentialStorePath {
.EXAMPLE .EXAMPLE
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
.NOTES
- File Name : Get-DefaultCredentialStorePath.ps1
- Author : Marco Blessing - marco.blessing@googlemail.com
- Requires :
.LINK
https://github.com/OCram85/PSCredentialStore
#> #>
[CmdletBinding()] [CmdletBinding()]
[OutputType([string])] [OutputType([string])]
param( param (
[Parameter(Mandatory = $false)] [Parameter(Mandatory = $false)]
[switch]$Shared [switch]$Shared
) )
begin { } begin {}
process { process {
if ($Shared.IsPresent) { if ($Shared.IsPresent) {
@ -57,5 +50,5 @@ function Get-DefaultCredentialStorePath {
} }
} }
end { } end {}
} }

View File

@ -6,24 +6,16 @@ function Get-ModuleBase {
.DESCRIPTION .DESCRIPTION
This is just a wrapper for enabling pester tests. This is just a wrapper for enabling pester tests.
.OUTPUTS .OUTPUTS
Returns the base path as string 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()] [CmdletBinding()]
[OutputType()] [OutputType([string])]
param() param ()
begin { } begin {}
process { process {
return $MyInvocation.MyCommand.Module.ModuleBase return $MyInvocation.MyCommand.Module.ModuleBase
} }
end { } end {}
} }

View File

@ -14,21 +14,13 @@ function Get-RandomAESKey {
.EXAMPLE .EXAMPLE
.\Get-RandomAESKey .\Get-RandomAESKey
.NOTES
- File Name : Get-RandomAESKey.ps1
- Author : Marco Blessing - marco.blessing@googlemail.com
- Requires :
.LINK
https://github.com/OCram85/PSCredentialStore
#> #>
[CmdletBinding()] [CmdletBinding()]
[OutputType([byte[]])] [OutputType([byte[]])]
param() param ()
begin { } begin {}
process { process {
$key = [byte[]]::new(32) $key = [byte[]]::new(32)
@ -40,5 +32,5 @@ function Get-RandomAESKey {
} }
} }
end { } end {}
} }

View File

@ -13,21 +13,14 @@ function Get-TempDir {
.EXAMPLE .EXAMPLE
Get-TempDir Get-TempDir
.NOTES
- File Name : Get-TempDir.ps1
- Author : Marco Blessing - marco.blessing@googlemail.com
- Requires :
.LINK
https://github.com/OCram85/PSCredentialStore
#> #>
[CmdletBinding()] [CmdletBinding()]
[OutputType([string])] [OutputType([string])]
param() param ()
begin {
begin {}
}
process { process {
if ($IsLinux) { if ($IsLinux) {
return (Resolve-Path -Path '/tmp/').Path return (Resolve-Path -Path '/tmp/').Path
@ -35,10 +28,14 @@ function Get-TempDir {
if ($IsMacOS) { if ($IsMacOS) {
return (Resolve-Path -Path '/tmp/').Path 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 return (Resolve-Path -Path $env:TEMP).Path
} }
} }
end {
} end {}
} }

View File

@ -22,18 +22,10 @@ function Import-CSPfxCertificate {
.EXAMPLE .EXAMPLE
Import-CSPfxCertificate -Path (Join-Path -Path $Env:APPDATA -ChildPath '/PSCredentialStore.pfx') 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()] [CmdletBinding()]
[OutputType()] param (
param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Path, [string]$Path,
@ -68,6 +60,7 @@ function Import-CSPfxCertificate {
)] )]
[string]$OpenFlags = 'ReadWrite' [string]$OpenFlags = 'ReadWrite'
) )
begin { begin {
$Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation) $Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation)
try { try {
@ -77,6 +70,7 @@ function Import-CSPfxCertificate {
$_.Exception.Message | Write-Error -ErrorAction Stop $_.Exception.Message | Write-Error -ErrorAction Stop
} }
} }
process { process {
try { try {
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new( $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new(

View File

@ -38,15 +38,8 @@ function Resolve-Dependency {
If (-not (Resolve-Dependency -Name 'VMware')) { If (-not (Resolve-Dependency -Name 'VMware')) {
Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f 'VMware') -ErrorAction 'Stop' Write-Error -Message ("Could not resolve the optional dependencies defined for {0}" -f 'VMware') -ErrorAction 'Stop'
} }
.NOTES
- File Name : ResolveDependency.ps1
- Author : Marco Blessing - marco.blessing@googlemail.com
- Requires :
.LINK
https://github.com/OCram85/PSCredentialStore
#> #>
[OutputType([bool])] [OutputType([bool])]
[CmdletBinding()] [CmdletBinding()]
param ( param (
@ -86,6 +79,5 @@ function Resolve-Dependency {
} }
} }
end { end {}
}
} }

View File

@ -23,18 +23,11 @@ function Test-CSPfxCertificate {
.EXAMPLE .EXAMPLE
Test-CSPfxCertificate -Thumbprint '12345678' -StoreName 'My' -StoreLocation 'CurrentUser' 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()] [CmdletBinding()]
[OutputType([bool])] [OutputType([bool])]
param( param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Thumbprint, [string]$Thumbprint,

View File

@ -32,18 +32,11 @@ function Test-Module {
.EXAMPLE .EXAMPLE
.\Test-Dependency -Name 'VMware.PowerCLI' -Type 'Module' -StopIfFails .\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])] [OutputType([bool])]
[CmdletBinding()] [CmdletBinding()]
param( param (
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Name, [string]$Name,
@ -56,7 +49,8 @@ Could not find the required {0} called {1}. Please install the required {0} to r
[Parameter(Mandatory = $false)] [Parameter(Mandatory = $false)]
[switch]$StopIfFails [switch]$StopIfFails
) )
begin { }
begin {}
process { process {
$Message = $MessagePattern -f $Type, $Name $Message = $MessagePattern -f $Type, $Name
@ -73,5 +67,5 @@ Could not find the required {0} called {1}. Please install the required {0} to r
} }
} }
end { } end {}
} }

View File

@ -23,35 +23,28 @@ function Get-CredentialStore {
.EXAMPLE .EXAMPLE
$CSContent = Get-CredentialStore -Path "C:\TMP\mystore.json" $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")] [CmdletBinding(DefaultParameterSetName = 'Private')]
[OutputType("PSCredentialStore.Store")] [OutputType('PSCredentialStore.Store')]
param( param (
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[string]$Path, [string]$Path,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared [switch]$Shared
) )
begin { } begin {}
process { process {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -61,26 +54,26 @@ function Get-CredentialStore {
try { try {
$FileContent = Get-Content -Path $Path -Raw $FileContent = Get-Content -Path $Path -Raw
$CS = ConvertFrom-Json $FileContent $CS = ConvertFrom-Json $FileContent
$CS.PSObject.TypeNames.Insert(0, "PSCredentialStore.Store") $CS.PSObject.TypeNames.Insert(0, 'PSCredentialStore.Store')
return $CS Write-Output $CS
} }
catch [System.Exception] { catch [System.Exception] {
$MessageParams = @{ $MessageParams = @{
Message = "Unknown CredentialStore format. Invalid JSON file." Message = 'Unknown CredentialStore format. Invalid JSON file.'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
} }
else { else {
$MessageParams = @{ $MessageParams = @{
Message = "Could not find the CredentialStore." Message = 'Could not find the CredentialStore.'
ErrorAction = "Stop" ErrorAction = 'Stop'
} }
Write-Error @MessageParams Write-Error @MessageParams
} }
} }
end { } end {}
} }

View File

@ -49,49 +49,38 @@ function New-CredentialStore {
.EXAMPLE .EXAMPLE
New-CredentialStore -Shared -Path "C:\TMP\CredentialStore.json" New-CredentialStore -Shared -Path "C:\TMP\CredentialStore.json"
# Creates a new shared CredentialStore in the given location. # 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")] [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Private')]
[OutputType("PSCredentialStore.Store")] [OutputType('PSCredentialStore.Store')]
param( param (
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared, [switch]$Shared,
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[System.IO.FileInfo]$Path, [System.IO.FileInfo]$Path,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Switch]$Force, [switch]$Force,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Switch]$PassThru, [switch]$PassThru,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Switch]$SkipPFXCertCreation, [switch]$SkipPFXCertCreation,
[Parameter(Mandatory = $false, ParameterSetName = "Private")] [Parameter(Mandatory = $false, ParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[Switch]$UseCertStore [switch]$UseCertStore
) )
begin { begin {
# Lets get the current Date in a human readable format. # Lets get the current Date in a human readable format.
$CurrentDate = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" $CurrentDate = Get-Date -Format 'u'
# Set latest Credential Store version
# Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope
# test if the path input is a valid file path # test if the path input is a valid file path
if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Path')) { if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Path')) {
@ -108,7 +97,7 @@ function New-CredentialStore {
$ErrorParams = @{ $ErrorParams = @{
ErrorAction = 'Stop' ErrorAction = 'Stop'
Exception = [System.IO.InvalidDataException]::new( 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 Write-Error @ErrorParams
@ -119,17 +108,17 @@ function New-CredentialStore {
process { process {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
} }
# Test if in the CredentialStore already exists. # Test if in the CredentialStore already exists.
Write-Verbose "Test if there is already a credential store." Write-Verbose 'Test if there is already a credential store.'
if ((Test-Path -Path $Path) -and ($Force -ne $true)) { if ((Test-Path -Path $Path) -and ($Force -ne $true)) {
$ErrorParams = @{ $ErrorParams = @{
ErrorAction = 'Stop' ErrorAction = 'Stop'
@ -211,11 +200,11 @@ function New-CredentialStore {
Type = $null Type = $null
} }
if ($PSCmdlet.ParameterSetName -eq "Shared") { if ($PSCmdlet.ParameterSetName -eq 'Shared') {
$ObjProperties.Type = "Shared" $ObjProperties.Type = 'Shared'
} }
else { else {
$ObjProperties.Type = "Private" $ObjProperties.Type = 'Private'
} }
if (! $SkipPFXCertCreation.IsPresent) { if (! $SkipPFXCertCreation.IsPresent) {
@ -253,6 +242,5 @@ function New-CredentialStore {
} }
} }
end { end {}
}
} }

View File

@ -16,36 +16,27 @@ function Test-CredentialStore {
.EXAMPLE .EXAMPLE
Test-CredentialStore -eq $true 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( [CmdletBinding(DefaultParameterSetName = 'Private')]
[Parameter(Mandatory = $false, ParameterSetName = "Shared")] [OutputType([bool])]
param (
[Parameter(Mandatory = $false, ParameterSetName = 'Shared')]
[string]$Path, [string]$Path,
[Parameter(Mandatory = $true, ParameterSetName = "Shared")] [Parameter(Mandatory = $true, ParameterSetName = 'Shared')]
[switch]$Shared [switch]$Shared
) )
begin { begin {}
# Set latest Credential Store version
#Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant
}
process { process {
# Set the CredentialStore for private, shared or custom mode. # Set the CredentialStore for private, shared or custom mode.
Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) Write-Debug ("ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName)
if ($PSCmdlet.ParameterSetName -eq "Private") { if ($PSCmdlet.ParameterSetName -eq 'Private') {
$Path = Get-DefaultCredentialStorePath $Path = Get-DefaultCredentialStorePath
} }
elseif ($PSCmdlet.ParameterSetName -eq "Shared") { elseif ($PSCmdlet.ParameterSetName -eq 'Shared') {
if (!($PSBoundParameters.ContainsKey('Path'))) { if (!($PSBoundParameters.ContainsKey('Path'))) {
$Path = Get-DefaultCredentialStorePath -Shared $Path = Get-DefaultCredentialStorePath -Shared
} }
@ -53,15 +44,15 @@ function Test-CredentialStore {
Write-Verbose -Message ("Path is: {0}" -f $Path) Write-Verbose -Message ("Path is: {0}" -f $Path)
if (Test-Path $Path) { if (Test-Path $Path) {
Write-Verbose "CredentialStore in given path found." Write-Verbose 'CredentialStore in given path found.'
return $true Write-Output $true
} }
else { else {
Write-Verbose "The given CredentialStore does not exist!" Write-Verbose 'The given CredentialStore does not exist!'
return $false Write-Output $false
} }
} }
end { } end {}
} }

View File

@ -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
}
}

View File

@ -1,25 +1,70 @@
$Global:ProgressPreference = 'SilentlyContinue' $Global:ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'
function Invoke-ShowEnv() { function Invoke-ShowEnv {
[CmdletBinding()] [CmdletBinding()]
param() [Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSProvideCommentHelp',
'',
Justification = 'internal function'
)]
param ()
process { process {
Get-ChildItem -Path 'Env:' | Format-Table | Out-String Get-ChildItem -Path 'Env:' | Format-Table | Out-String
} }
} }
function Invoke-InstallDependencies() { function Invoke-InstallDependencies {
[CmdletBinding()] [CmdletBinding()]
[OutputType()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute(
param() 'PSProvideCommentHelp',
'',
Justification = 'internal function'
)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseSingularNouns',
'',
Justification = 'internal function'
)]
param ()
process { process {
$ErrorActionPreference = 'Stop'
try { try {
Install-Module -Name 'PSScriptAnalyzer' -Scope CurrentUser -RequiredVersion '1.19.1' -Force -SkipPublisherCheck -AllowClobber -Verbose:$VerbosePreference -ErrorAction 'Stop' $ParamsPSScript = @{
Install-Module -Name 'Pester' -Scope CurrentUser -RequiredVersion '4.10.1' -Force -SkipPublisherCheck -AllowClobber -Verbose:$VerbosePreference -ErrorAction 'Stop' Name = 'PSScriptAnalyzer'
Install-Module -Name 'posh-git' -Scope CurrentUser -RequiredVersion '0.7.3' -Force -SkipPublisherCheck -AllowClobber -Verbose:$VerbosePreference -ErrorAction 'Stop' Scope = 'CurrentUser'
Install-Module -Name 'PSCoverage' -Scope CurrentUser -Force -SkipPublisherCheck -AllowClobber -RequiredVersion '1.2.108' -Verbose:$VerbosePreference -ErrorAction 'Stop' 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 { catch {
$ExceParams = @{ $ExceParams = @{
@ -35,47 +80,80 @@ function Invoke-InstallDependencies() {
} }
} }
function Invoke-Linter () { function Invoke-Linter {
[CmdletBinding()] [CmdletBinding()]
param() [Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSProvideCommentHelp',
'',
Justification = 'internal function'
)]
param ()
process { 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()] [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 { process {
Write-Verbose -Message '===== Running Pester =====' -Verbose:$VerbosePreference
try { $PesterConf = New-PesterConfiguration
Write-Host '===== Preload internal private functions =====' -ForegroundColor Black -BackgroundColor Yellow $PesterConf.Run.Path = (Resolve-Path -Path './src').Path
$PesterConf.Run.Exit = $false
$Privates = Get-ChildItem -Path (Join-Path -Path $Env:DRONE_WORKSPACE -ChildPath '/src/Private/*') -Include "*.ps1" -Recurse -ErrorAction Stop $PesterConf.Run.PassThru = $true
foreach ($File in $Privates) { $PesterConf.CodeCoverage.Enabled = $true
if (Test-Path -Path $File.FullName) { $PesterConf.CodeCoverage.OutputFormat = $CoverageFormat
. $File.FullName $PesterConf.TestResult.Enabled = $true
Write-Verbose -Message ('Private function dot-sourced: {0}' -f $File.FullName) -Verbose $CovFiles = Get-ChildItem -Path "./src/*.ps1" -Recurse | Where-Object {
} $_.BaseName -notmatch '.Tests'
else { } | Select-Object -ExpandProperty 'FullName'
Write-Warning -Message ('Could not find file: {0} !' -f $File.FullName) $PesterConf.CodeCoverage.Path = $CovFiles
} $PesterConf.Output.Verbosity = $Verbosity
} # Set Tags if given
if ($Tag) {
$PesterConf.Filter.Tag = $Tag
} }
catch { if ($ExcludeTag) {
$_.Exception.Message | Write-Error $PesterConf.Filter.ExcludeTag = $ExcludeTag
throw 'Could not load required private functions!'
} }
$TestResults = Invoke-Pester -Configuration $PesterConf -ErrorAction 'Stop'
Write-Host '===== Running Pester =====' -ForegroundColor Black -BackgroundColor Yellow if ($PassThru.IsPresent) {
$srcFiles = Get-ChildItem -Path "./src/*.ps1" -Recurse | Sort-Object -Property 'Name' | Select-Object -ExpandProperty 'FullName' Write-Output -InputObject $TestResults
$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)
} }
} }
} }

View File

@ -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
}
}
}

View File

@ -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)
}
}
}

View File

@ -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