Public/Get-SecureCredential.ps1
<#
.SYNOPSIS Retrieves stored credentials from an encrypted file. .DESCRIPTION This function retrieves stored credentials from an encrypted file. If a plaintext credential file is found, it encrypts the credentials and deletes the plaintext file. .PARAMETER EncryptedCredsName The name of the credential to be retrieved. .OUTPUTS PSCredential The retrieved credentials. .EXAMPLE $credential = Get-SecureCredential -EncryptedCredsName "MyCredentials" $credential.UserName $credential.GetNetworkCredential().Password The function first checks if a plaintext credential file exists. If found, it reads the credentials, encrypts them, deletes the plaintext file, and stores the encrypted credentials. If no plaintext file is found, it attempts to load the encrypted credentials directly. #> function Get-SecureCredential { [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', 'EncryptedCredsName', Justification = 'This parameter does not contain plaintext password')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '' ,Justification = 'This functionality allows encrypting plaintext password and storing securely')] param ( [Parameter(Mandatory = $true)] [Alias('Name')] [string]$EncryptedCredsName ) $CredentialFileRoot = (Resolve-Path .\).Path $PlaintextCredsFileName = "$EncryptedCredsName.plaintext" $EncryptedCredsFileName = "$EncryptedCredsName.encrypted" $PlaintextCredsFile = Join-Path -Path $CredentialFileRoot -ChildPath $PlaintextCredsFileName $EncryptedCredsFile = Join-Path -Path $CredentialFileRoot -ChildPath $EncryptedCredsFileName Write-Debug "Checking for plaintext credential file at '$PlaintextCredsFile'..." if (Test-Path -Path $PlaintextCredsFile -PathType Leaf) { Write-Debug "Plaintext credential file found at '$PlaintextCredsFile'." $Content = Get-Content -Path $PlaintextCredsFile $LineCount = ($Content | Measure-Object).Count if ($LineCount -ne 2) { Throw "Credential file has incorrect structure (line count: $LineCount). Please refer to the script help for details about credential management." } Write-Verbose "Encrypting credentials and removing plaintext file." # Overwriting plaintext file content to mitigate file restoration attack vector "Plaintext credentials removed" | Out-File -FilePath $PlaintextCredsFile -Force Remove-Item -Path $PlaintextCredsFile -Force -ErrorAction Stop # Writing new credentials $NewCreds = [PSCredential]::New($Content[0], ($Content[1] | ConvertTo-SecureString -AsPlainText -Force)) $Content = $null $NewCreds | Export-Clixml -Path $EncryptedCredsFile -Force Write-Verbose "Credentials saved to '$EncryptedCredsFile'." } elseif (-not (Test-Path -Path $EncryptedCredsFile -PathType Leaf)) { Throw "Credential file '$EncryptedCredsFile' could not be found." } try { $Credential = Import-Clixml -Path $EncryptedCredsFile } catch { Throw "An error occurred while loading credentials. Message: $($_.Exception.Message)" } Write-Verbose "Encrypted credentials for '$EncryptedCredsName' loaded successfully." return $Credential } |