We have a build process that needs to decrypt a password which it then uses to connect to a database. We are using the Data Protection API (DPAPI) to encrypt the password at the machine scope on the build server (I'm logged in with my own domain account) using PowerShell:
[Security.Cryptography.ProtectedData]::Protect( $passwordBytes, $null, [Security.Cryptography.DataProtectionScope]::LocalMachine );
The decryption is also done in a PowerShell script, which is executed by CruiseControl.NET, running as our build user:
[Security.Cryptography.ProtectedData]::Unprotect( $encryptedbytes, $null, [Security.Cryptography.DataProtectionScope]::LocalMachine );
The call to Unprotect
, however, fails with the following message: "Key not valid for use in specified state.". According to the docs, this error can occur using impersonation, and the impersonating code should load the user's profile.
For security purposes, the build user is denied the Log on through Terminal Services right. To test the problem, I logged into the build server as myself, then used runas to open a PowerShell prompt as the build user:
runas /profile /user:DOMAIN\BUILDUSER powershell.exe
I then run the PowerShell script to unprotect/decrypt the password, and get the same error.
I used Process Monitor to watch for any failures or access denied events, and there weren't any.
I'm able to decrypt the password when I log in with my own domain account.
What's going on? Is my build user's profile not being loaded? Is there some security setting somewhere I don't know about to enable this? Why can't I decrypt the password?
Developer error. It turns out I was encrypting at the CurrentUser scope, not the LocalMachine scope. I updated my script and everything is working now.