Providers/AD/Public/Get-ADTestPasswordFromVault.ps1
|
function Get-ADTestPasswordFromVault { <# .EXTERNALHELP TestEnvironment-Help.xml .SYNOPSIS Retrieves a stored password from the ADTestEnvironment SecretStore vault #> [CmdletBinding(DefaultParameterSetName = 'ByServiceAccount')] [OutputType([System.Security.SecureString], ParameterSetName = 'ByServiceAccount')] [OutputType([System.Security.SecureString], ParameterSetName = 'BySecretName')] [OutputType([string], ParameterSetName = 'ByServiceAccount')] [OutputType([string], ParameterSetName = 'BySecretName')] [OutputType([PSCustomObject[]], ParameterSetName = 'ListSecrets')] param( [Parameter(ParameterSetName = 'ByServiceAccount', Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ServiceAccountName, [Parameter(ParameterSetName = 'BySecretName', Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SecretName, [Parameter()] [ValidateNotNullOrEmpty()] [string]$VaultName = "ADTestEnvironment", [Parameter()] [switch]$AsPlainText, [Parameter(ParameterSetName = 'ListSecrets')] [switch]$ListSecrets, [Parameter()] [switch]$IncludeExpired ) begin { $correlationId = [System.Guid]::NewGuid() Write-Verbose "Starting Get-ADTestPasswordFromVault - CorrelationId: $correlationId" } process { try { # Check if SecretManagement module is available if (-not (Get-Module -ListAvailable -Name Microsoft.PowerShell.SecretManagement)) { throw "Microsoft.PowerShell.SecretManagement module is not installed. Install it using: Install-Module Microsoft.PowerShell.SecretManagement" } Import-Module Microsoft.PowerShell.SecretManagement -Force # Check if vault exists $vault = Get-SecretVault -Name $VaultName -ErrorAction SilentlyContinue if (-not $vault) { throw "SecretStore vault '$VaultName' not found. Create it first using Export-ADTestPasswordDocumentation with -UseSecretStore parameter." } if ($ListSecrets) { # List all secrets in the vault Write-Verbose "Listing all secrets in vault: $VaultName" $secrets = Get-SecretInfo -Vault $VaultName $secretList = @() foreach ($secret in $secrets) { $secretInfo = [PSCustomObject]@{ SecretName = $secret.Name ServiceAccount = $secret.Metadata.ServiceAccount CreatedDate = $secret.Metadata.CreatedDate StoredDate = $secret.Metadata.StoredDate Description = $secret.Metadata.Description Department = $secret.Metadata.Department ExpirationDate = $secret.Metadata.ExpirationDate CorrelationId = $secret.Metadata.CorrelationId Source = $secret.Metadata.Source IsExpired = $false } # Check if secret is expired if ($secret.Metadata.ExpirationDate) { try { $expirationDate = [DateTime]::Parse($secret.Metadata.ExpirationDate) $secretInfo.IsExpired = $expirationDate -lt (Get-Date) } catch { Write-Verbose "Could not parse expiration date for secret: $($secret.Name)" } } # Filter expired secrets unless specifically included if ($secretInfo.IsExpired -and -not $IncludeExpired) { Write-Verbose "Excluding expired secret: $($secret.Name)" continue } $secretList += $secretInfo } Write-Verbose "Found $($secretList.Count) secrets in vault" return $secretList } elseif ($PSCmdlet.ParameterSetName -eq 'ByServiceAccount') { # Find secrets for the specified service account Write-Verbose "Searching for secrets for service account: $ServiceAccountName" $secrets = Get-SecretInfo -Vault $VaultName | Where-Object { $_.Metadata.ServiceAccount -eq $ServiceAccountName } if (-not $secrets) { throw "No secrets found for service account '$ServiceAccountName' in vault '$VaultName'" } # Filter out expired secrets unless specifically included if (-not $IncludeExpired) { $secrets = $secrets | Where-Object { if ($_.Metadata.ExpirationDate) { try { $expirationDate = [DateTime]::Parse($_.Metadata.ExpirationDate) return $expirationDate -ge (Get-Date) } catch { # If we can't parse the date, include it return $true } } # No expiration date means it doesn't expire return $true } } if (-not $secrets) { throw "No non-expired secrets found for service account '$ServiceAccountName' in vault '$VaultName'. Use -IncludeExpired to include expired secrets." } # Get the most recent secret (by name which includes timestamp) $latestSecret = $secrets | Sort-Object Name -Descending | Select-Object -First 1 Write-Verbose "Retrieved latest secret: $($latestSecret.Name)" $password = Get-Secret -Name $latestSecret.Name -Vault $VaultName if ($AsPlainText) { Write-Warning "Returning password as plain text - ensure secure handling" return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) } else { return $password } } else { # Get secret by exact name Write-Verbose "Retrieving secret by name: $SecretName" # Check if secret exists and is not expired $secretInfo = Get-SecretInfo -Name $SecretName -Vault $VaultName -ErrorAction SilentlyContinue if (-not $secretInfo) { throw "Secret '$SecretName' not found in vault '$VaultName'" } # Check expiration if not including expired if (-not $IncludeExpired -and $secretInfo.Metadata.ExpirationDate) { try { $expirationDate = [DateTime]::Parse($secretInfo.Metadata.ExpirationDate) if ($expirationDate -lt (Get-Date)) { throw "Secret '$SecretName' has expired on $($expirationDate.ToString('yyyy-MM-dd HH:mm:ss')). Use -IncludeExpired to retrieve expired secrets." } } catch [System.FormatException] { Write-Verbose "Could not parse expiration date for secret: $SecretName" } } $password = Get-Secret -Name $SecretName -Vault $VaultName -ErrorAction Stop if ($AsPlainText) { Write-Warning "Returning password as plain text - ensure secure handling" return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) } else { return $password } } } catch { Write-Error "Failed to retrieve password from vault: $($_.Exception.Message)" -ErrorAction Stop } } end { Write-Verbose "Completed Get-ADTestPasswordFromVault - CorrelationId: $correlationId" } } |