diff --git a/extensions/powershell/secret/copy_files.txt b/extensions/powershell/secret/copy_files.txt new file mode 100644 index 000000000..b9e7ea40d --- /dev/null +++ b/extensions/powershell/secret/copy_files.txt @@ -0,0 +1,2 @@ +microsoft.powershell.secret.ps1 +microsoft.powershell.dsc.extension.json diff --git a/extensions/powershell/secret/microsoft.powershell.dsc.extension.json b/extensions/powershell/secret/microsoft.powershell.dsc.extension.json new file mode 100644 index 000000000..4c81021da --- /dev/null +++ b/extensions/powershell/secret/microsoft.powershell.dsc.extension.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://aka.ms/dsc/schemas/v3/bundled/extension/manifest.json", + "type": "Microsoft.PowerShell/SecretManagement", + "version": "0.1.0", + "description": "Retrieve secrets using the Microsoft.PowerShell.SecretManagement module", + "secret": { + "executable": "pwsh", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-Command", + "./microsoft.powershell.secret.ps1", + { + "nameArg": "-Name" + }, + { + "vaultArg": "-Vault" + } + ] + } +} diff --git a/extensions/powershell/secret/microsoft.powershell.secret.ps1 b/extensions/powershell/secret/microsoft.powershell.secret.ps1 new file mode 100644 index 000000000..928b47b0c --- /dev/null +++ b/extensions/powershell/secret/microsoft.powershell.secret.ps1 @@ -0,0 +1,25 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$Name, + [Parameter()] + [string]$Vault +) + +if (Get-Command Get-Secret -ErrorAction Ignore) { + $secretParams = @{ + Name = $Name + AsPlainText = $true + } + + if (-not ([string]::IsNullOrEmpty($Vault))) { + $secretParams['Vault'] = $Vault + } + + $secret = Get-Secret @secretParams -ErrorAction Ignore + + Write-Output $secret +} \ No newline at end of file diff --git a/extensions/powershell/secret/microsoft.powershell.secret.tests.ps1 b/extensions/powershell/secret/microsoft.powershell.secret.tests.ps1 new file mode 100644 index 000000000..285eaf123 --- /dev/null +++ b/extensions/powershell/secret/microsoft.powershell.secret.tests.ps1 @@ -0,0 +1,41 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +BeforeDiscovery { + $runningInCI = $false +} + +BeforeAll { + $FullyQualifiedName = @() + $FullyQualifiedName += @{ModuleName="Microsoft.PowerShell.SecretManagement";ModuleVersion="1.1.2"} + $FullyQualifiedName += @{ModuleName="Microsoft.PowerShell.SecretStore";ModuleVersion="1.0.6"} + foreach ($module in $FullyQualifiedName) { + if (-not (Get-Module -ListAvailable -FullyQualifiedName $module)) { + Save-PSResource -Name $module.ModuleName -Version $module.ModuleVersion -Path $TestDrive -Repository PSGallery -TrustRepository + } + } + + $env:PSModulePath += [System.IO.Path]::PathSeparator + $TestDrive +} + +Describe 'Tests for PowerShell Secret Management' -Skip:($runningInCI) { + It 'Should get secret from default store' { + # Instead of doing it in the BeforeAll block, reset the store here as we know we are running in the CI + Reset-SecretStore -Password (ConvertTo-SecureString -AsPlainText -String 'P@ssw0rd' -Force) -Force + Register-SecretVault -Name 'VaultA' -ModuleName 'Microsoft.PowerShell.SecretStore' -DefaultVault + Set-Secret -Name TestSecret -Secret "Super@SecretPassword" + + $configYaml = @' + $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json + resources: + - name: Echo + type: Microsoft.DSC.Debug/Echo + properties: + output: "[secret('TestSecret')]" +'@ + $out = dsc -l trace config get -i $configYaml 2> $TestDrive/error.log | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 -Because (Get-Content -Raw -Path $TestDrive/error.log) + $out.results.Count | Should -Be 1 + $out.results[0].result.actualState.Output | Should -BeExactly 'Super@SecretPassword' + } +} \ No newline at end of file