Skip to content

Instantly share code, notes, and snippets.

@eizedev
Forked from altrive/SavedCredential.ps1
Created October 9, 2020 09:38
Show Gist options
  • Save eizedev/0e083c23d5c68183cc4b88e9c8c31cea to your computer and use it in GitHub Desktop.
Save eizedev/0e083c23d5c68183cc4b88e9c8c31cea to your computer and use it in GitHub Desktop.
Credential management utilities for PowerShell

Summary

Credential management utilities for PowerShell.

Cmdlets:

Set-SavedCredential
Set credential information to config file.
Get-SavedCredential
Get credential information from config file. if no credential found, show credential enter dialog.
Show-SavedCredential
Show credentials list stored in config file
Clear-SavedCredential
Remove config file
Test-Credential
Validate credential

Note

  • Credentials is stored at user %Temp% directory, "SavedCredentials\Credentials.xml" config file.
  • Config file is stored at Temp directory, so it is not persisted, may be deleted in some case.
  • Password in config file is encypted by Convert-FromSecureString(DAPI is used internally)
  • Config file is valid for LocalMachine/Currentuser context only.

Usage

#Set credential informations before use
Set-SavedCredential -Id "LocalAdmin"  -UserName "localhost\Administrator" -Password "Password!" 
Set-SavedCredential -Id "FileShare"   -UserName "localhost\FileShare"     -Password "Password!"
Set-SavedCredential -Id "DomainAdmin" -UserName "TEST\Administrator"      -Password "Password!"
Set-SavedCredential -Id "SqlAdmin"    -UserName "TEST\sqlSvc"             -Password "Password!"

#Show credentials
Show-SavedCredential

#Get PSCredential by Id
$cred1 = Get-SavedCredential -Id "LocalAdmin"
$cred2 = Get-SavedCredential -Id "FileShare"  -Validate

#Remove saved config file(Recommended for Production Environment)
Clear-SavedCredential
#Requires -Version 3
#Credential file path
$script:CredentialsFile = Join-Path $env:TEMP "SavedCredentials\Credentials.xml"
function Set-SavedCredential()
{
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]
$Id,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]
$UserName,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]
$Password,
[switch] $Validate
)
#Validate credential
if($Validate)
{
if($UserName.StartsWith("localhost\")){
$validationContext = "Machine"
}else{
$validationContext = "Domain"
}
$isValid = Test-Credential -UserName $UserName -Password $Password -Context $validationContext
if(!$isValid){
Write-Error ("Credential Validation Failed: {0}({1})" -f $Id, $UserName)
}
}
#Convert password to SecureString plain text
$securePassword = $Password | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
#Get saved credential if exists
$credentials= @{}
if(Test-Path $CredentialsFile){
$credentials = Import-Clixml -Path $CredentialsFile
}
else{
#Ensure output directory exists
$baseDir = [IO.Path]::GetDirectoryName($CredentialsFile)
New-Item -Type Directory -Path $baseDir -ErrorAction Ignore | Out-Null
}
#add/edit credential
$credentials[$Id] = @{UserName=$UserName;Password=$securePassword}
#Save Credentials as CliXml Format
$credentials | Export-Clixml -Path $CredentialsFile -Encoding UTF8 -Force
}
function Get-SavedCredential
{
[CmdletBinding()]
[OutputType([Management.Automation.PsCredential])]
param(
[Parameter(Mandatory,Position=0)]
[ValidateNotNullOrEmpty()]
[string] $Id,
[switch] $Validate
)
$credentials = Import-Clixml -Path $CredentialsFile -ErrorAction Ignore
if(($credentials -eq $null) -or !($credentials.ContainsKey($Id)))
{
return Get-Credential -Message "Enter Credential for $Id" #Don't save credential for temporary use.
}
#Get saved credential
$result = $credentials[$Id]
#Convert to PSCredential
[string]$userName = $result.UserName
$securePassword = ConvertTo-SecureString $result.Password
$cred = New-Object System.Management.Automation.PsCredential($userName, $securePassword)
#Validate Credential
if($Validate){
if($cred.GetNetworkCredential().Domain -eq "localhost"){
$validationContext = "Machine"
}
else{
$validationContext = "Domain"
}
$isValid = Test-Credential -UserName $cred.UserName -Password $cred.GetNetworkCredential().Password -Context $validationContext
if(!$isValid){
Write-Error ("Credential Validation Failed: {0}({1})" -f $Id, $userName)
}
}
return $cred
}
function Clear-SavedCredential
{
[CmdletBinding()]
param()
if(Test-Path $CredentialsFile){
#Remove credential file
Remove-Item $CredentialsFile -Force
}
}
function Show-SavedCredential
{
[CmdletBinding()]
[OutputType([hashtable])]
param()
if(!(Test-Path $CredentialsFile)){
Write-Error "Credential file not found!"
}
$result = Import-Clixml -Path $CredentialsFile -ErrorAction Ignore
return $result
}
function Test-Credential
{
[CmdletBinding()]
[OutputType([bool])]
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $UserName,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Password,
[ValidateSet("Domain","Machine")]
[string] $Context = "Domain"
)
begin {
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ctx = New-Object DirectoryServices.AccountManagement.PrincipalContext($context)
}
process {
return $ctx.ValidateCredentials($userName, $password)
}
end{
$ctx.Dispose()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment