Retrieving Secrets by name when the name is a variable

Product: PowerShell Universal
Version: 2026.1.3

Hi everyone,

First of all, let me disclose tht I’m far from being an expert on PSU since I have only started working with it in a test environment recently, neither am I a professional programmer - I’m a hobbyist at best.
I’ve been prototyping a PSU-based solution to replace an old internal system and I’ve been experimenting with PSU Variables and Secrets.

To sum-up what I’m trying to do:

Our users need to log into to various Web services with generic accounts (ex: one account per geographical site on each service) but naturally, we don’t want to share the credentials openly with everyone who needs access.

For this, they have an SSO-based intranet dashboard that calls web automation scripts (which I’m also working on converting from an older technology to Playwright).
I managed, by script, to export and import Secrets into PSU in the PSCredential format and when I try to retrieve them individually, everything works no problem.

However, the way I wanted to do things was to have one script per service, which would then fetch the right set of credentials based on the user’s geographical site and potnetially other variables.

That’s where my issue arises:

Our Secret variables are named following a structure like say ServiceName_GeoSiteName
So if I construct the variable by doing
$SecretName = $ServiceName+“_”+$UserGeoSite
I cannot seem to find a way to use $SecretName to call the Secret with
$Secret:$SecretName
Unexpected token ‘$SecretName’ in expression or statement.
I’ve tried fiddling around whith brackets, parenthesis, moving the $ sign about but I cannot figure a way to dynamically refer to a Secret.
Is there a way to call a Secret like this where the name of the Secret is not known prior to user interaction?
Am I going at it wrong / is my logic flawed?

Thank you for your help!

You could do it with subexpressions and the secret provider.

Here is an older post that may help:

Thank you for your reply, do you have any specific pointers as to how to do it?

I cannot seem to get it to work, I’ve tried the forms mentioned in the linked thread (and the link within as well) and tinkering with them but to no avail.

For example if I attempt to use composed structures such as:

$("Secret:$SecretName")

It simply ends up printing

Secret:$SecretName

Whereas various attempts at

$(Get-ChildItem -Path "Secret:$SecretName")

Throws the following error:

Cannot find path 'NameOfMySecret' because it does not exist.

Is that what you meant by subexpressions?

Try it like this:

$SecretName = “name”

Get-ChildItem -Path “Secret:$($SecretName)”

edit:

After checking again the subexpression is not needed.

This works for me:

Get-ChildItem -Path "Secret:$SecretName"

Okay, so your solution works and I realize that I’m being hindered by an underlying issue I had not detected sooner.

For reference, here is my testing code:

$tool = 'WebService'
$site = 'SiteID'
$SecretName = $tool+'_'+$site

$user = 'UserName01'
$passw = 'PassWord01!'
$passw = ConvertTo-SecureString $passw -AsPlainText -Force #Please don't shame me for insecure practices
$credsObject = New-Object System.Management.Automation.PSCredential($user,$passw)

#Creating the secret
New-PSUVariable -Name $SecretName -Vault "Database" -Type "PSCredential" -InputObject $credsObject -Description "Test variable for secret creation via script" -Tag "Playwright" -TrustCertificate

#Retrieving it as a test
Get-ChildItem -Path "Secret:$($SecretName)"

When I run it, the Secret is seemingly correctly created

(Can’t post screenshot of the successful prompt window creating the secret because media limit)

image

But the retrieval fails with error:

Cannot find path 'WebService_SiteID' because it does not exist.
at <ScriptBlock>, [Redacted]\Test_CreateSecrets.ps1: line 14

However, if I create the secret with the same information but manually using the PSU Variables GUI (and remove the New-PSUVariable line) it works perfectly

(Can’t post screenshot of the successful prompt window returning the username and password because media limit)

Clearly, the problem appears to be with Secrets created automatically through scripts… If you have any idea of what I’m doing wrong with that New-PSUVariable command, I’d be a big help!

Thank you again

(Edit: fake news, i take it back)
Oh yeah, you can only create variables with New-PSUVariable, not secrets. So your script will probably work if you leave out the “Secret:” part.

Yesterday, I found that there is a PSU API for the Secrets. Maybe you will have more luck with it.

I ended up using the Secret Management module to dynamically save and retrieve secrets before I knew about the API.

Long sigh

I see, thank you for your help and guidance I will look into that API thingy you mentionned.

1 Like

I don’t mean to double-down or start a conversation, but isn’t it odd that the cmdlet New-PSUVariable allows you to create “Variables” that:

  • Are marked as “Secret” in the creation output
  • Take PSCredentials as InputObject
  • Are hinted as being Secrets in the GUI

Yet are not retrievable by the $Secret:SecretName call?

Everything seems to indicate that it can create Secrets but the aforementioned created secrets are not correctly fetchable.

1 Like

So, I had time to mess around a bit more and it turns out that if I create a Secret using:

