├── .config
├── RequiredModules.psd1
└── dotnet-tools.json
├── .devcontainer
├── Dockerfile
└── devcontainer.json
├── .github
└── workflows
│ └── press.yml
├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── PSModule.build.ps1
├── README.MD
├── SecretManagement.KeePass
├── PoshKeePass
│ ├── PoShKeePass.format.ps1xml
│ ├── PoShKeePass.psd1
│ ├── PoShKeePass.psm1
│ ├── bin
│ │ ├── PTLibRestore.dll
│ │ ├── SkiaSharp.dll
│ │ ├── System.Buffers.dll
│ │ ├── System.Memory.dll
│ │ ├── System.Numerics.Vectors.dll
│ │ ├── System.Runtime.CompilerServices.Unsafe.dll
│ │ ├── System.Security.Cryptography.ProtectedData.dll
│ │ └── pt.KeePassLibStd.dll
│ ├── changelog.md
│ ├── license
│ └── readme.md
├── Public
│ ├── Register-KeePassSecretVault.ps1
│ └── Unlock-KeePassSecretVault.ps1
├── SecretManagement.KeePass.Extension
│ ├── Private
│ │ ├── ConvertTo-ReadOnlyDictionary.ps1
│ │ ├── GetKeepassParams.ps1
│ │ ├── Test-DBChanged.ps1
│ │ ├── Test-Verbose.ps1
│ │ ├── Unlock-SecureString.ps1
│ │ └── VaultError.ps1
│ ├── Public
│ │ ├── Connect-KeepassDatabase.ps1
│ │ ├── Get-Secret.ps1
│ │ ├── Get-SecretInfo.ps1
│ │ ├── Remove-Secret.ps1
│ │ ├── Set-Secret.ps1
│ │ ├── Test-SecretVault.ps1
│ │ ├── Unlock-SecretVault.ps1
│ │ └── Unregister-SecretVault.ps1
│ ├── SecretManagement.KeePass.Extension.psd1
│ └── SecretManagement.KeePass.Extension.psm1
├── SecretManagement.KeePass.psd1
├── SecretManagement.KeePass.psm1
└── Tests
│ ├── Get-Secret.Tests.ps1
│ ├── Mocks
│ ├── TestdbKeyFile.kdbx
│ ├── TestdbKeyFile.key
│ ├── TestdbKeyFileAndMasterPassword.kdbx
│ ├── TestdbKeyFileAndMasterPassword.key
│ ├── TestdbKeyFileV2.kdbx
│ ├── TestdbKeyFileV2.keyx
│ ├── TestdbPathAndUseMasterPassword.kdbx
│ └── TestdbPathOnly.kdbx
│ ├── Register-KeePassSecretVault.Tests.ps1
│ ├── Remove-Secret.Tests.ps1
│ ├── SecretManagementVault.Tests.ps1
│ ├── Test-SecretVault.Tests.ps1
│ └── TestSecretVault-CommonTests.include.ps1
├── build.ps1
└── images
├── KeePassSecretManagementDemo.gif
└── Logo.png
/.config/RequiredModules.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | 'Microsoft.Powershell.SecretManagement' = '1.1.0'
3 | 'PowerConfig' = '0.1.3'
4 | 'PSFramework' = '1.6.205'
5 | }
6 |
--------------------------------------------------------------------------------
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "gitversion.tool": {
6 | "version": "5.6.6",
7 | "commands": [
8 | "dotnet-gitversion"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/powershell:ubuntu-18.04
2 | RUN pwsh -noprofile -noninteractive -c 'Install-Module PowershellGet -Scope AllUsers -AllowPrerelease -Force'
3 | RUN pwsh -noprofile -noninteractive -c 'Register-PSResourceRepository -PSGallery -Trusted;Install-PSResource Pester -Scope AllUsers -Verbose;Install-PSResource -Scope AllUsers Microsoft.Powershell.SecretManagement'
4 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.154.2/containers/powershell
3 | {
4 | "name": "PowerShell",
5 | "build": {
6 | "dockerfile": "Dockerfile"
7 | },
8 |
9 | // Set *default* container specific settings.json values on container create.
10 | "settings": {
11 | "terminal.integrated.shell.linux": "/usr/bin/pwsh"
12 | },
13 |
14 | // Add the IDs of extensions you want installed when the container is created.
15 | "extensions": [
16 | "ms-vscode.powershell-preview",
17 | "hbenl.vscode-test-explorer",
18 | "mhutchie.git-graph",
19 | "cschleiden.vscode-github-actions",
20 | "tylerleonhardt.vscode-pester-test-adapter"
21 | ],
22 |
23 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
24 | // "forwardPorts": [],
25 |
26 | // Uncomment the next line to run commands after the container is created. This gets run in bash which is why we call `pwsh`.
27 | //"postCreateCommand": "/usr/bin/pwsh -c 'Install-Module Pester,Microsoft.Powershell.SecretManagement -Force'",
28 |
29 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
30 | // "remoteUser": "vscode"
31 | }
32 |
--------------------------------------------------------------------------------
/.github/workflows/press.yml:
--------------------------------------------------------------------------------
1 | name: Press Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - main
8 | - ci
9 | - production
10 | tags:
11 | - '*'
12 | release:
13 | types:
14 | - published
15 | pull_request:
16 | branches:
17 | - master
18 | - main
19 | - production
20 | jobs:
21 | build:
22 | name: 👷 Build
23 | runs-on: ubuntu-20.04
24 | steps:
25 | # Workaround: https://github.com/actions/runner/issues/520#issuecomment-720508121
26 | - if: always()
27 | name: 🐛 Get Debug Status
28 | id: debugStatus
29 | run: |
30 | echo '::set-output name=runnerDebug::${{secrets.ACTIONS_RUNNER_DEBUG}}'
31 | echo '::set-output name=stepDebug::${{secrets.ACTIONS_STEP_DEBUG}}'
32 |
33 | - name: 🚚 Checkout
34 | uses: actions/checkout@v2
35 | with:
36 | # Required for GitVersion
37 | #TODO: Calculate fetch depth up to the parent branch's last version tag (this is all gitversion really needs)
38 | fetch-depth: 0
39 | - name: 🔗 Cache Powershell Modules
40 | uses: actions/cache@v2
41 | with:
42 | path: |
43 | ~/Documents/Powershell/Modules
44 | ~/Documents/WindowsPowershell/Modules
45 | ~/.local/share/powershell/Modules
46 | ~/.local/share/Press
47 | ~/AppData/Local/Press
48 | ~/.nuget/packages/gitversion.tool
49 | key: build-${{ hashFiles('.config/RequiredModules.psd1') }}
50 |
51 | - if: steps.debugStatus.outputs.stepDebug
52 | name: 🔬 Powershell Environment Information
53 | shell: pwsh
54 | run: |
55 | "::group::Powershell Modules"
56 | ($ENV:PSModulePath).split([io.path]::pathseparator) | where {Test-Path $_} | Get-ChildItem
57 | "::endgroup"
58 |
59 | "::group::Variables"
60 | Get-Variable | select name,value | Out-String
61 | "::endgroup"
62 |
63 | "::group::Environment"
64 | dir env: | Out-String
65 | "::endgroup"
66 |
67 | - name: 👷 Build
68 | id: build
69 | shell: pwsh
70 | run: |
71 | if ('${{secrets.ACTIONS_STEP_DEBUG}}') {$verbosePreference = 'continue'}
72 | ./build '.,Package'
73 |
74 | - name: 📦 Capture Powershell Module
75 | uses: actions/upload-artifact@v2
76 | with:
77 | name: PSModule
78 | path: BuildOutput/${{ steps.build.outputs.moduleName }}
79 |
80 | - name: 📦 Capture Powershell Zip
81 | uses: actions/upload-artifact@v2
82 | with:
83 | name: ${{ steps.build.outputs.moduleName }}-${{ steps.build.outputs.nugetVersion }}.zip
84 | #FIXME: Double zip
85 | path: BuildOutput/*.zip
86 |
87 | - name: 📦 Capture Powershell Nuget Package
88 | uses: actions/upload-artifact@v2
89 | with:
90 | name: ${{ steps.build.outputs.moduleName }}.${{ steps.build.outputs.nugetVersion }}.nupkg
91 | path: BuildOutput/*.nupkg
92 |
93 | - if: always() && runner.os != 'Windows' && steps.debugStatus.outputs.runnerDebug
94 | name: 🐛 Debug via SSH if ACTIONS_RUNNER_DEBUG secret is set
95 | uses: lhotari/action-upterm@v1
96 |
97 | #TODO: Move to dedicated function
98 | - name: 📦 Update Draft Github Release
99 | if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci'
100 | shell: pwsh
101 | run: |
102 | ./build 'Press.UpdateGitHubRelease'
103 | env:
104 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105 |
106 | test:
107 | name: 🧪 Test
108 | needs: build
109 | runs-on: ${{ matrix.os }}
110 | strategy:
111 | fail-fast: true
112 | matrix:
113 | os:
114 | # - ubuntu-latest
115 | - ubuntu-20.04
116 | - ubuntu-18.04
117 | # - ubuntu-16.04
118 | # - windows-latest
119 | - windows-2019
120 | # - windows-2016
121 | # - macos-latest
122 | - macos-11.0
123 | - macos-10.15
124 | steps:
125 | - name: 🚚 Checkout
126 | uses: actions/checkout@v2
127 | with:
128 | # Required for GitVersion
129 | #TODO: Calculate fetch depth up to the parent branch's last version tag (this is all gitversion really needs)
130 | fetch-depth: 0
131 |
132 | - name: 🔗 Cache Powershell Modules
133 | uses: actions/cache@v2
134 | with:
135 | path: |
136 | ~/Documents/Powershell/Modules
137 | ~/Documents/WindowsPowershell/Modules
138 | ~/.local/share/powershell/Modules
139 | ~/.local/share/Press
140 | ~/AppData/Local/Press
141 | ~/.nuget/packages/gitversion.tool
142 | key: test-${{ matrix.os }}-${{ hashFiles('Source/.config/RequiredModules.psd1') }}
143 |
144 | - name: ➕ Restore Built Powershell Module
145 | uses: actions/download-artifact@v2
146 | with:
147 | name: PSModule
148 | #TODO: Pull this from environment setup
149 | path: BuildOutput/${{ github.event.repository.name }}
150 |
151 | - name: 🧪 Test Powershell 7+
152 | shell: pwsh
153 | run: |
154 | if ('${{secrets.ACTIONS_STEP_DEBUG}}') {$verbosePreference = 'continue'}
155 | #Press Meta
156 | if ('${{ github.event.repository.name }}' -eq 'Press') {
157 | $GLOBAL:PressModulePath = Resolve-Path ./BuildOutput/Press/Press.psd1
158 | }
159 |
160 | . ./build.ps1 'Test'
161 |
162 | deployPrerelease:
163 | name: 🚀 Deploy Prelease Module
164 | if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
165 | runs-on: ubuntu-20.04
166 | environment: Powershell Gallery PreRelease
167 | needs:
168 | - build
169 | - test
170 | steps:
171 | - name: ➕ Restore Built Powershell Module
172 | uses: actions/download-artifact@v2
173 | with:
174 | name: PSModule
175 | #TODO: Get BuildOutput Config Path
176 | path: BuildOutput/${{ github.event.repository.name }}
177 | - name: 🚀 Publish Module to PowerShell Gallery
178 | shell: pwsh
179 | run: |
180 | if (-not '${{ secrets.PS_GALLERY_KEY }}') {throw 'You need to configure a PS_GALLERY_KEY secret for this environment with your Powershell Gallery API Key'}
181 | Install-Module Microsoft.Powershell.SecretManagement -RequiredVersion 1.1.0 -Force
182 | Install-Module PSFramework -RequiredVersion 1.6.205 -Force -AllowClobber
183 | Publish-Module -Verbose -Name $PWD/BuildOutput/${{ github.event.repository.name }} -NugetApiKey ${{ secrets.PS_GALLERY_KEY }}
184 |
185 | deploy:
186 | name: 🚀 Deploy
187 | if: startsWith(github.ref, 'refs/tags/')
188 | runs-on: ubuntu-20.04
189 | environment: Powershell Gallery
190 | needs:
191 | - build
192 | - test
193 | steps:
194 | - name: ➕ Restore Built Powershell Module
195 | uses: actions/download-artifact@v2
196 | with:
197 | name: PSModule
198 | #TODO: Get BuildOutput Config Path
199 | path: BuildOutput/${{ github.event.repository.name }}
200 | - name: 🚀 Publish Module to PowerShell Gallery
201 | shell: pwsh
202 | run: |
203 | if (-not '${{ secrets.PS_GALLERY_KEY }}') {throw 'You need to configure a PS_GALLERY_KEY secret for this environment with your Powershell Gallery API Key'}
204 | Install-Module Microsoft.Powershell.SecretManagement -RequiredVersion 1.1.0 -Force
205 | Install-Module PSFramework -RequiredVersion 1.6.205 -Force -AllowClobber
206 | Publish-Module -Verbose -Name $PWD/BuildOutput/${{ github.event.repository.name }} -NugetApiKey ${{ secrets.PS_GALLERY_KEY }}
207 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | TestExplorerResults.xml
2 | BuildOutput
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "github-actions.workflows.pinned.refresh.enabled": true,
3 | "github-actions.workflows.pinned.refresh.interval": 5,
4 | "editor.formatOnSaveMode": "modifications",
5 | "editor.formatOnSave": true,
6 | "github-actions.workflows.pinned.workflows": [
7 | ".github/workflows/press.yml"
8 | ]
9 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Justin Grote
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PSModule.build.ps1:
--------------------------------------------------------------------------------
1 |
2 | if (-not (Get-Module PowerConfig -ErrorAction SilentlyContinue)) {
3 | try {
4 | Import-Module PowerConfig -ErrorAction Stop
5 | } catch {
6 | Install-Module PowerConfig -AllowPrerelease -Force
7 | Import-Module PowerConfig -ErrorAction Stop
8 | }
9 | }
10 | if (-not (Get-Module Press -ErrorAction SilentlyContinue)) {
11 | try {
12 | Import-Module Press -ErrorAction Stop
13 | } catch {
14 | Install-Module Press -Force
15 | Import-Module Press -ErrorAction Stop
16 | }
17 | }
18 | if (-not (Get-Module 'Microsoft.Powershell.SecretManagement' -ErrorAction SilentlyContinue)) {
19 | try {
20 | Import-Module 'Microsoft.Powershell.SecretManagement' -ErrorAction Stop
21 | } catch {
22 | Install-Module 'Microsoft.Powershell.SecretManagement' -AllowPrerelease -RequiredVersion '1.1.0' -Force
23 | Import-Module 'Microsoft.Powershell.SecretManagement' -ErrorAction Stop
24 | }
25 | }
26 | if (-not (Get-Module 'PSFramework' -ErrorAction SilentlyContinue)) {
27 | try {
28 | Import-Module 'PSFramework' -ErrorAction Stop
29 | } catch {
30 | Install-Module 'PSFramework' -AllowPrerelease -RequiredVersion '1.6.205' -Force -AllowClobber
31 | Import-Module 'PSFramework' -ErrorAction Stop
32 | }
33 | }
34 |
35 | . Press.Tasks
36 |
37 | Task Press.CopyModuleFiles @{
38 | Inputs = {
39 | Get-ChildItem -File -Recurse $PressSetting.General.SrcRootDir
40 | $SCRIPT:IncludeFiles = (
41 | (Get-ChildItem -File -Recurse "$($PressSetting.General.SrcRootDir)\SecretManagement.KeePass.Extension") |
42 | Resolve-Path
43 | )
44 | $IncludeFiles
45 | }
46 | Outputs = {
47 | $buildItems = Get-ChildItem -File -Recurse $PressSetting.Build.ModuleOutDir
48 | if ($buildItems) { $buildItems } else { 'EmptyBuildOutputFolder' }
49 | }
50 | Jobs = {
51 | Remove-BuildItem $PressSetting.Build.ModuleOutDir
52 |
53 | $copyResult = Copy-PressModuleFiles @commonParams `
54 | -Destination $PressSetting.Build.ModuleOutDir `
55 | -PSModuleManifest $PressSetting.BuildEnvironment.PSModuleManifest
56 |
57 | $PressSetting.OutputModuleManifest = $copyResult.OutputModuleManifest
58 | }
59 | }
60 |
61 | Task CopyKeePassExtension -After Press.CopyModuleFiles {
62 | #KeePass Extension Files
63 | $KPExtensionPath = "$($PressSetting.General.SrcRootDir)\SecretManagement.KeePass.Extension"
64 | Copy-Item $KPExtensionPath -Recurse -Force -Exclude '*.Tests.ps1' -Destination $PressSetting.Build.ModuleOutDir -Container
65 | }
66 |
67 | Task CopyPoshKeePass -After Press.CopyModuleFiles {
68 | #KeePass Extension Files
69 | $PKPExtensionPath = "$($PressSetting.General.SrcRootDir)\PoshKeePass"
70 | Copy-Item $PKPExtensionPath -Recurse -Force -Exclude '*.Tests.ps1' -Destination $PressSetting.Build.ModuleOutDir -Container
71 | }
72 |
73 | Task Package Press.Package.Zip
74 |
75 | Task Press.Test.Pester.WindowsPowershell {
76 | Write-Warning 'Windows Powershell Tests cannot currently be run due to a bug. Run the tests manually. Remove when https://github.com/pester/Pester/issues/1974 is closed'
77 | }
78 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # KeePass Secret Management Extension
2 |
3 | ## Actions
4 |
5 | [![Actions][]][ActionsLink]
6 |
7 | ## Summary
8 |
9 | This is a simple proof-of-concept using a modified version of PoshKeePass to allow for cross platform usage.
10 |
11 | 
12 |
13 | ## Quick Start
14 |
15 | 1. Create a keepass database with a master password, Keyfile or both.
16 | 1. `Install-Module SecretManagement.KeePass`
17 | 1. Run the following command:
18 |
19 | ```powershell
20 | Register-SecretVault -Name 'testVault' -ModuleName 'SecretManagement.Keepass' -VaultParameters @{
21 | Path = "path/to/my/vault.kdbx"
22 | UseMasterPassword = $true
23 | KeyPath= "path/to/my/keyfile.key"
24 | }
25 | ```
26 |
27 | 1. (optional) Use Test-SecretVault to validate your connection to the vault
28 |
29 | ```powershell
30 | Test-SecretVault -Name 'testVault'
31 | ```
32 |
33 | 2. Get the secret data using Get-Secret
34 |
35 | ```powershell
36 | Get-Secret -Name 'My secret entry 1' -Vault 'testVault'
37 | ```
38 |
39 | ## Known Limitations
40 |
41 | [Actions]: https://github.com/JustinGrote/SecretManagement.KeePass/workflows/Test/badge.svg?branch=main
42 | [ActionsLink]: https://github.com/JustinGrote/SecretManagement.KeePass/workflows
43 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/PoShKeePass.format.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PSKeePass.Entry
6 |
7 | PSKeePass.Entry
8 |
9 |
10 |
11 |
12 |
13 |
14 | Title
15 |
16 |
17 | UserName
18 |
19 |
20 | Password
21 |
22 |
23 | FullPath
24 |
25 |
26 | Notes
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/PoShKeePass.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/PoShKeePass.psd1
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/PTLibRestore.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/PTLibRestore.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/SkiaSharp.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/SkiaSharp.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/System.Buffers.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/System.Buffers.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/System.Memory.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/System.Memory.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/System.Numerics.Vectors.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/System.Numerics.Vectors.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/System.Runtime.CompilerServices.Unsafe.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/System.Runtime.CompilerServices.Unsafe.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/System.Security.Cryptography.ProtectedData.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/System.Security.Cryptography.ProtectedData.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/bin/pt.KeePassLibStd.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/PoshKeePass/bin/pt.KeePassLibStd.dll
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## v.2.1.3.0
4 |
5 | * Added [#160](https://github.com/PSKeePass/PoShKeePass/issues/160) - Default Database Configuration Profile.
6 | * When set, the `-DatabaseProfileName` parameter is optional, and if not passed it will grab the default profile from the config.
7 | * To Set it up on an existing profile simply use the update command:
8 |
9 | ```powershell
10 | Update-KeePassDatabaseConfigurationProfile -DatabaseProfileName 'name' -Default
11 | ```
12 |
13 | * To Create a new profile as default use the new command:
14 |
15 | ```powershell
16 | New-KeePassDatabaseConfigurationProfile -DatabaseProfileName 'name' -Default -DatabasePath '' other options
17 | ```
18 |
19 | * This allows for calls to the main module functions without the `-DatabaseProfileName` parameter such as:
20 |
21 | ```powershell
22 | Get-KeePassEntry -UserName 'aUser'
23 | ```
24 |
25 | ## v.2.1.2.8
26 |
27 | * Added - [#84](https://github.com/PSKeePass/PoShKeePass/issues/84) - Manage Notes properties on KPGroup Objects.
28 |
29 | * v.2.1.2.6 - Added - [#158](https://github.com/PSKeePass/PoShKeePass/issues/158) - Added Update-KeePassDatabaseConfiguration function and tests.
30 |
31 | * v.2.1.2.5 - Fix - [#157](https://github.com/PSKeePass/PoShKeePass/issues/157) - Set New-KPConnection function back to internal function and no longer exports.
32 |
33 | ## v.2.1.2.4
34 |
35 | * Added Feature [#29](https://github.com/PSKeePass/PoShKeePass/issues/29) - Can now manage the Expiration Time/Enabled State of groups and entry.
36 |
37 | * v.2.1.2.3 - Fix [#64](https://github.com/PSKeePass/PoShKeePass/issues/65) - Review Message for grammar, clarified some messages as well.
38 |
39 | * v.2.1.2.2 - Fix [#156](https://github.com/PSKeePass/PoShKeePass/issues/156) - New-KeePassDatabase will now error out if kdbx file already exists, instead of silently overwriting an existing file.
40 |
41 | * v.2.1.2.1 - Fix [#149](https://github.com/PSKeePass/PoShKeePass/issues/149) - **Breaking Change** New-KeePassGroup and Update-KeePassGroup now return a KeePass PSObject via the ConvertTo-KPPsObject function.
42 |
43 | ## v.2.1.2.0
44 |
45 | * Fix [#148](https://github.com/PSKeePass/PoShKeePass/issues/148) - Can now update an entry multiple times, while retaining history and not through internal lib exception
46 | * Changes to build script
47 |
48 | ## v2.1.1.8
49 |
50 | ### Many fixes, features and improvements, please note the **Breaking Changes** Below
51 |
52 | * Fix [#129](https://github.com/PSKeePass/PoShKeePass/issues/129) - Can now pass Credential Object to `-MasterKey` Parameter
53 | * Fix/Implemented [#69](https://github.com/PSKeePass/PoShKeePass/issues/69) - All primary Functions return a Powershell object rather than a KeePass Object **This Includes Breaking changes!**.
54 | * **Breaking:**
55 | * Since a powershell object is now returned, in order to access the keepass object a child property has been added to the ps object, `.KPEntry` and `.KPGroup`.
56 | * Deprecated the `-AsPlainText` parameter on the `Get-KeePassGroup` function, the call will still work but it will present a warning message. This is being removed as it is no longer necessary.
57 | * **Non-Breaking:**
58 | * Moved how database profile name was being added to the ps object for better performance on conversion.
59 | * Implemented [#93](https://github.com/PSKeePass/PoShKeePass/issues/93) - `Get-KeePassEntry` Now supports `-Title` and `-UserName` parameters also via pipeline.
60 | * Normalized Error handling to remove repetitive code
61 | * Converted extraneous logic to parameter splatting
62 | * Code formatting and removed explict parameter attributes where not necessary.
63 | * Updated Object creation to use the `hashtable` method for performance over the `New-Object` + `Add-Memeber`.
64 | * Fix [#44](https://github.com/PSKeePass/PoShKeePass/issues/44) - Pipeline now Works for `Remove-KeePassDatabaseConfiguration`.
65 | * Implemented [#141](https://github.com/PSKeePass/PoShKeePass/issues/141) - Much stronger Pipeline support.
66 | * `-DatabaseProfileName` no longer needs to be specified to a KPPSObject pipeline recieving function.
67 | * Example: `Get-KeePassEntry -Title 'test' -DatabaseProfileName 'profile' | Remove-KeePassEntry`
68 | * All parent and object paths now are recieved by the pipeline which of course can be overridden by specifing the parameter.
69 | * Fixed [#140](https://github.com/PSKeePass/PoShKeePass/issues/140) and [#138](https://github.com/PSKeePass/PoShKeePass/issues/138) - by removing the `EncodeKeePassLib.ps1` script file as it is no longer in use.
70 | * Fixed [#144](https://github.com/PSKeePass/PoShKeePass/issues/144) - Removed Faultly logic which allowed for the KeePass Icon to get set to blank while updating an object.
71 | * Implemented [#143](https://github.com/PSKeePass/PoShKeePass/issues/143) There are no more dynamic parameters! So all of the gitches have left with them. They still support tab completion by using `Register-ArgumentCompleter`.
72 | * **Breaking Change** as this is only supported in powershell v5 and up, auto complete will not work in older versions.
73 | * Implemented [#118](https://github.com/PSKeePass/PoShKeePass/issues/118) - by adding support for keepasslib version `2.39.1`
74 | * The new file format version between the previous version of `2.34` and the latest apears to be much slower on some operations.
75 | * Testing the new Lib version against the previously suported version `2.34` all worked and appears to be backwards compatible. Also it does not upgrade the file format version.
76 | * Version can easily flipped back by modifying the global variable in the `.psm1` file.
77 | * This fixes [#131](https://github.com/PSKeePass/PoShKeePass/issues/131).
78 | * Fix [#145](https://github.com/PSKeePass/PoShKeePass/issues/145) - Updating a KeePass Entry now updates the modification time in UTC.
79 | * **Breaking Change** - Renamed the `LastAccessTime` and `LastModificationTime` properties to `LastAccessTimeUtc` and `LastModificationTimeUtc` to reflect that they are in UTC.
80 | * Addressed [#88](https://github.com/PSKeePass/PoShKeePass/issues/88) - `Get-KeePassEntry`
81 | * Since a Ps object is now always returned, all fields but the password are in plaintext. Now specifying the `-AsPlainText` will decode the password to plaintext.
82 | * This gives the user better control over when they expose the password as plaintext if need be.
83 | * Another improvement is there is now a `-WithCredential` parameter which adds a `.Credential` property to the return Entry PS Object.
84 | * This is not done by default as it has overhead.
85 | * This gives the user better options and does not require manual creation of the credential.
86 | * **Breaking Change** Since this has been implemeneted the `-AsPsCredential` parameter has been removed. The new method is better as it allows for multiple entries to be returned with thier cred objects instead of limiting it to 1 entry.
87 | * **Breaking Change** - `ConvertTo-KPPSObject` and all returned objects the `.FullPath` property now returns the true full path of the object. The `ParentGroup` property still exists and can be used as an alteranative data source for any lost functionality.
88 |
89 | ## v2.0.5.6
90 |
91 | * Update-KeePassEntry no longer creates a new entry, Entry history is retained, UUID is never changed, All time modificiation fields are now updated when appropriate.
92 | * [#127](https://github.com/PSKeePass/PoShKeePass/issues/127)
93 | * [#123](https://github.com/PSKeePass/PoShKeePass/issues/123)
94 | * [#120](https://github.com/PSKeePass/PoShKeePass/issues/120)
95 | * Code clean up in the internal functions
96 | * Removed unecessary comments.
97 | * Simplified parameter attributes, and formatting.
98 | * Updated error handling to use write-error and simplified handling.
99 | * Normalized repetative checks to their own `Test-X` functions and moved error\null handling inside.
100 | * Test-KPConnection - Checks to see if connection exists and and is open.
101 | * Test-KPPasswordValue - Correctly checks for supported types and moved error handling inside.
102 | * Fixed Dev Tool AutoVersioning Script, now updates psd1 version again.
103 | * Simplified `Import-KPLibrary` function.
104 | * Updated `ConvertTo-KPPSObject` to be construct PSObject differently and gained 86% speed performance improvement.
105 | * Created a `build.ps1` script to build the module for use and publishing to gallery
106 | * Updated `New-KPConnection` to prompt for user MasterKey (keepass passsword) via console prompt `Read-host` instead of `$Host.ui.PromptForCredential()`, this is much faster than loading the gui.
107 |
108 | ## v2.0.4.5
109 |
110 | * #135 - Restructured Module to a more modular structure. Single file per function, seperate root folders for exported functions vs internal functions, (functions, internal).
111 | * Added global variable `$Global:KeePassConfigurationFile` with the path of the config file and updated all references to file.
112 | * Updated formatting of readme and changelog to abide by md standards.
113 |
114 | ## v2.0.4.4
115 |
116 | * Some Community PR here, great help thank you
117 | * #53, #117 `-AsPSCredential` Support to `Get-KeePassEntry`
118 | * `-Title` Parameter Added to `Get-KeePassEntry`
119 | * General bug fixes #115, #116, #120, #123, #127
120 | * `New-KeePassDatabase` function added
121 |
122 | ## v2.0.4.3
123 |
124 | * [#133](https://github.com/PSKeePass/PoShKeePass/issues/133) Fixed
125 |
126 | ## v2.0.4.1
127 |
128 | * [#132](https://github.com/PSKeePass/PoShKeePass/issues/132) Fixed - Windows Defender identifies PoshKeepass as trojan. Please see the issue for more details.
129 |
130 | ## v2.0.4.0
131 |
132 | * #108 Fixed bug by capturing PSCredential to MasterKey variable.
133 |
134 | ## v2.0.3.9
135 |
136 | 1. #92 Added PowerShell Format XML File for creating PowerShell Object views.
137 | 2. #90 Updated default properties returned for KeePass Entries to Include the Notes Property. Did this via the new format XML file.
138 | 3. #67 Consolidated KeePass database connection and authentication functions. Thanks @Ninjigen for your help on this.
139 | 4. #67 Now supports authentication using all three methods as a combination: MasterKey, KeyFile, WindowsAccount.
140 | 5. #100 Fixed bug when using the `-MasterKey` options on and of the functions. The proper variable is now removed.
141 | 6. #95 Added internal function `Restore-KPConfigurationFile`. This is implemented to restore your configuration file from a previous version of the module, when updating from PSGallery.
142 | 7. Moved exported functions to the Module Manifest.
143 |
144 | ## v2.0.3.1
145 |
146 | ### Issue #79 - Added support Icon Management
147 |
148 | * Updated `New` and `Update` Entry and Group functions to support setting and updating Icon values.
149 | * Update `ConvertTo-KPPSObject` to output the IconId.
150 | * Added Pester Tests for adding and updating Icons.
151 | * Update `Get-KPDynamicParameters` to support creating the Icon dynamic param from the `KeePassLib.PwIcon` Enum.
152 |
153 | ## v2.0.3.0
154 |
155 | * Issue 68 - Update getting XML Configuration Document from `Get-Content` to creating a new `System.Xml.XmlDocument` object and using the `Load()` Method.
156 |
157 | ## v2.0.2.9
158 |
159 | * Issue 66 - Updated `ReadString()` method calls to `ReadSafe()` method calls.
160 | * Issue 71 - Updated to Use Proper String Interpolation.
161 | * Issue 72 - Removed Commented out code.
162 | * Issue 73 - Converted to Single Quotes Where Possible.
163 | * Issue 74 - Formatted Code consistently.
164 |
165 | ## v2.0.2.6
166 |
167 | * Updated `New-KeePassPassword` to output as `KeePassLib.Security.ProtectedString` - _This removed the plain text conversion to secure string.
168 | * Updated All New/Update Entry Functions to support _SecureString_ or _ProtectedString_ for the KeePassPassword Parameter.
169 |
170 | ## v2.0.2.1
171 |
172 | ## Added Dynamic Parameter MasterKey
173 |
174 | Added optional Parameter `-MasterKey` to core functions.
175 |
176 | This parameter was added to allow for easier scripting with databases that use a masterkey password.
177 |
178 | Previously if a masterkey password was used the updated functions would prompt the user of the masterkey after the funciton was called. This is still the behaviour if the masterkey is required but not specified.
179 |
180 | Functions Updated:
181 |
182 | 1. `New-KeePassEntry`
183 | 2. `New-KeePassGroup`
184 | 3. `Get-KeePassEntry`
185 | 4. `Get-KeePassGroup`
186 | 5. `Update-KeePassEntry`
187 | 6. `Update-KeePassGroup`
188 | 7. `Remove-KeePassEntry`
189 | 8. `Remove-KeePassGroup`
190 |
191 | ## Simplfied Dynamic Parameters
192 |
193 | Internally created a function that builds the commonly used Dynamic Parameters.
194 |
195 | `Get-KPDynamicParameter`
196 |
197 | ## Simplfied Building an Automatic Database Connection
198 |
199 | Internally created a function that builds the Database connection based off of the Database Configuration Profile Specified.
200 |
201 | `Invoke-KPConnection`
202 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Christian Lehrer, John Klann
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/PoshKeePass/readme.md:
--------------------------------------------------------------------------------
1 | # PowerShell KeePass
2 |
3 | [PoShKeePass](https://www.powershellgallery.com/packages/PoShKeePass) is a PowerShell module that combines the ease of the PowerShell cli and the extensibility of the [KeePassLib API](http://keepass.info/help/v2/setup.html) to provide a powerful and easy to use management and automating platform for [KeePass](http://keepass.info/) databases.
4 |
5 | ## Features
6 |
7 | 1. **Database Configuration Profiles** - Supports mutliple databases and authentication options.
8 | 2. **Getting, Creating, Updating, and Removing KeePass Entries and Groups** - All of these perform as much automatic database authentication as possible using the database configuration profile. For databases that use a masterkey (password) it will prompt for it.
9 | 3. **Generating KeePass Passwords** - Supports most character sets and advanced keepass options. Also supports creating password profiles that can be specified to create a new password with the same rule set.
10 |
11 | ## Getting Started
12 |
13 | ### Install
14 |
15 | ```powershell
16 | Install-Module -Name PoShKeePass
17 | ```
18 |
19 | ### Documentation
20 |
21 | Please check out our [Getting Started](https://github.com/PSKeePass/PoShKeePass/wiki/Getting-Started) documentation on our [wiki](https://github.com/PSKeePass/PoShKeePass/wiki).
22 |
23 | ## Important Notes & Reminders
24 |
25 | 1. Please always keep up to date **backups** of your KeePass database files .kdbx and .key files.
26 | 2. The module uses the KeePassLib 2.3.x which is embedded in the module file.
27 | 3. This module was built and tested in PowerShell 5 on Windows 10 but should work in PowerShell 4 and Windows 8.1 and Server 2012 R2 and up. It may work in some earlier versions but is currently untested and not supported. If you come across issues create an issue and I will look into fixing it or create a pull request.
28 | 4. There is an underlying framework that I wrote into the module to make all of the api calls that I will eventually expose for advanced scripting.
29 |
30 | ## Changelog
31 |
32 | Please review the [changelog document](https://github.com/PSKeePass/PoShKeePass/blob/master/changelog.md) for a full history.
33 |
34 | ## v.2.1.3.0
35 |
36 | * Added [#160](https://github.com/PSKeePass/PoShKeePass/issues/160) - Default Database Configuration Profile.
37 | * When set, the `-DatabaseProfileName` parameter is optional, and if not passed it will grab the default profile from the config.
38 | * To Set it up on an existing profile simply use the update command:
39 |
40 | ```powershell
41 | Update-KeePassDatabaseConfigurationProfile -DatabaseProfileName 'name' -Default
42 | ```
43 |
44 | * To Create a new profile as default use the new command:
45 |
46 | ```powershell
47 | New-KeePassDatabaseConfigurationProfile -DatabaseProfileName 'name' -Default -DatabasePath '' other options
48 | ```
49 |
50 | * This allows for calls to the main module functions without the `-DatabaseProfileName` parameter such as:
51 |
52 | ```powershell
53 | Get-KeePassEntry -UserName 'aUser'
54 | ```
55 |
56 | ## v.2.1.2.8
57 |
58 | * Added - [#84](https://github.com/PSKeePass/PoShKeePass/issues/84) - Manage Notes properties on KPGroup Objects.
59 |
60 | * v.2.1.2.6 - Added - [#158](https://github.com/PSKeePass/PoShKeePass/issues/158) - Added Update-KeePassDatabaseConfiguration function and tests.
61 |
62 | * v.2.1.2.5 - Fix - [#157](https://github.com/PSKeePass/PoShKeePass/issues/157) - Set New-KPConnection function back to internal function and no longer exports.
63 |
64 | ## v.2.1.2.4
65 |
66 | * Added Feature [#29](https://github.com/PSKeePass/PoShKeePass/issues/29) - Can now manage the Expiration Time/Enabled State of groups and entry.
67 |
68 | * v.2.1.2.3 - Fix [#64](https://github.com/PSKeePass/PoShKeePass/issues/65) - Review Message for grammar, clarified some messages as well.
69 |
70 | * v.2.1.2.2 - Fix [#156](https://github.com/PSKeePass/PoShKeePass/issues/156) - New-KeePassDatabase will now error out if kdbx file already exists, instead of silently overwriting an existing file.
71 |
72 | * v.2.1.2.1 - Fix [#149](https://github.com/PSKeePass/PoShKeePass/issues/149) - **Breaking Change** New-KeePassGroup and Update-KeePassGroup now return a KeePass PSObject via the ConvertTo-KPPsObject function.
73 |
74 | ## v.2.1.2.0
75 |
76 | * Fix [#148](https://github.com/PSKeePass/PoShKeePass/issues/148) - Can now update an entry multiple times, while retaining history and not through internal lib exception
77 | * Changes to build script
78 |
79 | ## v2.1.1.8
80 |
81 | ### Many fixes, features and improvements, please note the **Breaking Changes** Below
82 |
83 | * Fix [#129](https://github.com/PSKeePass/PoShKeePass/issues/129) - Can now pass Credential Object to `-MasterKey` Parameter
84 | * Fix/Implemented [#69](https://github.com/PSKeePass/PoShKeePass/issues/69) - All primary Functions return a Powershell object rather than a KeePass Object **This Includes Breaking changes!**.
85 | * **Breaking:**
86 | * Since a powershell object is now returned, in order to access the keepass object a child property has been added to the ps object, `.KPEntry` and `.KPGroup`.
87 | * Deprecated the `-AsPlainText` parameter on the `Get-KeePassGroup` function, the call will still work but it will present a warning message. This is being removed as it is no longer necessary.
88 | * **Non-Breaking:**
89 | * Moved how database profile name was being added to the ps object for better performance on conversion.
90 | * Implemented [#93](https://github.com/PSKeePass/PoShKeePass/issues/93) - `Get-KeePassEntry` Now supports `-Title` and `-UserName` parameters also via pipeline.
91 | * Normalized Error handling to remove repetitive code
92 | * Converted extraneous logic to parameter splatting
93 | * Code formatting and removed explict parameter attributes where not necessary.
94 | * Updated Object creation to use the `hashtable` method for performance over the `New-Object` + `Add-Memeber`.
95 | * Fix [#44](https://github.com/PSKeePass/PoShKeePass/issues/44) - Pipeline now Works for `Remove-KeePassDatabaseConfiguration`.
96 | * Implemented [#141](https://github.com/PSKeePass/PoShKeePass/issues/141) - Much stronger Pipeline support.
97 | * `-DatabaseProfileName` no longer needs to be specified to a KPPSObject pipeline recieving function.
98 | * Example: `Get-KeePassEntry -Title 'test' -DatabaseProfileName 'profile' | Remove-KeePassEntry`
99 | * All parent and object paths now are recieved by the pipeline which of course can be overridden by specifing the parameter.
100 | * Fixed [#140](https://github.com/PSKeePass/PoShKeePass/issues/140) and [#138](https://github.com/PSKeePass/PoShKeePass/issues/138) - by removing the `EncodeKeePassLib.ps1` script file as it is no longer in use.
101 | * Fixed [#144](https://github.com/PSKeePass/PoShKeePass/issues/144) - Removed Faultly logic which allowed for the KeePass Icon to get set to blank while updating an object.
102 | * Implemented [#143](https://github.com/PSKeePass/PoShKeePass/issues/143) There are no more dynamic parameters! So all of the gitches have left with them. They still support tab completion by using `Register-ArgumentCompleter`.
103 | * **Breaking Change** as this is only supported in powershell v5 and up, auto complete will not work in older versions.
104 | * Implemented [#118](https://github.com/PSKeePass/PoShKeePass/issues/118) - by adding support for keepasslib version `2.39.1`
105 | * The new file format version between the previous version of `2.34` and the latest apears to be much slower on some operations.
106 | * Testing the new Lib version against the previously suported version `2.34` all worked and appears to be backwards compatible. Also it does not upgrade the file format version.
107 | * Version can easily flipped back by modifying the global variable in the `.psm1` file.
108 | * This fixes [#131](https://github.com/PSKeePass/PoShKeePass/issues/131).
109 | * Fix [#145](https://github.com/PSKeePass/PoShKeePass/issues/145) - Updating a KeePass Entry now updates the modification time in UTC.
110 | * **Breaking Change** - Renamed the `LastAccessTime` and `LastModificationTime` properties to `LastAccessTimeUtc` and `LastModificationTimeUtc` to reflect that they are in UTC.
111 | * Addressed [#88](https://github.com/PSKeePass/PoShKeePass/issues/88) - `Get-KeePassEntry`
112 | * Since a Ps object is now always returned, all fields but the password are in plaintext. Now specifying the `-AsPlainText` will decode the password to plaintext.
113 | * This gives the user better control over when they expose the password as plaintext if need be.
114 | * Another improvement is there is now a `-WithCredential` parameter which adds a `.Credential` property to the return Entry PS Object.
115 | * This is not done by default as it has overhead.
116 | * This gives the user better options and does not require manual creation of the credential.
117 | * **Breaking Change** Since this has been implemeneted the `-AsPsCredential` parameter has been removed. The new method is better as it allows for multiple entries to be returned with thier cred objects instead of limiting it to 1 entry.
118 | * **Breaking Change** - `ConvertTo-KPPSObject` and all returned objects the `.FullPath` property now returns the true full path of the object. The `ParentGroup` property still exists and can be used as an alteranative data source for any lost functionality.
119 |
120 | ## Known Issues
121 |
122 | See the [Known-Issue](https://github.com/PSKeePass/PoShKeePass/issues?q=is%3Aissue+is%3Aopen+label%3AKnown-Issue) tag to get a list of known issues and their status.
123 |
124 | ## Contributing
125 |
126 | * If you are insterested in fixing issues and contributing directly to the code base, please see the documentation on [How to Contribute](https://github.com/PSKeePass/PoShKeePass/blob/master/contribute.md).
127 | * If you come across a bug or have a feature request feel free to create an issue with the appropriate label.
128 |
129 | ## Shout-Outs
130 |
131 | * PSKeePass would like to thank [Jason Fossen](https://github.com/JasonFossen) for his [initial work](https://cyber-defense.sans.org/blog/2015/08/13/powershell-for-keepass-sample-script) with KeePass in PowerShell.
132 | * PSKeePass would like to thank [Christian Lehrer](https://github.com/chritea) for his powershell keepass work and contributions.
133 | * PSKeePass would like to thank [Ninjigen](https://github.com/Ninjigen) for his powershell keepass work and contributions.
134 | * PSKeePass would like to thank [Andrzej Pilacik](http://www.apdba.com/) (aka @cypisek77) for his review and feedback on documentation and over all rubber ducking.
135 |
136 | ## License
137 |
138 | Copyright (c) 2019 [John Klann](https://github.com/jkdba). All rights reserved.
139 |
140 | Licensed under the [MIT](https://github.com/PSKeePass/PoShKeePass/blob/master/license) License.
141 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Public/Register-KeePassSecretVault.ps1:
--------------------------------------------------------------------------------
1 | function Register-KeepassSecretVault {
2 | <#
3 | .SYNOPSIS
4 | Registers a Keepass Vault with the Secret Management engine
5 | .DESCRIPTION
6 | Enables you to register a keepass vault with the secret management engine, with more discoverable parameters and
7 | safety checks
8 | .EXAMPLE
9 | PS C:\> Register-KeepassSecretVault -Path $HOME/Desktop/MyVault.kdbx
10 | Explanation of what the example does
11 | #>
12 |
13 | [CmdletBinding(DefaultParameterSetName = 'UseMasterPassword')]
14 | param(
15 | #Path to your kdbx database file
16 | [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)][String]$Path,
17 | #Name of your secret management vault. Defaults to the base filename
18 | [String]$Name,
19 | #Path to your kdbx keyfile path if you use one. Only v1 keyfiles (2.44 and older) are currently supported
20 | [String]$KeyPath,
21 | #Prompt for a master password for the vault
22 | [Switch]$UseMasterPassword,
23 | #Use your Windows Login account as an authentication factor for the vault
24 | [Switch]$UseWindowsAccount,
25 | #Automatically create a keepass database with the specifications you provided
26 | [Parameter(ParameterSetName='Create')][Switch]$Create,
27 | #Specify the master password to use when automatically creating a vault
28 | [Parameter(ParameterSetName='Create')][SecureString]$MasterPassword,
29 | #Report key titles as full paths including folders. Useful if you want to view conflicting Keys
30 | [Switch]$ShowFullTitle,
31 | #Show Recycle Bin entries
32 | [Switch]$ShowRecycleBin,
33 | #Don't validate the vault operation upon registration. This is useful for pre-staging
34 | #vaults or vault configurations in deployments.
35 | [Parameter(ParameterSetName='SkipValidate')][Switch]$SkipValidate
36 | )
37 |
38 | $ErrorActionPreference = 'Stop'
39 | if (-not ($SkipValidate -or $Create)) {
40 | $Path = Resolve-Path $Path
41 | }
42 | if (-not $Name) { $Name = ([IO.FileInfo]$Path).BaseName }
43 | if ($UseWindowsAccount -and -not ($PSEdition -eq 'Desktop' -or $IsWindows)) {
44 | throw [NotSupportedException]'-UseWindowsAccount parameter is only supported on Windows'
45 | }
46 | if (-not $UseMasterPassword -and -not $UseWindowsAccount -and -not $KeyPath) {
47 | throw [InvalidOperationException]'No authentication methods specified. You must specify at least one of: UseMasterPassword, UseWindowsAccount, or KeyPath'
48 | }
49 | if ($Create) {
50 | $ConnectKPDBParams = @{
51 | Path = $Path
52 | KeyPath = $KeyPath
53 | UseWindowsAccount = $UseWindowsAccount
54 | Create = $Create
55 | MasterPassword = $MasterPassword
56 | }
57 | $dbConnection = Connect-KeePassDatabase @ConnectKPDBParams
58 | if (-not $dbConnection) {throw 'Connect-KeePassDatabase was executed but a database connection was not returned. This should not happen.'}
59 | }
60 |
61 | #BUG: Workaround for https://github.com/PowerShell/SecretManagement/issues/103
62 | if (Get-Module SecretManagement.KeePass -ErrorAction SilentlyContinue -OutVariable KeePassModule) {
63 | $ModuleName = $KeePassModule.Path
64 | } else {
65 | $ModuleName = 'SecretManagement.KeePass'
66 | }
67 |
68 | Register-SecretVault -ModuleName $ModuleName -Name $Name -VaultParameters @{
69 | Path = $Path
70 | UseMasterPassword = $UseMasterPassword.IsPresent
71 | UseWindowsAccount = $UseWindowsAccount.IsPresent
72 | KeyPath = $KeyPath
73 | ShowFullTitle = $ShowFullTitle.IsPresent
74 | ShowRecycleBin = $ShowRecycleBin.IsPresent
75 | }
76 |
77 | if (-not (Get-SecretVault -Name $Name)) { throw 'Register-SecretVault did not return an error but the vault is not registered.' }
78 | #Create does the same validation
79 | if (-not $SkipValidate -and -not $Create) {
80 | if (-not (Test-SecretVault -VaultName $Name)) {
81 | Unregister-SecretVault -Name $Name -ErrorAction SilentlyContinue
82 | throw "$Name is an invalid vault configuration, removing. Consider using -SkipValidate if you wish to pre-load a configuration without testing it"
83 | }
84 | }
85 |
86 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Public/Unlock-KeePassSecretVault.ps1:
--------------------------------------------------------------------------------
1 | function Unlock-KeePassSecretVault {
2 | <#
3 | .SYNOPSIS
4 | Enables the entry of a master password prior to vault activities for unattended scenarios.
5 | If registering a vault for the first time unattended, be sure to use the -SkipValidate parameter of Register-KeepassSecretVault
6 | .EXAMPLE
7 | Get-SecretVault 'MyKeepassVault' | Unlock-KeePassSecretVault -Password $MySecureString
8 | .EXAMPLE
9 | Unlock-KeePassSecretVault -Name 'MyKeepassVault' -Password $MySecureString
10 | #>
11 | param (
12 | [Parameter(Mandatory)][SecureString]$Password,
13 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)][String]$Name
14 | )
15 |
16 | Write-PSFMessage -Level Warning 'DEPRECATED: This command has been deprecated. Please use the SecretManagement command Unlock-SecretVault instead.'
17 | Microsoft.PowerShell.SecretManagement\Unlock-SecretVault -Password $Password -Name $Name
18 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/ConvertTo-ReadOnlyDictionary.ps1:
--------------------------------------------------------------------------------
1 | using namespace System.Collections.ObjectModel
2 | using namespace System.Collections.Generic
3 | function ConvertTo-ReadOnlyDictionary {
4 | <#
5 | .SYNOPSIS
6 | Converts a hashtable to a ReadOnlyDictionary[String,Object]. Needed for SecretInformation
7 | #>
8 | [CmdletBinding()]
9 | param(
10 | [Parameter(ValueFromPipeline)][hashtable]$hashtable
11 | )
12 | process {
13 | $dictionary = [SortedDictionary[string,object]]::new([StringComparer]::OrdinalIgnoreCase)
14 | $hashtable.GetEnumerator().foreach{
15 | $dictionary[$_.Name] = $_.Value
16 | }
17 | [ReadOnlyDictionary[string,object]]::new($dictionary)
18 | }
19 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/GetKeepassParams.ps1:
--------------------------------------------------------------------------------
1 | function GetKeepassParams ([String]$VaultName, [Hashtable]$AdditionalParameters) {
2 | $KeepassParams = @{}
3 | if ($VaultName) {
4 | $KeepassParams.KeePassConnection = (Get-Variable -Scope Script -Name "Vault_$VaultName").Value
5 | }
6 | return $KeepassParams
7 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/Test-DBChanged.ps1:
--------------------------------------------------------------------------------
1 | function Test-DBChanged ($dbConnection) {
2 | [string]$currentDbFileHash = (Get-FileHash -Path $dbConnection.IOConnectionInfo.Path).Hash
3 | [byte[]]$dbHashBytes = $dbConnection.HashOfFileOnDisk
4 |
5 | #Convert to String
6 | [string]$dbHash = $dbHashBytes.foreach{[String]::Format('{0:X2}', $_)} -join ''
7 |
8 |
9 | #Return true or false
10 | $currentDbFileHash -ne $dbHash
11 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/Test-Verbose.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/Test-Verbose.ps1
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/Unlock-SecureString.ps1:
--------------------------------------------------------------------------------
1 | function Unlock-SecureString ([SecureString]$SecureString) {
2 | <#
3 | .SYNOPSIS
4 | Compatibility function to convert a secure string to plain text
5 | .OUTPUT
6 | String
7 | #>
8 | if ($PSVersionTable.PSVersion -ge '6.0.0') {
9 | ConvertFrom-SecureString -AsPlainText -SecureString $SecureString
10 | } else {
11 | #Legacy Windows Powershell Workaround Method
12 | [PSCredential]::new('SecureString',$SecureString).GetNetworkCredential().Password
13 | }
14 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Private/VaultError.ps1:
--------------------------------------------------------------------------------
1 | function VaultError ([String]$Message) {
2 | <#
3 | .SYNOPSIS
4 | Takes a terminating error and first writes it as a non-terminating error to the user to better surface the issue.
5 | #>
6 |
7 | #FIXME: Use regular errors if https://github.com/PowerShell/SecretManagement/issues/102 is resolved
8 | Write-PSFMessage -Level Error "Vault ${VaultName}: $Message"
9 | throw "Vault ${VaultName}: $Message"
10 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Connect-KeepassDatabase.ps1:
--------------------------------------------------------------------------------
1 | using namespace KeePassLib
2 | using namespace KeePassLib.Keys
3 | using namespace KeePassLib.Serialization
4 | using namespace KeePassLib.Interfaces
5 | using namespace System.Runtime.InteropServices
6 |
7 | function Connect-KeePassDatabase {
8 | <#
9 | .SYNOPSIS
10 | Open a connection to a keepass database
11 | #>
12 | param (
13 | #Path to the Keepass database
14 | [Parameter(Mandatory)][String]$Path,
15 | #Prompt for a master password
16 | [Switch]$UseMasterPassword,
17 | #The master password to unlock the database
18 | [SecureString]$MasterPassword,
19 | #The path to the key file for the database
20 | [String]$KeyPath,
21 | #Whether to use a secure key stored via DPAPI in your windows profile
22 | [Switch]$UseWindowsAccount,
23 | #Create a new database at the specified path. Will error if a database does not exist at the specified path
24 | [Switch]$Create,
25 | #Allow clobbering an existing database
26 | [Switch]$AllowClobber
27 | )
28 |
29 | $DBCompositeKey = [CompositeKey]::new()
30 |
31 | if (-not $MasterPassword -and -not $KeyPath -and -not $UseWindowsAccount) {
32 | Write-PSFMessage -Level Verbose "No vault authentication mechanisms specified. Assuming you wanted to prompt for the Master Password"
33 | $UseMasterPassword = $true
34 | }
35 |
36 | if ($UseMasterPassword -and -not $MasterPassword) {
37 | $CredentialParams = @{
38 | Username = 'Keepass Master Password'
39 | Message = "Enter the Keepass Master password for: $Path"
40 | }
41 | #PS7+ Only
42 | if ($PSEdition -ne 'Desktop') {
43 | $CredentialParams.Title = 'Keepass Master Password'
44 | }
45 | $MasterPassword = (Get-Credential @CredentialParams).Password
46 | }
47 |
48 | #NOTE: Order in which the CompositeKey is created is important and must follow the order of : MasterKey, KeyFile, Windows Account
49 | if ($MasterPassword) {
50 | $DBCompositeKey.AddUserKey(
51 | [KcpPassword]::new(
52 | #Decode SecureString
53 | [Marshal]::PtrToStringUni([Marshal]::SecureStringToBSTR($MasterPassword))
54 | )
55 | )
56 | }
57 |
58 | if ($KeyPath) {
59 |
60 | if (-not (Test-Path $KeyPath)) {
61 | if ($Create) {
62 | #Create a new key
63 | [KcpKeyFile]::Create(
64 | $KeyPath,
65 | $null
66 | )
67 | } else {
68 | #Will emit a path not found error
69 | Resolve-Path $KeyPath
70 | }
71 | } else {
72 | Write-PSFMessage -Level Verbose "A keepass key file was already found at $KeyPath. Reusing this key for safety. Please manually delete this key if you wish to use a new one"
73 | }
74 |
75 | $resolvedKeyPath = Resolve-Path $KeyPath
76 | # Assume UNC path if no drive present.
77 | if ($Null -eq $resolvedKeyPath.Drive) {
78 | $dbCompositeKey.AddUserKey(
79 | [KcpKeyFile]::new(
80 | $resolvedKeyPath.ProviderPath, #Path to keyfile
81 | $true #Error if it is a database file
82 | )
83 | )
84 | } else {
85 | $dbCompositeKey.AddUserKey(
86 | [KcpKeyFile]::new(
87 | $resolvedKeyPath, #Path to keyfile
88 | $true #Error if it is a database file
89 | )
90 | )
91 | }
92 | }
93 |
94 | if ($UseWindowsAccount) {
95 | if ($PSVersionTable.PSVersion -gt '5.99.99' -and -not $IsWindows) {
96 | throw [NotSupportedException]'The -UseWindowsAccount parameter is only supported on a Windows Platform'
97 | }
98 | $DBCompositeKey.AddUserKey([KcpUserAccount]::new())
99 | }
100 |
101 | $ParentPath = (Resolve-Path ($Path | Split-Path)).ProviderPath
102 | $DBFile = $Path | Split-Path -Leaf
103 | $resolvedPath = Join-Path -Path $ParentPath -ChildPath $DBFile
104 |
105 | $DBConnection = [PWDatabase]::new()
106 | $DBConnectionInfo = [IOConnectionInfo]::FromPath($resolvedPath)
107 |
108 | if ($Create) {
109 | if (-not $AllowClobber -and (Test-Path $resolvedPath)) {
110 | throw "-Create was specified but a database already exists at $resolvedPath. Please specify -AllowClobber to overwrite the database."
111 | }
112 | $DBConnection.New(
113 | $DBConnectionInfo,
114 | $DBCompositeKey
115 | )
116 | $DBConnection.Save($null)
117 | }
118 |
119 | #Establish the connection
120 |
121 | $DBConnection.Open(
122 | $DBConnectionInfo,
123 | $DBCompositeKey,
124 | $null #No status logger
125 | )
126 | if (-not $DBConnection.IsOpen) { throw "Unable to connect to the database at $resolvedPath. Please check you supplied proper credentials" }
127 | $DBConnection
128 | }
129 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Get-Secret.ps1:
--------------------------------------------------------------------------------
1 | function Get-Secret {
2 | [CmdletBinding()]
3 | param (
4 | [string]$Name,
5 | [Alias('Vault')][string]$VaultName,
6 | [Alias('VaultParameters')][hashtable]$AdditionalParameters = (Get-SecretVault -Name $VaultName).VaultParameters
7 | )
8 | if ($AdditionalParameters.Verbose) { $VerbosePreference = 'continue' }
9 |
10 | Write-PSFMessage "Searching Entry with Name=$Name"
11 | if (-not (Test-SecretVault -VaultName $vaultName -AdditionalParameters $AdditionalParameters)) {
12 | Write-PSFMessage -Level Error 'There appears to be an issue with the vault (Test-SecretVault returned false)' -Target "$Name"
13 | throw 'There appears to be an issue with the vault (Test-SecretVault returned false)'
14 | }
15 |
16 | if (-not $Name) {
17 | Write-PSFMessage -Level Error 'You must specify a secret Name' -Target "$Name"
18 | throw 'You must specify a secret Name'
19 | }
20 |
21 | $KeepassParams = GetKeepassParams $VaultName $AdditionalParameters
22 |
23 | if ($Name) { $KeePassParams.Title = $Name }
24 | $keepassGetResult = Get-SecretInfo -Vault $vaultName -Filter $Name -AsKPPSObject
25 |
26 | if ($null -eq $keepassGetResult) {
27 | Write-PSFMessage "No Keepass Entry found" -Target $Name
28 | return
29 | }
30 | if ($keepassGetResult.count -gt 1) {
31 | Write-PSFMessage -Level Error "Multiple ambiguous entries found for $Name, please remove the duplicate entry or specify the full path of the secret" -Target "$Name"
32 | throw "Multiple ambiguous entries found for $Name, please remove the duplicate entry or specify the full path of the secret"
33 | }
34 | $result = if (-not $keepassGetResult.Username) {
35 | $keepassGetResult.Password
36 | }
37 | else {
38 | [PSCredential]::new($KeepassGetResult.UserName, $KeepassGetResult.Password)
39 | }
40 | return $result
41 | }
42 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Get-SecretInfo.ps1:
--------------------------------------------------------------------------------
1 | using namespace Microsoft.PowerShell.SecretManagement
2 | using namespace System.Collections.ObjectModel
3 | function Get-SecretInfo {
4 | [CmdletBinding()]
5 | param(
6 | [Alias('Name')][string]$Filter,
7 | [Alias('Vault')][string]$VaultName = (Get-SecretVault).VaultName,
8 | [Alias('VaultParameters')][hashtable]$AdditionalParameters = (Get-SecretVault -Name $VaultName).VaultParameters,
9 | [Switch]$AsKPPSObject
10 | )
11 | if ($AdditionalParameters.Verbose) {$VerbosePreference = 'continue'}
12 |
13 | if (-not (Test-SecretVault -VaultName $vaultName)) {
14 | Write-PSFMessage -Level Error 'There appears to be an issue with the vault (Test-SecretVault returned false)'
15 | return $false
16 | }
17 |
18 | $KeepassParams = GetKeepassParams -VaultName $VaultName -AdditionalParameters $AdditionalParameters
19 | $KeepassGetResult = Get-KPEntry @KeepassParams | ConvertTo-KPPSObject
20 | if (-not $AdditionalParameters.ShowRecycleBin) {
21 | $KeepassGetResult = $KeepassGetResult | Where-Object FullPath -notmatch '^[^\/]+?\/Recycle ?Bin$'
22 | }
23 |
24 | #TODO: Split this off into private function for testing
25 | function Get-KPSecretName ([PSCustomObject]$KPPSObject) {
26 | <#
27 | .SYNOPSIS
28 | Gets the secret name for the vault context, contingent on some parameters
29 | WARNING: Relies on external context $AdditionalParameters
30 | #>
31 | if ($AdditionalParameters.ShowFullTitle) {
32 | #Strip everything before the first /
33 | $i = $KPPSObject.FullPath.IndexOf('/')
34 | $prefix = if ($i -eq -1) {$null} else {
35 | $KPPSObject.FullPath.Substring($i+1)
36 | }
37 | #Output Prefix/Title
38 | if ($prefix) {
39 | return $prefix,$KPPSObject.Title -join '/'
40 | } else {
41 | return $KPPSObject.Title
42 | }
43 | } else {
44 | return $KPPSObject.Title
45 | }
46 | }
47 |
48 | if ($Filter) {
49 | $KeepassGetResult = $KeepassGetResult | Where-Object {
50 | (Get-KPSecretName $PSItem) -like $Filter
51 | }
52 | }
53 |
54 | #Used by internal commands like Get-Secret
55 | if ($AsKPPSObject) {
56 | return $KeepassGetResult
57 | }
58 |
59 | [Object[]]$secretInfoResult = $KeepassGetResult | Foreach-Object {
60 | if (-not $PSItem.Title) {
61 | Write-PSFMessage -Level Warning "Keepass Entry with blank title found at $($PSItem.FullPath). These are not currently supported and will be omitted"
62 | return
63 | }
64 |
65 | [ReadOnlyDictionary[String,Object]]$metadata = [ordered]@{
66 | UUID = $PSItem.uuid.ToHexString()
67 | Title = $PSItem.Title
68 | ParentGroup = $PSItem.ParentGroup
69 | Path = $PSItem.FullPath,$PSItem.Title -join '/'
70 | Notes = $PSItem.Notes
71 | URL = $PSItem.Url
72 | Tags = $PSItem.Tags -join ', '
73 | Created = $PSItem.CreationTime
74 | Accessed = $PSItem.LastAccessTimeUtc
75 | Modified = $PSItem.LastModifiedTimeUtc
76 | Moved = $PSItem.LocationChanged
77 | IconName = $PSItem.IconId
78 | UsageCount = $PSItem.UsageCount
79 | Expires = if ($Expires) {$PSItem.ExpireTime}
80 | } | ConvertTo-ReadOnlyDictionary
81 |
82 | #TODO: Find out why the fully qualified is required on Linux even though using Namespace is defined above
83 | [Microsoft.PowerShell.SecretManagement.SecretInformation]::new(
84 | (Get-KPSecretName $PSItem), #string name
85 | #TODO: Add logic to mark as securestring if there is no username
86 | [Microsoft.PowerShell.SecretManagement.SecretType]::PSCredential, #SecretType type
87 | $VaultName, #string vaultName
88 | $metadata #ReadOnlyDictionary[string,object] metadata
89 | )
90 | }
91 |
92 | [Object[]]$sortedInfoResult = $secretInfoResult | Sort-Object -Unique -Property Name
93 | if ($sortedInfoResult.count -lt $secretInfoResult.count) {
94 | $nonUniqueFilteredRecords = Compare-Object $sortedInfoResult $secretInfoResult -Property Name | Where-Object SideIndicator -eq '=>'
95 | Write-PSFMessage -Level Error "Vault ${VaultName}: Entries with non-unique titles were detected, the duplicates were filtered out. $(if (-not $additionalParameters.ShowFullTitle) {'Consider adding the ShowFullTitle VaultParameter to your vault registration'})"
96 | Write-PSFMessage -Level Error "Vault ${VaultName}: Filtered Non-Unique Titles: $($nonUniqueFilteredRecords.Name -join ', ')"
97 | }
98 | $sortedInfoResult
99 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Remove-Secret.ps1:
--------------------------------------------------------------------------------
1 | function Remove-Secret {
2 | [CmdletBinding()]
3 | param (
4 | [ValidateNotNullOrEmpty()][string]$Name,
5 | [Alias('Vault')][string]$VaultName,
6 | [Alias('VaultParameters')][hashtable]$AdditionalParameters = (Get-SecretVault -Name $VaultName).VaultParameters
7 | )
8 | if ($AdditionalParameters.Verbose) {$VerbosePreference = 'continue'}
9 | if (-not (Test-SecretVault -VaultName $vaultName)) {
10 | VaultError 'There appears to be an issue with the vault (Test-SecretVault returned false)'
11 | return $false
12 | }
13 | $KeepassParams = GetKeepassParams $VaultName $AdditionalParameters
14 |
15 | $GetKeePassResult = Get-SecretInfo -VaultName $VaultName -Name $Name -AsKPPSObject
16 | if ($GetKeePassResult.count -gt 1) {
17 | VaultError "There are multiple entries with the name $Name and Remove-Secret will not proceed for safety."
18 | return $false
19 | }
20 | if (-not $GetKeePassResult) {
21 | VaultError "No Keepass Entry named $Name found"
22 | return $false
23 | }
24 |
25 | Remove-KPEntry @KeepassParams -KeePassEntry $GetKeePassResult.KPEntry -ErrorAction stop -Confirm:$false
26 |
27 | return $true
28 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Set-Secret.ps1:
--------------------------------------------------------------------------------
1 | using namespace KeepassLib.Security
2 | function Set-Secret {
3 | [CmdletBinding()]
4 | param (
5 | [string]$Name,
6 | [object]$Secret,
7 | [Alias('Vault')][string]$VaultName,
8 | [Alias('VaultParameters')][hashtable]$AdditionalParameters = (Get-SecretVault -Name $VaultName).VaultParameters
9 | )
10 | if ($AdditionalParameters.Verbose) { $VerbosePreference = 'continue' }
11 |
12 | if (-not $Name) {
13 | Write-PSFMessage -Level Error ([NotSupportedException]'The -Name parameter is mandatory for the KeePass vault')
14 | return $false
15 | }
16 | if (-not (Test-SecretVault -VaultName $vaultName)) {
17 | Write-PSFMessage -Level Error 'There appears to be an issue with the vault (Test-SecretVault returned false)'
18 | return $false
19 | }
20 | $KeepassParams = GetKeepassParams $VaultName $AdditionalParameters
21 | # Write-PSFMessage -Level Verbose "KeepassParams=$($KeepassParams|ConvertTo-JSon -Compress)" -Tag Sherlock -Target $Name
22 | # Write-PSFMessage -Level Verbose "AdditionalParameters=$($AdditionalParameters|ConvertTo-JSon -Compress)" -Tag Sherlock -Target $Name
23 |
24 |
25 | switch ($Secret.GetType()) {
26 | ([String]) {
27 | $KeepassParams.Username = $null
28 | $KeepassParams.KeepassPassword = [ProtectedString]::New($true, $Secret)
29 | break
30 | }
31 | ([SecureString]) {
32 | $KeepassParams.Username = $null
33 | $KeepassParams.KeepassPassword = [ProtectedString]::New($true, (Unlock-SecureString $Secret))
34 | break
35 | }
36 | ([PSCredential]) {
37 | $KeepassParams.Username = $Secret.Username
38 | $KeepassParams.KeepassPassword = [ProtectedString]::New($true, $Secret.GetNetworkCredential().Password)
39 | break
40 | }
41 | default {
42 | Write-PSFMessage -Level Error ([NotImplementedException]'This vault provider only accepts string, securestring, and PSCredential secrets')
43 | return $false
44 | }
45 | }
46 |
47 | if (Get-SecretInfo -Name $Name -Vault $VaultName) {
48 | Write-PSFMessage "Updating Keepass Entry" -Target $Name -Tag Update
49 |
50 | try {
51 | # $KeepassEntry = Get-SecretInfo -Name $Name -Vault $VaultName -AsKPPSObject
52 | # Need to get the original KPEntry Object for modification
53 | $KeepassParamsGetKPEntry = GetKeepassParams $VaultName $AdditionalParameters
54 |
55 | $KeepassResults = Get-KPEntry @KeepassParamsGetKPEntry -Title $Name
56 | if (-not $AdditionalParameters.ShowRecycleBin) {
57 | $countBeforeRemoval = $KeepassResults.count
58 | Write-PSFMessage -Level Verbose "Removing found entries with FullPath containing 'RecycleBin'"
59 | # $KeepassResults = $KeepassResults | Where-Object FullPath -notmatch '^[^\/]+?\/Recycle ?Bin$'
60 | $KeepassResults = $KeepassResults | Where-Object { $_.ParentGroup.GetFullPath('/', $true) -notmatch '^[^\/]+?\/Recycle ?Bin$' }
61 | Write-PSFMessage -Level Verbose "Removed $($countBeforeRemoval - $KeepassResults.count) Entries, $countBeforeRemoval entries before and $($KeepassResults.count) after"
62 | }
63 |
64 | # $fullPathes = $KeepassResults|Foreach-Object {
65 | # $path=$_.ParentGroup.GetFullPath('/', $true)
66 | # $title = $_.Strings.ReadSafe('Title')
67 | # "Title= $title; Fullpath= $Path;"
68 | # }
69 | # Write-PSFMessage -level Host -Tag Sherlock "fullPathes=$($fullPathes -join ';')"
70 | if ($KeepassResults.count -gt 1) {
71 | Write-PSFMessage -Level Error "Retrieved $($KeepassResults.count) Keepass-Entries, narrow down the criteria"
72 | return
73 | }
74 | $KeepassEntry = $KeepassResults #[1]
75 | # $KeepassEntry = Get-KPEntry -KeePassConnection $KeepassParams.KeepassConnection -Title $Title
76 | Write-PSFMessage "Found KeepassEntry=$KeepassEntry" -Level Debug
77 | # Write-PSFMessage "`$KeepassEntry.getType()=$($KeepassEntry.GetType())" -tag "Sherlock"
78 | }
79 | catch {
80 | Write-PSFMessage -Level Error "Fehler bei Get-KPEntry, $_"
81 | }
82 | # Write-PSFMessage -Level Warning "Vault ${VaultName}: A secret with the title $Name already exists. This vault currently does not support overwriting secrets. Please remove the secret with Remove-Secret first."
83 | # return $false
84 |
85 | $KPEntry = Set-KPEntry @KeepassParams -Title $Name -PassThru -KeePassEntry $KeepassEntry -Confirm:$False
86 |
87 | # Write-PSFMessage -Level Warning "Vault ${VaultName}: A secret with the title $Name already exists. This vault currently does not support overwriting secrets. Please remove the secret with Remove-Secret first."
88 | # return $false
89 | }
90 | else {
91 | #Set default group
92 | #TODO: Support Creating Secrets with paths
93 | Write-PSFMessage "Adding Keepass Entry" -Target $Name -Tag Add
94 | $KeepassParams.KeePassGroup = (Get-Variable "VAULT_$VaultName").Value.RootGroup
95 | $KPEntry = Add-KPEntry @KeepassParams -Title $Name -PassThru
96 | }
97 |
98 | #Save the changes immediately
99 | #TODO: Consider making this optional as a vault parameter
100 | $KeepassParams.KeepassConnection.Save($null)
101 |
102 | return [Bool]($KPEntry)
103 | }
104 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Test-SecretVault.ps1:
--------------------------------------------------------------------------------
1 | function Test-SecretVault {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter(ValueFromPipelineByPropertyName,Mandatory)]
5 | [Alias('Vault')][Alias('Name')][string]$VaultName,
6 |
7 | #This intelligent default is here because if you call test-secretvault from other commands it doesn't populate like it does when called from SecretManagement
8 | [Parameter(ValueFromPipelineByPropertyName)]
9 | [Alias('VaultParameters')][hashtable]$AdditionalParameters = (get-secretvault $VaultName).VaultParameters
10 | )
11 | if ($AdditionalParameters.Verbose) {$VerbosePreference = 'continue'}
12 |
13 | Write-PSFMessage -Level Verbose "SecretManagement: Testing Vault ${VaultName}"
14 | #TODO: Hash vault parameter settings and reset vault state if they change. May be a bug if user changes vault parameters in same session
15 |
16 | #Test if connection already open, no need to do further testing if so
17 | try {
18 | $DBConnection = (Get-Variable -Name "Vault_$VaultName" -Scope Script -ErrorAction Stop).Value
19 | if (-not $DBConnection.isOpen) {
20 | Write-PSFMessage -Level Error 'Connection closed, starting a new connection'
21 | return $false
22 | }
23 | if (Test-DBChanged $DBConnection) {
24 | $dbConnection.close()
25 | Write-PSFMessage -Level Error 'Database file on disk has changed, starting a new connection'
26 | return $false
27 | }
28 | Write-PSFMessage -Level Verbose "Vault ${VaultName}: Connection already open, using existing connection"
29 | return $dbConnection.isOpen
30 | } catch {
31 | Write-PSFMessage -Level Verbose "${VaultName}: $PSItem"
32 | }
33 |
34 | #Basic Sanity Checks
35 | if (-not $VaultName) {
36 | Write-PSFMessage -Level Error 'Keepass: You must specify a Vault Name to test'
37 | return $false
38 | }
39 |
40 | if (-not $AdditionalParameters.Path) {
41 | #TODO: Create a default vault if path isn't supplied
42 | #TODO: Add ThrowUser to throw outside of module scope
43 | Write-PSFMessage -Level Error 'You must specify the Path vault parameter as a path to your KeePass Database'
44 | return $false
45 | }
46 |
47 | if (-not (Test-Path $AdditionalParameters.Path)) {
48 | Write-PSFMessage -Level Error "Could not find the keepass database $($AdditionalParameters.Path). Please verify the file exists or re-register the vault"
49 | return $false
50 | }
51 |
52 | #3 Scenarios Supported: Master PW, Keyfile, PW + Keyfile
53 | $ConnectKPDBParams = @{
54 | Path = $AdditionalParameters.Path
55 | KeyPath = $AdditionalParameters.KeyPath
56 | UseWindowsAccount = $AdditionalParameters.UseWindowsAccount
57 | UseMasterPassword = $AdditionalParameters.UseMasterPassword
58 | }
59 |
60 | [SecureString]$vaultMasterPassword = Get-Variable -Name "Vault_${VaultName}_MasterPassword" -ValueOnly -ErrorAction SilentlyContinue
61 | if ($vaultMasterPassword) {
62 | Write-PSFMessage -Level Verbose "Cached Master Password Found for $VaultName"
63 | $ConnectKPDBParams.MasterPassword = $vaultMasterPassword
64 | }
65 |
66 | try {
67 | $DBConnection = Connect-KeePassDatabase @ConnectKPDBParams
68 | } catch {
69 | Write-PSFMessage -Level Error $PSItem
70 | }
71 |
72 |
73 | if ($DBConnection.IsOpen) {
74 | Set-Variable -Name "Vault_$VaultName" -Scope Script -Value $DBConnection
75 | return $DBConnection.IsOpen
76 | }
77 |
78 | #If we get this far something went wrong
79 | Write-PSFMessage -Level Error "Unable to open connection to the database"
80 | return $false
81 |
82 | # if (-not $AdditionalParameters.Keypath -or $AdditionalParameters.UseMasterKey) {
83 |
84 | # }
85 | # if (-not (Get-KeePassDatabaseConfiguration -DatabaseProfileName $VaultName)) {
86 | # New-KeePassDatabaseConfiguration @KeePassDBConfigParams
87 | # Write-PSFMessage -Level Verbose "Vault ${VaultName}: A PoshKeePass database configuration was not found but was created."
88 | # return $true
89 | # }
90 | # try {
91 | # Get-KeePassEntry -DatabaseProfileName $VaultName -MasterKey $VaultMasterKey -Title '__SECRETMANAGEMENT__TESTSECRET_SHOULDNOTEXIST' -ErrorAction Stop
92 | # } catch {
93 | # Clear-Variable -Name "Vault_$VaultName" -Scope Script -ErrorAction SilentlyContinue
94 | # throw $PSItem
95 | # }
96 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Unlock-SecretVault.ps1:
--------------------------------------------------------------------------------
1 | function Unlock-SecretVault {
2 | param (
3 | [Parameter(Mandatory)][SecureString]$Password,
4 | [Parameter(Mandatory)][Alias('Vault')][Alias('Name')][String]$VaultName,
5 | [Alias('VaultParameters')][hashtable]$AdditionalParameters
6 | )
7 |
8 | Write-PSFMessage "Unlocking SecretVault $VaultName"
9 | $vault = Get-SecretVault -Name $VaultName -ErrorAction Stop
10 | $vaultName = $vault.Name
11 | if ($vault.ModuleName -ne 'SecretManagement.KeePass') {
12 | Write-PSFMessage -Level Error "$vaultName was found but is not a Keepass Vault."
13 | return $false
14 | }
15 | Set-Variable -Name "Vault_${vaultName}_MasterPassword" -Scope Script -Value $Password -Force
16 | #Force a reconnection
17 | Remove-Variable -Name "Vault_${vaultName}" -Scope Script -Force -ErrorAction SilentlyContinue
18 | if (-not (Test-SecretVault -Name $vaultName -AdditionalParameters $AdditionalParameters)) {
19 | Write-PSFMessage -Level Error "${vaultName}: Failed to unlock the vault"
20 | return $false
21 | }
22 | Write-PSFMessage "SecretVault $vault unlocked successfull"
23 | return $true
24 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/Public/Unregister-SecretVault.ps1:
--------------------------------------------------------------------------------
1 | using namespace System.Management.Automation
2 | function Unregister-SecretVault {
3 | [CmdletBinding()]
4 | param(
5 | [string] $VaultName,
6 | [hashtable] $AdditionalParameters
7 | )
8 | if ($AdditionalParameters.Verbose) {$VerbosePreference = 'continue'}
9 | try {
10 | Remove-Variable -Name "Vault_$VaultName" -Scope Script -Force -ErrorAction Stop
11 | } catch [ItemNotFoundException] {
12 | Write-PSFMessage -Level Verbose "Vault ${VaultName}: Vault was not loaded at time of deregistration"
13 | }
14 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/SecretManagement.KeePass.Extension.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | ModuleVersion = '0.9.1.3'
3 | RootModule = 'SecretManagement.KeePass.Extension.psm1'
4 | FunctionsToExport = @('Set-Secret','Get-Secret','Remove-Secret','Get-SecretInfo','Test-SecretVault','Unregister-SecretVault','Connect-KeepassDatabase','Unlock-SecretVault')
5 | RequiredModules = @(
6 | @{ ModuleName = 'PSFramework'; ModuleVersion = '1.6.205' }
7 | )
8 | NestedModules = @(
9 | '../PoshKeePass/PoShKeePass.psd1'
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.Extension/SecretManagement.KeePass.Extension.psm1:
--------------------------------------------------------------------------------
1 |
2 | using namespace Microsoft.PowerShell.SecretManagement
3 |
4 | Get-ChildItem "$PSScriptRoot/Private" -Exclude "*.Tests.ps1" | Foreach-Object {
5 | . $PSItem.FullName
6 | }
7 | $publicFunctions = Get-ChildItem "$PSScriptRoot/Public" -Exclude "*.Tests.ps1" | Foreach-Object {
8 | . $PSItem.FullName
9 | #Output the name of the function assuming it is the same as the .ps1 file so it can be exported
10 | $PSItem.BaseName
11 | }
12 |
13 | Export-ModuleMember $publicFunctions
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/SecretManagement.KeePass.psd1
--------------------------------------------------------------------------------
/SecretManagement.KeePass/SecretManagement.KeePass.psm1:
--------------------------------------------------------------------------------
1 | #region SourceInit
2 | $publicFunctions = Get-ChildItem "$PSScriptRoot/Public" -Exclude "*.Tests.ps1" | Foreach-Object {
3 | . $PSItem.FullName
4 | #Output the name of the function assuming it is the same as the .ps1 file so it can be exported
5 | $PSItem.BaseName
6 | }
7 |
8 | Export-ModuleMember $publicFunctions
9 | #endregion SourceInit
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Get-Secret.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'Get-Secret' {
2 | BeforeAll {
3 | #Setup Testing Environment and mock calls to/from parent SecretManagement Module
4 |
5 | #Remove SecretManagement Parent Module if Present
6 | Get-Module 'SecretManagement.KeePass' | Remove-Module -Force
7 | Get-Module 'Microsoft.Powershell.SecretManagement' | Remove-Module -Force
8 |
9 | $ExtensionModule = Import-Module "$PSScriptRoot/../SecretManagement.KeePass.Extension/*.psd1" -Force -PassThru
10 | $Mocks = Join-Path $PSScriptRoot './Mocks' | Resolve-Path
11 | $BaseKeepassDatabaseName = 'Testdb'
12 | $DoubleEntryExceptionMessage = 'Multiple ambiguous entries found for double entry, please remove the duplicate entry or specify the full path of the secret'
13 | $ExtModuleName = $ExtensionModule.Name
14 |
15 | Mock -ModuleName $ExtModuleName 'Get-SecretVault' {
16 | @{
17 | VaultName = $VaultName
18 | VaultParameters = @{
19 | Path = $vaultPath
20 | }
21 | }
22 | }
23 | }
24 | AfterAll {
25 | Remove-Module $ExtensionModule -Force
26 | }
27 |
28 | Context 'Function Parameter Validation' {
29 | BeforeAll {
30 | $SCRIPT:FunctionName = 'Get-Secret'
31 | }
32 | It 'has one parameter set' {
33 | (Get-Command -Module $ExtModuleName -Name $FunctionName).ParameterSets.Count | Should -BeExactly 1
34 | }
35 | It 'has a parameter ""' {
36 | $allParameterNames = (Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters.Keys
37 | $Name | Should -BeIn $AllParameterNames
38 | } -TestCases @(
39 | @{Name = 'Name' }
40 | @{Name = 'VaultName' }
41 | @{Name = 'AdditionalParameters' }
42 | )
43 |
44 | It 'has the mandatory value of parameter "" set to ""' {
45 | $testAttribute = ((Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters[$Name].Attributes |
46 | Where-Object { $PSItem -is [System.Management.Automation.ParameterAttribute] }).Mandatory
47 | $testAttribute | Should -Be $Mandatory
48 | } -TestCases @(
49 | @{Name = 'Name'; Mandatory = $False }
50 | @{Name = 'VaultName'; Mandatory = $False }
51 | @{Name = 'AdditionalParameters'; Mandatory = $False }
52 | )
53 |
54 | It 'has parameter of type ' {
55 | ((Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters[$Name].ParameterType) |
56 | Should -BeExactly $Type
57 | } -TestCases @(
58 | @{Name = 'Name'; Type = 'string' }
59 | @{Name = 'VaultName'; Type = 'string' }
60 | @{Name = 'AdditionalParameters'; Type = 'hashtable' }
61 | )
62 | }
63 |
64 | Context 'Get Secret information from MasterPassword protected KeePass' {
65 | BeforeAll {
66 | $masterKey = '"1}`.2R{LX1`Jm8%XX2/'
67 | $vaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $masterKey))
68 |
69 | $vaultName = "KeepassPesterTest_$([guid]::NewGuid())"
70 | $keePassDatabaseSuffix = 'PathOnly'
71 | $keePassDatabaseFileName = "$($baseKeepassDatabaseName)$($keePassDatabaseSuffix).kdbx"
72 | $vaultPath = Join-Path -Path $TestDrive -ChildPath $keePassDatabaseFileName
73 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
74 |
75 | $vaultParams = @{
76 | VaultName = $VaultName
77 | VaultParameters = @{
78 | Path = $vaultPath
79 | }
80 | }
81 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
82 | }
83 |
84 | It 'should return a for entry ' -Tag CurrentTest {
85 | $Secret = Get-Secret @vaultParams -Name $SecretName
86 | $Secret | Should -BeOfType $PSType
87 | } -TestCases @(
88 | @{SecretName = 'New Entry 1';PSType = 'System.Management.Automation.PSCredential' }
89 | @{SecretName = 'New Entry 2';PSType = 'System.Management.Automation.PSCredential' }
90 | @{SecretName = 'No UserName';PSType = 'System.Security.SecureString' }
91 | )
92 |
93 | It 'should return for ' {
94 | $getSecretResult = Get-Secret @vaultParams -Name $SecretName
95 | $getSecretResult.UserName | Should -BeExactly $UserName
96 | } -TestCases @(
97 | @{SecretName = 'New Entry 1';UserName = 'myusername 1' }
98 | @{SecretName = 'New Entry 2';UserName = 'Some Administrator account' }
99 | )
100 |
101 | It 'should throw when multiple secrets are returned' {
102 | { Get-Secret @vaultParams -Name 'double entry' -ErrorAction Stop } |
103 | Should -Throw -ExpectedMessage $DoubleEntryExceptionMessage
104 | }
105 | It 'should return nothing when entry is not found in the KeePass DB' {
106 | Get-Secret @vaultParams -Name 'not present' | Should -BeNullOrEmpty
107 | }
108 | }
109 |
110 | Context 'Get Secret information from KeyFile protected KeePass' {
111 | BeforeAll {
112 | $KeyFileName = 'TestdbKeyFile.key'
113 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
114 | $KeePassDatabaseSuffix = 'KeyFile'
115 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
116 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
117 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
118 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
119 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
120 |
121 | $vaultParams = @{
122 | VaultName = $VaultName
123 | VaultParameters = @{
124 | Path = $VaultPath
125 | KeyPath = $KeyPath
126 | }
127 | }
128 | }
129 |
130 | It 'should return a for entry ' {
131 | $Secret = Get-Secret @vaultParams -Name $SecretName
132 | $Secret | Should -Not -BeNullOrEmpty
133 | $Secret | Should -BeOfType $PSType
134 | } -TestCases @(
135 | @{SecretName = 'New Entry 1';PSType = 'System.Management.Automation.PSCredential' }
136 | @{SecretName = 'New Entry 2';PSType = 'System.Management.Automation.PSCredential' }
137 | @{SecretName = 'No UserName';PSType = 'System.Security.SecureString' }
138 | )
139 |
140 | It 'should return for ' {
141 | $secretResult = Get-Secret @vaultParams -Name $SecretName
142 | $secretResult.UserName | Should -BeExactly $UserName
143 | } -TestCases @(
144 | @{SecretName = 'New Entry 1';UserName = 'myusername 1' }
145 | @{SecretName = 'New Entry 2';UserName = 'Some Administrator account' }
146 | )
147 |
148 | It 'should throw when multiple secrets are returned' {
149 | { Get-Secret @vaultParams -Name 'double entry' -ErrorAction Stop } |
150 | Should -Throw -ExpectedMessage $DoubleEntryExceptionMessage
151 | }
152 | It 'should return nothing when entry is not found in the KeePass DB' {
153 | Get-Secret @vaultParams -Name 'not present' |
154 | Should -BeNullOrEmpty
155 | }
156 | }
157 |
158 | Context 'Get Secret information from MasterPassword and KeyFile protected KeePass' {
159 | BeforeAll {
160 | $KeyFileName = 'TestdbKeyFileAndMasterPassword.key'
161 | $MasterKey = '"1}`.2R{LX1`Jm8%XX2/'
162 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
163 |
164 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
165 | $KeePassDatabaseSuffix = 'KeyFileAndMasterPassword'
166 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
167 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
168 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
169 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
170 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
171 |
172 | $vaultParams = @{
173 | VaultName = $VaultName
174 | VaultParameters = @{
175 | Path = $VaultPath
176 | UseMasterPassword = $true
177 | KeyPath = $KeyPath
178 | }
179 | }
180 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
181 | }
182 |
183 | It 'should return a for entry ' {
184 | $Secret = Get-Secret @vaultParams -Name $SecretName
185 | $Secret | Should -BeOfType $PSType
186 | } -TestCases @(
187 | @{SecretName = 'New Entry 1';PSType = 'System.Management.Automation.PSCredential' }
188 | @{SecretName = 'New Entry 2';PSType = 'System.Management.Automation.PSCredential' }
189 | @{SecretName = 'No UserName';PSType = 'System.Security.SecureString' }
190 | )
191 |
192 | It 'should return for ' {
193 | $getSecretResult = Get-Secret @vaultParams -Name $SecretName
194 | $getSecretResult.UserName | Should -BeExactly $UserName
195 | } -TestCases @(
196 | @{SecretName = 'New Entry 1';UserName = 'myusername 1' }
197 | @{SecretName = 'New Entry 2';UserName = 'Some Administrator account' }
198 | )
199 |
200 | It 'should throw when multiple secrets are returned' {
201 | { Get-Secret @vaultParams -Name 'double entry' -ErrorAction Stop } |
202 | Should -Throw -ExpectedMessage $DoubleEntryExceptionMessage
203 | }
204 |
205 | It 'should return nothing when entry is not found in the KeePass DB' {
206 | Get-Secret @vaultParams -Name 'not present' | Should -BeNullOrEmpty
207 | }
208 | }
209 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFile.kdbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFile.kdbx
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFile.key:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.00
5 |
6 |
7 | 80NRqIoAD9U5kTDIiWbu5szvxj/9vB3cSTmFfwArZvk=
8 |
9 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFileAndMasterPassword.kdbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFileAndMasterPassword.kdbx
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFileAndMasterPassword.key:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.00
5 |
6 |
7 | hzo9VQ6TpenHQbK28kwcm5Tgi0g66MMujrbfDgxwo2E=
8 |
9 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFileV2.kdbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFileV2.kdbx
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbKeyFileV2.keyx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2.0
5 |
6 |
7 |
8 | 0176FB93 276FE575 9CCB2938 B26A24E4
9 | 22162891 A5229055 BCD5B7B1 9A741851
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbPathAndUseMasterPassword.kdbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/Tests/Mocks/TestdbPathAndUseMasterPassword.kdbx
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Mocks/TestdbPathOnly.kdbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/SecretManagement.KeePass/Tests/Mocks/TestdbPathOnly.kdbx
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Register-KeePassSecretVault.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Describe 'Register-KeepassSecretVault' {
3 | BeforeAll {
4 | Import-Module "$PSScriptRoot/../SecretManagement.KeePass.psd1" -Force
5 | $SCRIPT:Mocks = Resolve-Path "$PSScriptRoot/Mocks"
6 | $SCRIPT:TestDB = Join-Path $Mocks 'TestdbKeyFile.kdbx'
7 | $SCRIPT:TestDBKey = Join-Path $Mocks 'TestdbKeyFile.key'
8 | $SCRIPT:TestDBName = ([io.fileinfo]$TestDB).Basename
9 | Unregister-SecretVault -Name $TestDBName -ErrorAction SilentlyContinue
10 | }
11 | AfterEach {
12 | Unregister-SecretVault -Name $TestDBName -ErrorAction SilentlyContinue
13 | if (-not $testdrive) {throw 'TestDrive Missing! This should not happen, bailing out for safety.'}
14 | Get-ChildItem $testdrive | Remove-Item -Force
15 | }
16 | AfterAll {
17 | Remove-Module SecretManagement.KeePass
18 | }
19 |
20 | It 'Registers a Vault' {
21 | Register-KeepassSecretVault -ErrorAction Stop -Path $TestDB -KeyPath $TestDBKey
22 | Get-SecretVault -Name $TestDBName -OutVariable myvault | Should -not -BeNullOrEmpty
23 | $myvault.Name | Should -Be $TestDBName
24 | $myvault.ModuleName | Should -Be 'SecretManagement.KeePass'
25 | $myVault.VaultParameters.UseMasterPassword | Should -BeFalse
26 | $myVault.VaultParameters.UseWindowsAccount | Should -BeFalse
27 | $myVault.VaultParameters.Path | Should -Be $TestDB
28 | $myVault.VaultParameters.KeyPath | Should -Be $TestDBKey
29 | }
30 | It 'Fails if bad path specified' {
31 | {Register-KeepassSecretVault -ErrorAction Stop -Path "$HOME\Path\To\Nowhere.kdbx"} |
32 | Should -Throw -ErrorId 'PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand'
33 | }
34 | It 'Fails if no auth method specified' {
35 | {Register-KeepassSecretVault -ErrorAction Stop -Path $TestDB} |
36 | Should -Throw 'No authentication methods specified*'
37 | }
38 |
39 | It 'Creates a new vault if Create is specified' {
40 | $RegisterParams = @{
41 | Create = $true
42 | Path = (Join-Path $TestDrive "$TestDBName.kdbx")
43 | KeyPath = (Join-Path $TestDrive "$TestDBName.key")
44 | }
45 |
46 | Register-KeePassSecretVault @RegisterParams
47 |
48 | Get-SecretVault -Name $TestDBName -OutVariable DB | Should -Not -BeNullOrEmpty
49 | $expectedVaultParameters = @{
50 | Path = $RegisterParams.Path
51 | KeyPath = $RegisterParams.KeyPath
52 | UseMasterPassword = 'False'
53 | UseWindowsAccount = 'False'
54 | }
55 |
56 | $expectedVaultParameters.keys.foreach{
57 | $DB.VaultParameters.$PSItem | Should -Be $expectedVaultParameters.$PSItem
58 | }
59 | }
60 |
61 | It 'Doesnt Clobber an existing vault if Create is specified' {
62 | $RegisterParams = @{
63 | Create = $true
64 | Path = (Join-Path $TestDrive "$TestDBName.kdbx")
65 | KeyPath = (Join-Path $TestDrive "$TestDBName.key")
66 | }
67 |
68 | #Simulate an already present vault
69 | New-Item $RegisterParams.Path
70 |
71 | {Register-KeePassSecretVault @RegisterParams} |
72 | Should -Throw '-Create was specified but a database already exists*'
73 | }
74 | It 'Doesnt Clobber an existing keyfile if Create is specified' {
75 | $RegisterParams = @{
76 | Create = $true
77 | Path = (Join-Path $TestDrive "$TestDBName.kdbx")
78 | KeyPath = $TestDBKey
79 | }
80 | $dbKeyHash = (Get-FileHash $TestDBKey).Hash
81 | $dbKeyDateModified = (Get-Item $TestDBKey).LastWriteTime
82 | Register-KeePassSecretVault @RegisterParams
83 | (Get-FileHash $TestDBKey).Hash | Should -Be $dbKeyHash
84 | (Get-Item $TestDBKey).LastWriteTime | Should -Be $dbKeyDateModified
85 | }
86 | It 'Uses full titles if showfulltitle is specified' {
87 | Register-KeepassSecretVault -ErrorAction Stop -Path $TestDB -KeyPath $TestDBKey -ShowFullTitle
88 | (Get-SecretInfo 'General/New Entry 1' -Vault $TestDBName 3>$null).Name | Should -Be 'General/New Entry 1'
89 | }
90 | It 'Succeeds with bad path but SkipValidate specified' {
91 | Register-KeePassSecretVault -Name $TestDBName -Path "$TestDrive/NotArealPath" -SkipValidate -KeyPath "$TestDrive/NotARealKey"
92 | Get-SecretVault -Name $TestDBName | Should -Not -BeNullOrEmpty
93 | }
94 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Remove-Secret.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'Remove-Secret' {
2 | BeforeAll {
3 | #Setup Testing Environment and mock calls to/from parent SecretManagement Module
4 | #Remove SecretManagement Parent Module if Present
5 | Get-Module 'SecretManagement.KeePass' | Remove-Module -Force
6 | Get-Module 'Microsoft.Powershell.SecretManagement' | Remove-Module -Force
7 |
8 | $ExtensionModule = Import-Module "$PSScriptRoot/../SecretManagement.KeePass.Extension/*.psd1" -Force -PassThru
9 | $Mocks = Join-Path $PSScriptRoot './Mocks' | Resolve-Path
10 | $BaseKeepassDatabaseName = 'Testdb'
11 | $DoubleEntryExceptionMessage = 'Multiple ambiguous entries found for double entry, please remove the duplicate entry or specify the full path of the secret'
12 | $ExtModuleName = $ExtensionModule.Name
13 |
14 | Mock -ModuleName $ExtModuleName 'Get-SecretVault' {
15 | @{
16 | VaultName = $VaultName
17 | VaultParameters = @{
18 | Path = $vaultPath
19 | }
20 | }
21 | }
22 | }
23 | BeforeEach {
24 | $BaseKeepassDatabaseName = 'Testdb'
25 | $ModulePath = (Resolve-Path $PSScriptRoot/../..)
26 | $MasterKey = '"1}`.2R{LX1`Jm8%XX2/'
27 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
28 |
29 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
30 | $KeePassDatabaseSuffix = 'PathOnly'
31 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
32 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
33 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
34 | $vaultParams = @{
35 | VaultName = $VaultName
36 | VaultParameters = @{
37 | Path = $vaultPath
38 | }
39 | }
40 | Mock -Verifiable -ModuleName $ExtModuleName 'Get-Credential' -MockWith { $VaultMasterKey }
41 |
42 | #Create one test key to remove
43 | $TestSecretName = 'PesterTestSecret'
44 | Set-Secret @vaultParams -Name $TestSecretName -Secret 'supersafe'
45 | $TestSecretParams = @{
46 | Vault = $VaultName
47 | Name = $TestSecretName
48 | }
49 | }
50 |
51 | It 'Fails if name not specified' {
52 | { Remove-Secret @vaultParams -Name $null } |
53 | Should -Throw -ErrorId 'ParameterArgumentValidationError*'
54 | }
55 | It 'Removes predefined secret' {
56 | Remove-Secret @vaultParams -Name $TestSecretName
57 | Get-SecretInfo @TestSecretParams | Should -BeNullOrEmpty
58 | }
59 | It 'Fails on removing already removed secret' {
60 | Remove-Secret @vaultParams -Name $TestSecretName
61 | {
62 | Remove-Secret @vaultParams -Name $TestSecretName -ErrorVariable err 2>$null
63 | } | Should -Throw "Vault * No Keepass Entry named $TestSecretName found"
64 | }
65 | It 'Fails on duplicate secrets' {
66 | {
67 | Remove-Secret @vaultParams -Name 'Double Entry' -ErrorVariable err 2>$null
68 | } | Should -Throw 'Vault * There are multiple entries*'
69 | }
70 | }
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/SecretManagementVault.Tests.ps1:
--------------------------------------------------------------------------------
1 | #requires -modules @{ModuleName="Pester"; ModuleVersion="5.1.0"}
2 | Describe 'SecretManagement.Keepass' {
3 | BeforeAll {
4 | Remove-Module Microsoft.Powershell.SecretManagement, SecretManagement.Keepass, SecretManagement.KeePass.Extension -ErrorAction SilentlyContinue -Force
5 |
6 | #Fetch helper function
7 | . $PSScriptRoot/../SecretManagement.KeePass.Extension/Private/Unlock-SecureString.ps1
8 |
9 | #Would use TestDrive but the PoshKeePass Module doesn't understand it for purposes of new-keepassdatabase
10 | $VaultName = 'SecretManagement.Tests'
11 | $VaultExtensionName = 'SecretManagement.KeePass'
12 | $VaultPath = Join-Path $TestDrive.FullName 'KeepassTestVault.kdbx'
13 | $SCRIPT:VaultKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force 'ThisIsATestVaultYouShouldNotUseIt'))
14 |
15 | Import-Module "$PSScriptRoot/../PoshKeePass/PoShKeePass.psd1" -Force
16 |
17 | #Create three variations of databases: Master Key only, keyfile, and both
18 | $VaultKeyFilePath = Join-Path $TestDrive.FullName 'KeepassTestKeyFileVault.key'
19 | $VaultKeyDBPath = $VaultPath -replace 'Vault', 'KeyVault'
20 | $VaultKeyPWDBPath = $VaultPath -replace 'Vault', 'KeyPWVault'
21 | [KeePassLib.Keys.KcpKeyFile]::Create($VaultKeyFilePath, $null)
22 | New-KeePassDatabase -DatabasePath $VaultPath -MasterKey $VaultKey
23 | New-KeePassDatabase -DatabasePath $VaultKeyDBPath -KeyPath $VaultKeyFilePath
24 | New-KeePassDatabase -DatabasePath $VaultKeyPWDBPath -KeyPath $VaultKeyFilePath -MasterKey $VaultKey
25 |
26 | Remove-Module PoshKeePass
27 |
28 | Import-Module "$PSScriptRoot/../SecretManagement.KeePass.psd1" -Force
29 |
30 | $SCRIPT:RegisterSecretVaultParams = @{
31 | Name = $VaultName
32 | ModuleName = (Get-Module $VaultExtensionName).Path
33 | PassThru = $true
34 | VaultParameters = @{
35 | Path = $VaultPath
36 | }
37 | }
38 | try {
39 | $SCRIPT:TestVault = Register-SecretVault @RegisterSecretVaultParams
40 | }
41 | catch [InvalidOperationException] {
42 | if ($PSItem -match 'Provided Name for vault is already being used') {
43 | Unregister-SecretVault -Name $RegisterSecretVaultParams.Name
44 | $SCRIPT:TestVault = Register-SecretVault @RegisterSecretVaultParams
45 | }
46 | else {
47 | $PSCmdlet.ThrowTerminatingError($PSItem)
48 | }
49 | }
50 | }
51 |
52 | AfterAll {
53 | $TestVault | Unregister-SecretVault -ErrorAction SilentlyContinue
54 | Get-Item $VaultPath -ErrorAction SilentlyContinue | Remove-Item
55 | }
56 |
57 | BeforeEach {
58 | $secretName = "tests/$((New-Guid).Guid)"
59 | }
60 |
61 | Context 'Unlock' {
62 | It 'Unattended Vault Unlock' {
63 | Unlock-SecretVault -Name $TestVault.Name -Password $VaultKey.Password
64 | Test-SecretVault -Name $TestVault.Name | Should -Be $true
65 | }
66 | }
67 |
68 | Context 'InvalidRegistration' {
69 | BeforeAll {
70 | $SCRIPT:InvalidVaultName = 'Pester.InvalidVault'
71 | Register-SecretVault -Name $InvalidVaultName -ModuleName (Resolve-Path $PSScriptRoot/..) -VaultParameters @{Path = "$TestDrive\NotARealDB.kdbx" }
72 | }
73 | AfterAll {
74 | Unregister-SecretVault -Name $InvalidVaultName
75 | }
76 | It 'Test-SecretVault should fail on uninitalized vault' {
77 | Test-SecretVault -Name $InvalidVaultName -ErrorVariable mytest 2>$null | Should -Be $False
78 | }
79 | }
80 |
81 | Context 'SecretManagement' {
82 | BeforeAll {
83 | #Unlock the vault
84 | Test-SecretVault -Name $TestVault.Name
85 | }
86 |
87 | It 'Get-SecretVault' {
88 | Get-SecretVault -Name $TestVault.Name | Should -Not -BeNullOrEmpty
89 | }
90 | It 'Test-SecretVault' {
91 | Test-SecretVault -Name $TestVault.Name | Should -Be $true
92 | }
93 |
94 | It 'Get/Set/Remove String' {
95 | $secretText = 'This is my string secret'
96 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secretText
97 | $secretInfo = Get-SecretInfo -Name $secretName -Vault $VaultName
98 | $secretInfo.Name | Should -BeExactly $secretName
99 | $secretInfo.VaultName | Should -BeExactly $VaultName
100 |
101 | #Metadata
102 | $secretInfo.Metadata.IconName | Should -Be 'Key'
103 | $secretInfo.Metadata.ParentGroup | Should -Be 'KeePassTestVault'
104 |
105 | $secret = Get-Secret -Name $secretName -Vault $VaultName
106 | $secret | Should -Be 'System.Security.SecureString'
107 | Unlock-SecureString $secret | Should -BeExactly $secretText
108 |
109 | Remove-Secret -Name $secretName -Vault $VaultName
110 | {
111 | Get-Secret -Name $secretName -Vault $VaultName -ErrorAction Stop
112 | } | Should -Throw -ErrorId 'GetSecretNotFound,Microsoft.PowerShell.SecretManagement.GetSecretCommand'
113 | }
114 |
115 | It 'Get/Set/Remove SecureString' {
116 | $secretText = 'This is my securestring secret'
117 | Set-Secret -Name $secretName -Vault $VaultName -Secret ($secretText | ConvertTo-SecureString -AsPlainText -Force)
118 |
119 | $secretInfo = Get-SecretInfo -Name $secretName -Vault $VaultName
120 | $secretInfo.Name | Should -BeExactly $secretName
121 | $secretInfo.VaultName | Should -BeExactly $VaultName
122 |
123 | $secret = Get-Secret -Name $secretName -AsPlainText -Vault $VaultName
124 | $secret | Should -BeExactly $secretText
125 |
126 | Remove-Secret -Name $secretName -Vault $VaultName
127 | { Get-Secret -Name $secretName -Vault $VaultName -ErrorAction Stop } | Should -Throw -ErrorId 'GetSecretNotFound,Microsoft.PowerShell.SecretManagement.GetSecretCommand'
128 | }
129 |
130 | It 'Get/Set/Remove PSCredential' {
131 | $secretPassword = 'PesterPassword'
132 | $secret = [PSCredential]::new('PesterUser', ($secretPassword | ConvertTo-SecureString -AsPlainText -Force))
133 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
134 | $secretInfo = Get-SecretInfo -Name $secretName -Vault $VaultName
135 | $secretInfo.Name | Should -BeLike $secretName
136 | $secretInfo.VaultName | Should -BeExactly $VaultName
137 | $storedSecret = Get-Secret -Name $secretName -Vault $VaultName
138 | $storedSecret | Should -BeOfType [PSCredential]
139 | $storedSecret.GetNetworkCredential().Password | Should -BeExactly $secretPassword
140 | $storedSecret.Username | Should -BeExactly $secret.UserName
141 | Remove-Secret -Name $secretName -Vault $VaultName
142 | {
143 | Get-Secret -Name $secretName -Vault $VaultName -ErrorAction Stop
144 | } | Should -Throw -ErrorId 'GetSecretNotFound,Microsoft.PowerShell.SecretManagement.GetSecretCommand'
145 | }
146 |
147 | It 'Should not create a duplicate entry with Set-Secret' {
148 | Set-ItResult -Skipped -Because 'Broken by 1.1.0 - https://github.com/PowerShell/SecretManagement/issues/151'
149 | $secretPassword = 'PesterPassword'
150 | $secret = [PSCredential]::new('PesterUser', ($secretPassword | ConvertTo-SecureString -AsPlainText -Force))
151 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
152 | [String]$DuplicateSecretWarning = Set-Secret -Name $secretName -Vault $VaultName -Secret $secret -WarningAction Continue *>&1
153 | [String]$DuplicateSecretWarning | Should -BeLike "*A secret with the title $secretName already exists*"
154 | }
155 | It 'Should update an existing entry with Set-Secret' {
156 | # Set-ItResult -Skipped -Because 'Broken by 1.1.0 - https://github.com/PowerShell/SecretManagement/issues/151'
157 | $secretName = "New-Secret ToBeUpdated"
158 | $secretPassword = 'PesterPassword'
159 | $secretPasswordAfterUpdate = 'PesterPasswordWasUpdated'
160 | $secret = [PSCredential]::new('PesterUser', ($secretPassword | ConvertTo-SecureString -AsPlainText -Force))
161 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
162 | Get-Secret -Name $secretName -Vault $VaultName | Should -Not -BeNullOrEmpty
163 |
164 | $secret = [PSCredential]::new('PesterUser', ($secretPasswordAfterUpdate | ConvertTo-SecureString -AsPlainText -Force))
165 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
166 | $secretAfterUpdate = Get-Secret -Name $secretName -Vault $VaultName
167 | $secretAfterUpdate | Should -Not -BeNullOrEmpty
168 | Write-PSFMessage "`$secretAfterUpdate=$($secretAfterUpdate.Username):$($secretAfterUpdate.GetNetworkCredential().password)"
169 | $secretAfterUpdate.GetNetworkCredential().password | Should -Be $secretPasswordAfterUpdate
170 | }
171 | It 'Search a non existing entry' {
172 | { Get-Secret -Name "ThisOneDoesNotExist" -Vault $VaultName -ErrorAction stop } | Should -Throw -ErrorId 'GetSecretNotFound,Microsoft.PowerShell.SecretManagement.GetSecretCommand'
173 | }
174 | It 'Should ignore recycle bin on update of an existing entry with Set-Secret' {
175 | $functionName = 'Should ignore recycle bin on update of an existing entry with Set-Secret'
176 | $secretPassword = 'PesterPassword'
177 | $secretPasswordAfterUpdate = 'PesterPasswordWasUpdated'
178 | $secret = [PSCredential]::new('PesterUser', ($secretPassword | ConvertTo-SecureString -AsPlainText -Force))
179 | # Set a secret, verify it
180 | Write-PSFMessage "Set a secret, verify it" -FunctionName $functionName
181 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
182 | Get-Secret -Name $secretName -Vault $VaultName | Should -Not -BeNullOrEmpty
183 |
184 | # remove it, verify it
185 | Write-PSFMessage "remove it, verify it" -FunctionName $functionName
186 | Remove-Secret -Name $secretName -Vault $VaultName
187 | { Get-Secret -Name $secretName -Vault $VaultName -ErrorAction stop } | Should -Throw -ErrorId 'GetSecretNotFound,Microsoft.PowerShell.SecretManagement.GetSecretCommand'
188 |
189 | # Create it again, verify it
190 | Write-PSFMessage "Create it again, verify it" -FunctionName $functionName
191 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
192 | Get-Secret -Name $secretName -Vault $VaultName | Should -Not -BeNullOrEmpty
193 |
194 | # Update the new Credential
195 | Write-PSFMessage "Update the new Credential, even if one with the same name exists in the recycle bin" -FunctionName $functionName
196 | $secret = [PSCredential]::new('PesterUser', ($secretPasswordAfterUpdate | ConvertTo-SecureString -AsPlainText -Force))
197 | Set-Secret -Name $secretName -Vault $VaultName -Secret $secret
198 | $secretAfterUpdate = Get-Secret -Name $secretName -Vault $VaultName
199 | $secretAfterUpdate | Should -Not -BeNullOrEmpty
200 | # Write-PSFMessage "`$secretAfterUpdate=$($secretAfterUpdate.Username):$($secretAfterUpdate.GetNetworkCredential().password)"
201 | $secretAfterUpdate.GetNetworkCredential().password | Should -Be $secretPasswordAfterUpdate
202 | }
203 |
204 | It 'Register-SecretVault -AllowClobber' {
205 | $RegisterSecretVaultParams.VaultParameters.Pester = $true
206 | $RegisterSecretVaultParams.AllowClobber = $true
207 | $newVault = Register-SecretVault @RegisterSecretVaultParams
208 | $newVault.VaultParameters.Pester | Should -BeTrue
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/Test-SecretVault.Tests.ps1:
--------------------------------------------------------------------------------
1 | $CommonTests = Join-Path $PSScriptRoot './TestSecretVault-CommonTests.include.ps1'
2 | # Attention:
3 | # Test will fail under Windows Powershell 5.1 if the localization is not en-US
4 | Describe 'Test-SecretVault' {
5 | BeforeAll {
6 | #Setup Testing Environment and mock calls to/from parent SecretManagement Module
7 | #Remove SecretManagement Parent Module if Present
8 | Get-Module 'SecretManagement.KeePass' | Remove-Module -Force
9 | Get-Module 'Microsoft.Powershell.SecretManagement' | Remove-Module -Force
10 |
11 | $ExtensionModule = Import-Module "$PSScriptRoot/../SecretManagement.KeePass.Extension/*.psd1" -Force -PassThru
12 | $Mocks = Join-Path $PSScriptRoot './Mocks' | Resolve-Path
13 |
14 | $BaseKeepassDatabaseName = 'Testdb'
15 | $ExtModuleName = $ExtensionModule.Name
16 | $DoubleEntryExceptionMessage = 'Multiple ambiguous entries found for double entry, please remove the duplicate entry or specify the full path of the secret'
17 | $KeePassCompositeError = '*The composite key is invalid!*Make sure the composite key is correct and try again.*'
18 | $KeePassMasterKeyError = '*The master key is invalid!*'
19 |
20 | Mock -ModuleName $ExtModuleName 'Get-SecretVault' {
21 | @{
22 | VaultName = $VaultName
23 | VaultParameters = @{
24 | Path = $vaultPath
25 | }
26 | }
27 | }
28 | }
29 |
30 | Context 'Function Parameter Validation' {
31 | BeforeAll {
32 | $ExtModuleName = $ExtensionModule.Name
33 | $FunctionName = 'Test-SecretVault'
34 | $ParameterCount = 2
35 | }
36 |
37 | It 'has a parameter vaultname' {
38 | $Name = 'vaultname'
39 | $AllParameterNames = (Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters.Keys
40 | $Name | Should -BeIn $AllParameterNames
41 | }
42 | It 'has a parameter ""' -TestCases @(
43 | @{Name = 'VaultName' }
44 | @{Name = 'AdditionalParameters' }
45 | ) {
46 | $AllParameterNames = (Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters.Keys
47 | $Name | Should -BeIn $AllParameterNames
48 | }
49 | It 'has the mandatory value of parameter "" set to ""' -TestCases @(
50 | @{Name = 'VaultName'; Mandatory = $True }
51 | @{Name = 'AdditionalParameters'; Mandatory = $False }
52 | ) {
53 | ((Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters[$Name].Attributes | Where-Object { $_.GetType().FullName -eq 'System.Management.Automation.ParameterAttribute' }).Mandatory | Should -Be $Mandatory
54 | }
55 | It 'has parameter of type ' -TestCases @(
56 | @{Name = 'VaultName'; Type = 'string' }
57 | @{Name = 'AdditionalParameters'; Type = 'hashtable' }
58 | ) {
59 | ((Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters[$Name].ParameterType) | Should -BeExactly $Type
60 | }
61 | It 'has one parameter set' {
62 | (Get-Command -Module $ExtModuleName -Name $FunctionName).ParameterSets.Count | Should -BeExactly 1
63 | }
64 | }
65 |
66 | Context 'Validating with correct MasterPassword' {
67 | BeforeAll {
68 | $MasterKey = '"1}`.2R{LX1`Jm8%XX2/'
69 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
70 | $KeePassDatabaseSuffix = 'PathOnly'
71 |
72 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
73 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
74 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
75 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
76 |
77 | $vaultParams = @{
78 | VaultName = $VaultName
79 | VaultParameters = @{
80 | Path = $vaultPath
81 | }
82 | }
83 |
84 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
85 | }
86 |
87 | . $CommonTests -Credential
88 | }
89 |
90 | Context 'Validating with incorrect MasterPassword' {
91 | BeforeAll {
92 | $MasterKey = 'ThisIsAnInvalidMasterKey'
93 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
94 |
95 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
96 | $KeePassDatabaseSuffix = 'PathOnly'
97 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
98 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
99 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
100 |
101 | $vaultParams = @{
102 | VaultName = $VaultName
103 | VaultParameters = @{
104 | Path = $vaultPath
105 | }
106 | }
107 |
108 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
109 | }
110 | . $CommonTests -Invalid -Credential
111 | }
112 |
113 | Context 'Validating with Path and correct UseMasterPassword' {
114 | BeforeAll {
115 | $MasterKey = '"1}`.2R{LX1`Jm8%XX2/'
116 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
117 |
118 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
119 | $KeePassDatabaseSuffix = 'PathAndUseMasterPassword'
120 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
121 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
122 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
123 |
124 | $vaultParams = @{
125 | VaultName = $VaultName
126 | VaultParameters = @{
127 | Path = $vaultPath
128 | UseMasterPassword = $true
129 | }
130 | }
131 |
132 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
133 | }
134 | . $CommonTests -Credential
135 | }
136 | Context 'Validating with path and incorrect MasterPassword' {
137 | BeforeAll {
138 | $MasterKey = 'ThisIsAnInvalidMasterKey'
139 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
140 |
141 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
142 | $KeePassDatabaseSuffix = 'PathOnly'
143 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
144 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
145 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
146 |
147 | $vaultParams = @{
148 | VaultName = $VaultName
149 | VaultParameters = @{
150 | Path = $vaultPath
151 | UseMasterPassword = $true
152 | }
153 | }
154 |
155 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
156 | }
157 | . $CommonTests -Invalid -Credential
158 | }
159 |
160 | Context 'Validating with correct Keyfile' {
161 | BeforeAll {
162 | $KeyFileName = 'TestdbKeyFile.key'
163 |
164 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
165 | $KeePassDatabaseSuffix = 'KeyFile'
166 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
167 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
168 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
169 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
170 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
171 |
172 | $vaultParams = @{
173 | VaultName = $VaultName
174 | VaultParameters = @{
175 | Path = $vaultPath
176 | KeyPath = $KeyPath
177 | }
178 | }
179 | }
180 | . $CommonTests -KeyFile
181 | }
182 |
183 | Context 'Validating with incorrect Keyfile' {
184 | BeforeAll {
185 | $KeyFileName = 'TestdbKeyFileAndMasterPassword.key'
186 |
187 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
188 | $KeePassDatabaseSuffix = 'KeyFile'
189 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
190 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
191 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
192 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
193 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
194 |
195 | $vaultParams = @{
196 | VaultName = $VaultName
197 | VaultParameters = @{
198 | Path = $vaultPath
199 | KeyPath = $KeyPath
200 | }
201 | }
202 | }
203 | . $CommonTests -Invalid -KeyFile
204 | }
205 |
206 | Context 'Validating with correct Keyfile v2' {
207 | BeforeAll {
208 | $KeyFileName = 'TestdbKeyFileV2.keyx'
209 | $KeePassDatabaseSuffix = 'KeyFileV2'
210 |
211 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
212 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
213 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
214 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
215 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
216 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
217 |
218 | $vaultParams = @{
219 | VaultName = $VaultName
220 | VaultParameters = @{
221 | Path = $vaultPath
222 | KeyPath = $KeyPath
223 | }
224 | }
225 | }
226 | . $CommonTests -KeyFile
227 | }
228 |
229 | Context 'Validating with correct Keyfile and correct master password' {
230 | BeforeAll {
231 | $KeyFileName = 'TestdbKeyFileAndMasterPassword.key'
232 | $MasterKey = '"1}`.2R{LX1`Jm8%XX2/'
233 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
234 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
235 | $KeePassDatabaseSuffix = 'KeyFileAndMasterPassword'
236 |
237 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
238 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
239 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
240 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
241 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
242 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
243 |
244 | $vaultParams = @{
245 | VaultName = $VaultName
246 | VaultParameters = @{
247 | Path = $VaultPath
248 | UseMasterPassword = $true
249 | KeyPath = $KeyPath
250 | }
251 | }
252 | }
253 | . $CommonTests -Credential
254 | }
255 |
256 | Context 'Validating with correct Keyfile and incorrect master password' {
257 | BeforeAll {
258 | $KeyFileName = 'TestdbKeyFileAndMasterPassword.key'
259 | $MasterKey = 'NotTheCorrectMasterKey'
260 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
261 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
262 | $KeePassDatabaseSuffix = 'KeyFileAndMasterPassword'
263 |
264 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
265 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
266 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
267 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
268 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
269 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
270 |
271 | $vaultParams = @{
272 | VaultName = $VaultName
273 | VaultParameters = @{
274 | Path = $VaultPath
275 | UseMasterPassword = $true
276 | KeyPath = $KeyPath
277 | }
278 | }
279 | }
280 | . $CommonTests -Credential -Invalid
281 | }
282 |
283 |
284 | Context 'Validating with incorrect Keyfile and correct master password' {
285 | BeforeAll {
286 | $KeyFileName = 'TestdbKeyFile.key'
287 | $MasterKey = '"1}`.2R{LX1`Jm8%XX2/'
288 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
289 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
290 | $KeePassDatabaseSuffix = 'KeyFileAndMasterPassword'
291 |
292 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
293 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
294 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
295 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
296 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
297 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
298 |
299 | $vaultParams = @{
300 | VaultName = $VaultName
301 | VaultParameters = @{
302 | Path = $VaultPath
303 | UseMasterPassword = $true
304 | KeyPath = $KeyPath
305 | }
306 | }
307 | }
308 | . $CommonTests -Credential -Invalid
309 | }
310 |
311 | Context 'Validating with incorrect Keyfile and incorrect master password' {
312 | BeforeAll {
313 | $KeyFileName = 'TestdbKeyFile.key'
314 | $MasterKey = 'You can not enter with this password!'
315 | $VaultMasterKey = [PSCredential]::new('vaultkey', (ConvertTo-SecureString -AsPlainText -Force $MasterKey))
316 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
317 | $KeePassDatabaseSuffix = 'KeyFileAndMasterPassword'
318 |
319 | $VaultName = "KeepassPesterTest_$([guid]::NewGuid())"
320 | $KeePassDatabaseFileName = "$($BaseKeepassDatabaseName)$($KeePassDatabaseSuffix).kdbx"
321 | $VaultPath = Join-Path -Path $TestDrive -ChildPath $KeePassDatabaseFileName
322 | $KeyPath = Join-Path -Path $TestDrive -ChildPath $KeyFileName
323 | Copy-Item -Path (Join-Path $Mocks $KeePassDatabaseFileName) -Destination $VaultPath
324 | Copy-Item -Path (Join-Path $Mocks $KeyFileName) -Destination $KeyPath
325 |
326 | $vaultParams = @{
327 | VaultName = $VaultName
328 | VaultParameters = @{
329 | Path = $VaultPath
330 | UseMasterPassword = $true
331 | KeyPath = $KeyPath
332 | }
333 | }
334 | }
335 | . $CommonTests -Credential -Invalid
336 | }
337 | }
338 |
--------------------------------------------------------------------------------
/SecretManagement.KeePass/Tests/TestSecretVault-CommonTests.include.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [Switch]$Credential,
3 | [Switch]$KeyFile,
4 | [Switch]$Invalid
5 | )
6 |
7 | It "should not have a vault variable by default" {
8 | {
9 | InModuleScope $ExtensionModule {
10 | param($vaultName)
11 | Get-Variable "Vault_$vaultName" -ErrorAction 'Stop'
12 | } @{
13 | vaultName = $vaultParams.VaultName
14 | }
15 | } | Should -Throw 'Cannot find a variable with the name*'
16 | }
17 |
18 | if (-not $Invalid) {
19 | if ($KeyFile) {
20 | It 'Should not request a credential' {
21 | Set-ItResult -Skipped -Because 'Broken by SecretManagement 1.1.0 new runspace behavior'
22 | Test-SecretVault @vaultParams
23 | Should -Invoke -CommandName 'Get-Credential' -Exactly 0 -Scope Context
24 | }
25 | }
26 |
27 | if ($Credential) {
28 | It 'should request a credential on the first pass' {
29 | Mock -Verifiable -ModuleName $ExtModuleName -CommandName 'Get-Credential' -MockWith { $VaultMasterKey }
30 | Test-SecretVault @vaultParams
31 | Should -ModuleName $ExtModuleName -Invoke -CommandName 'Get-Credential' -Exactly 1 -Scope Context
32 | }
33 | It 'Should not request a credential on the second pass' {
34 | Test-SecretVault @vaultParams
35 | Test-SecretVault @vaultParams
36 | Should -ModuleName $ExtModuleName -Invoke -CommandName 'Get-Credential' -Exactly 1 -Scope Context
37 | }
38 | }
39 |
40 | It 'should have a Vault variable upon unlock' {
41 | Test-SecretVault @vaultParams | Should -BeTrue
42 | $vaultVars = InModuleScope $ExtensionModule {
43 | (Get-Variable -Name Vault_*).Name
44 | }
45 | "Vault_$($vaultParams.VaultName)" | Should -BeIn $vaultVars
46 | }
47 |
48 | It 'should return true' {
49 | Test-SecretVault @vaultParams | Should -BeTrue
50 | }
51 |
52 | } else {
53 | It 'Detects Invalid Composite Key and does not set a vault variable' {
54 | $infoString = Get-Module microsoft.powershell.secretmanagement | Format-Table | Out-String
55 | Write-PSFMessage -Level Verbose -Message "$infoString"
56 | $result = Test-SecretVault @vaultParams -ErrorVariable myerr 2>$null
57 | $myerr[-2] | Should -BeLike $KeePassMasterKeyError
58 | $result | Should -BeFalse
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | #requires -version 5
2 | using namespace System.IO
3 |
4 | <#
5 | .SYNOPSIS
6 | Bootstraps Invoke-Build and starts it with supplied parameters.
7 | .NOTES
8 | If you already have Invoke-Build installed, just use Invoke-Build instead of this script. This is for CI/CD environments like Appveyor, Jenkins, or Azure DevOps pipelines.
9 | .EXAMPLE
10 | .\build.ps1
11 | Starts Invoke-Build with the default parameters
12 | #>
13 |
14 | $ErrorActionPreference = 'Stop'
15 |
16 | #Add TLS 1.2 to potential security protocols on Windows Powershell. This is now required for powershell gallery
17 | if ($PSEdition -eq 'Desktop') {
18 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 'Tls12'
19 | }
20 |
21 | function BootstrapModule {
22 | param (
23 | $ModuleSpecification,
24 | $Path = (Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) 'Press')
25 | )
26 | $vEnvDir = New-Item -ItemType Directory -Force -Path $Path
27 |
28 | $env:PSModulePath = $vEnvDir,$env:PSModulePath -join [io.path]::PathSeparator
29 |
30 | #This is done for performance. If the module is found loaded it won't try to search filesystem
31 | $existingModule = (Get-Module -FullyQualifiedName $moduleSpecification -ErrorAction SilentlyContinue)
32 | if (-not $existingModule) {
33 | $existingModule = (Get-Module -ListAvailable -FullyQualifiedName $moduleSpecification -ErrorAction SilentlyContinue)
34 | }
35 |
36 | if ($existingModule) {
37 | Write-Verbose "Module $($moduleSpecification.ModuleName) was detected. Skipping bootstrap."
38 | return
39 | }
40 |
41 | $moduleParams = @{
42 | Name = $moduleSpecification.ModuleName
43 | MinimumVersion = $moduleSpecification.ModuleVersion
44 | MaximumVersion = $moduleSpecification.MaximumVersion
45 | Force = $true
46 | ErrorAction = 'Stop'
47 | }
48 | Write-Verbose "$($ModuleSpecification.ModuleName) not found locally. Bootstrapping..."
49 | Save-Module @moduleParams -Path $vEnvDir
50 | Import-Module @moduleParams
51 | }
52 |
53 | BootstrapModule @{
54 | ModuleName = 'InvokeBuild'
55 | ModuleVersion = '5.5.7'
56 | MaximumVersion = '5.99.99'
57 | }
58 |
59 | #Passthrough Invoke-Build
60 | Push-Location $PSScriptRoot
61 | try {
62 | Invoke-Expression "Invoke-Build $($args -join ' ')"
63 | } catch {
64 | throw $PSItem
65 | } finally {
66 | Pop-Location
67 | }
--------------------------------------------------------------------------------
/images/KeePassSecretManagementDemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/images/KeePassSecretManagementDemo.gif
--------------------------------------------------------------------------------
/images/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JustinGrote/SecretManagement.KeePass/cb0ddb3355b3e14c672679d687bbd8e5f5979bdf/images/Logo.png
--------------------------------------------------------------------------------