🧠 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
- 🧰 Before You Start
- 🔐 Security considerations
- 🧾The scripts
- 📦 How It Works
- 🛑 What This Doesn't Do
- ✅ Final Thoughts
- 🔗 More Articles in This Series
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-Credentialinto 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.secxmlfile in yourcommonfolder.Get-SecureCredential
Reads that.secxmlfile back in, and assigns it as a global variable using the alias you gave it.
What you need:
- PowerShell
- The
commonfolder in your HEMM module - You running the function on the same machine and user profile that created it (that’s how
Export-CliXmlsecurity 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-DEVYou’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-DEVThe function will:
- Load the
.secxmlfile - 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-DEVClean. 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
.secxmlfiles 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.
