Secrets Error in 2.6 (on Azure)

Thanks for bearing with me on this. I’ve got a PR in progress for this module and should have a viable workaround next year to avoid all these headaches (any many more) that the secret management is causing.

After making changes to the secret management module, it looks like I can successfully manage secrets through PSU in Azure against Azure Key Vault. I documented the process here.

I was able to successfully create a trigger that connects and registers the vault. I then created a secret through PSU and it stored it in Az Key Vault. Then I was able to use that secret in an API and script.

This is awesome, good work :slight_smile:

Resurrecting this old thread.

This morning, having updated to 3.1.5, we are sporadically getting the old Cryptography_DpApi_ProfileMayNotBeLoaded error when trying to access secrets.

I ask for $Secret:FooCredential inside a module, it works fine.

If I ask for it from a script, I get the error.

Even calling Get-AzKeyVaultSecret -Name FooCredential -VaultName MyVault is throwing the error.

@adam Can you remember what we did to fix this? Was it something you introduced in the back end?

Matt

I’m not sure why that would be happening all of a sudden. I don’t recall seeing this DpApi error. The problem that PSU was having with secret management was that it wasn’t threadsafe. We redesigned our secret management layer in v3 so this isn’t a problem any longer.

I found an exact issue with Posh-ACME. It’s using the Microsoft Secret Management module as well. It seems like they even implemented a work around (Set-AltPluginEncryption) to avoid this error. I’m not sure it’s helpful for figuring out what’s going on but it is interesting.

Are you running your scripts in the integrated environment when they fail? They don’t fail all the time?

Yeah I have a hand-rolled module that uses the $Secret scope and it works fine when I call it from a script, but if I try to get a secret from the script directly, it fails with that DpApi error.

Integrated environment, yeah.

Can you do me a favor and grab the full stack trace of the exception?

try {
$Secret:BadSecret 
} catch {
   $_.Exception.StackTrace 
} 

Hmm it’s not even catching an exception. I made my script look like this:

try {
    $Secret:TdCredential
} catch {
    Write-Host "Caught an exception! Here it is!"
   $_.Exception.StackTrace 
} 

… and the job output is literally just:

 [error] Cryptography_DpApi_ProfileMayNotBeLoaded 

EDIT: Tried this too, but got the same output:

try {
    Get-AzKeyVaultSecret -Name TdCredential -VaultName PSU
} catch {
    Write-Host "Caught an exception! Here it is!"
   $_.Exception.StackTrace 
} 

I don’t understand why it’s able to access the secrets if I do so from within a module though. Baffling.

Get this. I changed my script to this:


function Foo {
    param(
        [PSCredential] $Credential = $Secret:TdCredential
    )

    Write-Host $Credential.UserName
}

Foo

That outputs the username of my TdCredential secret.

So accessing a secret from the default value of a parameter (which is what my module does) works. But accessing it directly throws the DpApi error.

Does that help? My brain is starting to leak out of my ears.

Ah! This does throw the error though!


function Foo {
    param(
        [PSCredential] $Credential = $Secret:TdCredential
    )

    Write-Host $Credential.UserName

    $Secret:TdCredential
}

Foo

I think it’s something to do with accessing the credential as a “whole” object, rather than cracking it open and accessing the username and password (via GetNetworkCredential()) separately. The module in which I’m successfully accessing a secret is always cracking it open.

It’s clearly something to do with the way PowerShell is treating PSCredential/SecureString under the hood. If I crack open the credential object using GetNetworkCredential() I can successully read both the username and password, but if I try to work with it as a PSCredential object (which I have to - the functions I’m calling need it) it errors.

It looks like I can use the secret now if I just pass it intact to the function that needs it. It only throws the DpApi error if I try to output it to the pipeline. Maybe that was always the case.

The only reason I would’ve been trying to output the secret was to check if it was working, which at the time it may not have been because of the whole “Sync-PsuConfiguration -Integrated” not being called at startup after registering the key vault.

I don’t know if I’m wasting your time trying to chase this down, Adam. :frowning: