function Register-DSCConfigurationDataCredentialProvider { [CmdletBinding(SupportsShouldProcess=$true)] Param( [Parameter(Mandatory=$true, Position=1)] [string] $Vault, [Parameter(Mandatory=$false)] [ValidateSet("Generic", "KeePass")] [string] $VaultType = "Generic", [Parameter(Mandatory=$false)] [string] $DatabasePath, [Parameter(Mandatory=$false)] [string] $KeyPath, [Parameter(Mandatory=$false)] [string] $SettingsPath, [Parameter(Mandatory=$false)] [string] $ModuleName, [Parameter(Mandatory=$false)] [hashtable] $VaultParameters = @{}, [Parameter(Mandatory=$false)] [switch] $RegisterVault, [Parameter(Mandatory=$false)] [switch] $DefaultVault, [Parameter(Mandatory=$false)] [switch] $AllowClobber, [Parameter(Mandatory=$false)] [switch] $UseMasterPassword, [Parameter(Mandatory=$false)] [Alias("MasterKey")] [System.Security.SecureString] $MasterPassword, [Parameter(Mandatory=$false)] [Alias("MasterKeyPath")] [string] $MasterPasswordKeyPath, [Parameter(Mandatory=$false)] [switch] $Force, [Parameter(Mandatory=$false)] [switch] $PassThru ) DynamicParam { $ProviderNames = @(Get-ConfigurationDataSecretProviderName) if($ProviderNames.Count -eq 0){ $ProviderNames = @("__NoProvidersRegistered__") } $ParameterAttribute = [System.Management.Automation.ParameterAttribute]::new() $ParameterAttribute.Mandatory = $false $ParameterAttribute.Position = 0 $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList (,[string[]]$ProviderNames) $Attributes = [System.Collections.ObjectModel.Collection[System.Attribute]]::new() $Attributes.Add($ParameterAttribute) $Attributes.Add($ValidateSetAttribute) $RuntimeParameter = [System.Management.Automation.RuntimeDefinedParameter]::new( "Provider", [string], $Attributes ) $Dictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() $Dictionary.Add("Provider", $RuntimeParameter) return $Dictionary } begin { $Provider = [string]$PSBoundParameters["Provider"] if([string]::IsNullOrWhiteSpace($Provider)){ $ProviderNames = @(Get-ConfigurationDataSecretProviderName) if($ProviderNames.Count -eq 1){ $Provider = $ProviderNames[0] }elseif($ProviderNames.Count -eq 0){ throw "No configuration data secret providers are registered." }else{ throw "Provider is required. Registered providers: $($ProviderNames -join ', ')." } } $SettingsPath = Resolve-ConfigurationDataProviderSettingsPath -Provider $Provider -SettingsPath $SettingsPath } process { switch($Provider){ "SecretManagement" { if([string]::IsNullOrWhiteSpace($ModuleName)){ if($VaultType -eq "KeePass"){ $ModuleName = "SecretManagement.KeePass" }else{ $ModuleName = "Microsoft.PowerShell.SecretStore" } } $ShouldRegisterVault = $RegisterVault -or $PSBoundParameters.ContainsKey("ModuleName") if($VaultType -eq "KeePass" -and $ShouldRegisterVault){ if([string]::IsNullOrWhiteSpace($DatabasePath) -and -not $VaultParameters.ContainsKey("Path")){ throw "SecretManagement KeePass vault registration requires [DatabasePath] or VaultParameters['Path']." } if(-not [string]::IsNullOrWhiteSpace($DatabasePath)){ $VaultParameters["Path"] = $DatabasePath } if(-not [string]::IsNullOrWhiteSpace($KeyPath)){ $VaultParameters["KeyPath"] = $KeyPath } if($UseMasterPassword){ $VaultParameters["UseMasterPassword"] = $true } } if($ShouldRegisterVault){ if($VaultType -eq "KeePass"){ $KeePassModule = Get-Module -Name SecretManagement.KeePass -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 if($null -eq $KeePassModule){ throw "SecretManagement KeePass vault registration requires module [SecretManagement.KeePass]." } $ModuleReference = $KeePassModule.Name if(-not [string]::IsNullOrWhiteSpace($KeePassModule.Path)){ $ModuleReference = $KeePassModule.Path } $CommandParameters = @{ Name = $Vault ModuleName = $ModuleReference VaultParameters = @{ Path = $VaultParameters["Path"] UseMasterPassword = $false UseWindowsAccount = $false KeyPath = $null ShowFullTitle = $false ShowRecycleBin = $false } } foreach($Key in @("KeyPath", "UseMasterPassword", "UseWindowsAccount", "ShowFullTitle", "ShowRecycleBin", "SkipValidate")){ if($VaultParameters.ContainsKey($Key)){ $CommandParameters.VaultParameters[$Key] = $VaultParameters[$Key] } } if($DefaultVault){ $CommandParameters["DefaultVault"] = $true } if($AllowClobber){ $CommandParameters["AllowClobber"] = $true } if($PSCmdlet.ShouldProcess($Vault, "Register KeePass SecretManagement vault [$ModuleReference]")){ Register-SecretVault @CommandParameters } }else{ $CommandParameters = @{ Name = $Vault ModuleName = $ModuleName } if($VaultParameters.Count -gt 0){ $CommandParameters["VaultParameters"] = $VaultParameters } if($DefaultVault){ $CommandParameters["DefaultVault"] = $true } if($AllowClobber){ $CommandParameters["AllowClobber"] = $true } if($PSCmdlet.ShouldProcess($Vault, "Register SecretManagement vault [$ModuleName]")){ Register-SecretVault @CommandParameters } } } $ProviderSettings = [ordered]@{ SecretManagement = [ordered]@{ DefaultVault = $Vault } } if($VaultType -ne "Generic"){ $ProviderSettings.SecretManagement["VaultType"] = $VaultType } if($null -ne $MasterPassword){ if([string]::IsNullOrWhiteSpace($MasterPasswordKeyPath)){ throw "MasterPassword requires [MasterPasswordKeyPath]." } $Key = New-ConfigurationDataAesKeyFile -Path $MasterPasswordKeyPath -Force:$Force $ProtectedValue = $MasterPassword | ConvertFrom-SecureString -Key $Key $ProviderSettings.SecretManagement["MasterPassword"] = [ordered]@{ ProtectedValue = $ProtectedValue KeyPath = $MasterPasswordKeyPath } } if($PSCmdlet.ShouldProcess($SettingsPath, "Create provider settings for [$Provider]")){ Export-PowerShellDataFile -InputObject $ProviderSettings -Path $SettingsPath -Force:$Force } if($PassThru){ return $ProviderSettings } } default { throw "Provider [$Provider] does not provide an initialization implementation." } } } }