New-PSUVariable -Name $SecretName -Vault "Database" -Type "PSCredential" -InputObject $credsObject -Description "Test variable for secret creation via script" -Tag "Playwright" -TrustCertificate

It “cannot be found because it does not exist” when I try to retrieve it with

Get-ChildItem -Path "Secret:$($SecretName)"

However, if I go to the Variables GUI and edit the contents of the “broken” Variable by hand (changing username and password) it works and can then be retrieved using the very same code.

That behavior really cements the idea in my mind of there being a bug with the way New-PSUVariable interacts with PSCredentials, SecureStrings, Secrets or something like of the sort.

OR I really suck and I’m constructing my InputObject wrong..?

Huh, this is interesting.

I can verify this behavior. The variable is only available in the $Secret: scope after it is edited in the UI.

However, the secret is immediately available with.

Get-PSUVariable -Name $SecretName

Guess I came to the wrong conclusions about New-PSUVariable when I was trying to save secrets.

1 Like

Ah, happy to see I’m not just losing my marbles!

But does Get-PSUVariable -Name $SecretName let you retrieve the PSCredentials?

I wasn’t able to using this method.

Bad wording from me. I meant to say the variable object can be retrieved, but it’s also empty.

I think it’s definitely a bug and should be reported as a GitHub issue.

1 Like

@AurelienByCF Maybe this is how it is supposed to be used?


$user = 'UserName01'

$passw = 'PassWord01!'

$passw = ConvertTo-SecureString $passw -AsPlainText -Force

$SecretName = "testvar"


$var = New-PSUVariable -Name $SecretName -Vault "Database" -Type "PSCredential" -Description "Test variable for secret creation via script" 

$var | Set-PSUVariable -UserName $user -Password $passw -Name $SecretName 

"Get-ChildItem"

Get-ChildItem -Path "Secret:$SecretName"

"Get-PSUVariable"

Get-PSUVariable -Name $SecretName

'$secret:testvar'

$secret:testvar

'is $null?'

$null -eq $secret:testvar

1 Like

Wow! That works indeed, that’s so helpful, thank you! You’re a lifesaver.

I’m almost out of the weeds, but I do notice something:

With your method, when I try to convert the SecureString back to a usable string, it ends up giving me the literal text for the SecureString data type.

Code

Write-Output "Username: $retUser"
Write-Output "Password: $retPwd"
$decrypted = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($retPwd)
Write-Output "Password decryption step 1: $decrypted"
$decryptedPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($decrypted)
Write-Output "Password decryption step 2: $decryptedPassword"

Output

Username: UserName01
Password: System.Security.SecureString
Password decryption step 1: 1918782418872
Password decryption step 2: System.Security.SecureString

This decryption method normally works to retrieve the password in plaintext, but here it seems like the real value of $Password wasn’t really stored, and the password was set as literally “System.Security.SecureString” instead.

When I tried to shift back to a PSCredential object and pass it as InputObject in the Set-PSUVariable cmdlet, it’s the same issue from earlier all over again.

Perhaps this indicates a bug with the way the New/Set-PSUVariable cmdlets’ -InputObject argument handles PSCredential object types?

@Dynamic In the end you were right, the API calls create the Secret without any malfunction and are automatable so I will end up doing this I think.

For reference if someone else encounters the same issue:

Using the [POST] /api/v1/variable section from swagger/index.html

And sending this body:

{
  "id": 0,
  "name": "ApiTestSecret",
  "value": "",
  "userName": "ApiUsr",
  "password": "ApiPwd",
  "secret": true,
  "vault": "Database",
  "type": "PSCredential",
  "description": "Test API Secret",
  "missingSecret": false,
  "disableRunAsSupport": false,
  "deleteSecret": false,
  "readOnly": false,
  "database": false,
  "role": null,
  "scope": 0,
  "tags": [
    "Playwright"
  ],
  "roles": null,
  "force": false,
  "module": null,
  "required": false,
  "passwordNotRequired": false
}

Then retrieving it with:

$SecretName = 'ApiTestSecret'

$retUser = (Get-ChildItem -Path "Secret:$($SecretName)").Username
$retPwd = (Get-ChildItem -Path "Secret:$($SecretName)").Password

Write-Output "Username: $retUser"
Write-Output "Password: $retPwd"
$decrypted = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($retPwd)
Write-Output "Password decryption step 1: $decrypted"
$decryptedPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($decrypted)
Write-Output "Password decryption step 2: $decryptedPassword"

Correctly returns:

Username: ApiUsr
Password: System.Security.SecureString
Password decryption step 1: 1918966542200
Password decryption step 2: ApiPwd

I will nonetheless create a GitHub account and make a bug report about the New/Set-PSUVariable cmdlets with all our findings. You never know, maybe it’s an easy fix with the right info / repro steps.

Thank you again @Dynamic for your help, real MVP!

1 Like