🧠 TL;DR
Storing credentials securely in PowerShell is a nightmare people love to ignore — until it bites them in the middle of an automation task. These two functions (Set-SecureCredential
and Get-SecureCredential
) let you store creds once and reuse them safely across your scripts, without hardcoding passwords or getting stuck at prompts.
Overview
You’re automating tasks across servers. You’ve got scripts managing Active Directory, shares, scheduled tasks — the usual chaos. Some require alternate credentials. And what do most folks do?
- Type
Get-Credential
into every script - Copy/paste creds into a
$securePassword = '...'
block (🙃) - Or worse — store plain-text passwords in a file
None of that scales, and all of it’s risky. So, these two functions fix it:
You can clone this from my git repo.
🧰 Before You Start
What these functions do:
Set-SecureCredential
Prompts for a username and password, then saves it securely as an encrypted.secxml
file in yourcommon
folder.Get-SecureCredential
Reads that.secxml
file back in, and assigns it as a global variable using the alias you gave it.
What you need:
- PowerShell
- The
common
folder in your HEMM module - You running the function on the same machine and user profile that created it (that’s how
Export-CliXml
security works)
🔐 Security considerations
When it comes to storing credentials in PowerShell, Export-CliXml
is the best native option — it encrypts creds using your current user and machine context, meaning the files can’t be decrypted by anyone else. That said, security is only as strong as your weakest link, and if your account password is weak tea, that encrypted file might as well be plain text. These credential files are obscured with .secxml
extensions and aliased filenames (like HE-DEV_SCF.secxml
), which helps avoid drawing attention — but that doesn’t mean you can skip good hygiene. Make sure the account used to create these creds follows a proper password policy. No P@ssword123
. No reused secrets. If you’re automating admin tasks, act like one.
🧾The scripts
Set-SecureCredential
<#
.SYNOPSIS
Creates Secure credentials and stores them to be used later.
.DESCRIPTION
Prompts for credentials and saves them securely as an XML file under the "common" folder.
These can then be recalled in other functions using the saved alias.
.PARAMETER Alias
Optional alias to name the credential file. Defaults to 'SCF.secxml' if not provided.
.EXAMPLE
Set-SecureCredential -Alias HE-DEV
.NOTES
Author : Ashley Hay-Ellis
Version : 1.0
License : MIT
Change History:
2025-05-10 : Initial release
#>
function Set-SecureCredential {
[CmdletBinding()]
param (
[string]$Alias
)
$FileName = if ($Alias) { "${Alias}_SCF.secxml" } else { "SCF.secxml" }
$FilePath = ".\common\$FileName"
if (Test-Path -Path $FilePath) {
$response = Read-Host "File '$FilePath' already exists. Overwrite? (Y/N)"
if ($response -notin @('Y','y')) {
Write-Host "Credentials not updated." -ForegroundColor Yellow
return
}
}
$Credential = Get-Credential
$Credential | Export-CliXml -Path $FilePath
Write-Host "Credential saved to '$FilePath'" -ForegroundColor Green
}
Get-SecureCredential
<#
.SYNOPSIS
Loads secure credentials from a saved file and stores them as a global variable.
.DESCRIPTION
Reads credentials previously saved using Save-CredentialSecurely.
Imports the XML file and stores the result in a global variable named after the alias.
.PARAMETER Alias
The alias used when saving the credential.
.EXAMPLE
Get-SecureCredential -Alias HE-DEV
.NOTES
Author : Ashley Hay-Ellis
Version : 1.1
License : MIT
Change History:
2025-05-10 : Initial release
2025-05-11 : Standardised naming, improved error handling
#>
function Get-SecureCredential {
[CmdletBinding()]
param (
[string]$Alias
)
$FileName = if ($Alias) { "${Alias}_SCF.secxml" } else { "SCF.secxml" }
$FilePath = ".\common\$FileName"
if (-not (Test-Path -Path $FilePath)) {
Write-Warning "No credentials found for alias '$Alias'."
Write-Host "Run Set-SecureCredential -Alias $Alias to create them." -ForegroundColor Yellow
return
}
try {
$Credential = Import-CliXml -Path $FilePath
New-Variable -Name $Alias -Value $Credential -Scope Global -Force
Write-Host "Credential loaded into variable '$Alias'" -ForegroundColor Green
} catch {
Write-Error "Failed to import credential from $FilePath"
}
}
📦 How It Works
🧾 Step 1: Save your credentials
Set-SecureCredential -Alias HE-DEV
You’ll get prompted to enter creds. The function will save them as:
.\common\HE-DEV_SCF.secxml
🧾 Step 2: Load them in later
Get-SecureCredential -Alias HE-DEV
The function will:
- Load the
.secxml
file - Store it in a global variable called
$HE-DEV
So now in any function or script, you can use:
Invoke-Command -ComputerName SERVER01 -Credential $HE-DEV
Clean. Consistent. No prompts.
🛑 What This Doesn’t Do
- It won’t let you use the creds on a different machine or user profile — this isn’t a vault
- It won’t let you store multiple usernames under the same alias without overwriting
- It won’t commit your
.secxml
files to Git unless you’re reckless (you did add them to.gitignore
, right?)
✅ Final Thoughts
Credentials are always a pain — until you bake in a system to handle them. These two functions give you just enough control without having to build or deploy a full credential vault. For internal modules, small teams, or solo admins who care about doing things right, this setup hits the sweet spot between secure enough and actually usable.