Posh-ACME
Posh-ACME copied to clipboard
Export-PluginArgs : Access is denied
Hi there.
I have Posh-ACME 4.14.0 and I tried to get certificate with powershell script automation. But I get an error when passing the API key (apparently).
$ApiToken = 'XXX'
$DnsName = 'xxx.xxx.com'
$AdminCertEmail = '[email protected]'
Set-PAServer LE_PROD
$pArgs = @{ SelectelAdminToken = (ConvertTo-SecureString $ApiToken -AsPlainText -Force) }
$newCert = New-PACertificate $DnsName -AcceptTOS -Install -Contact $AdminCertEmail -Plugin Selectel
-PluginArgs $pArgs
At C:\Program Files\WindowsPowerShell\Modules\Posh-ACME\4.14.0\Public\Set-PAOrder.ps1:139 char:17
+ ... Export-PluginArgs -Order $order -PluginArgs $PluginArgs
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Export-PluginArgs], CryptographicException
+ FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Export-PluginArgs
Submit-ChallengeValidation : Cannot bind argument to parameter 'SelectelAdminToken' because it is null.
+ Submit-ChallengeValidation
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Submit-ChallengeValidation], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Submit-ChallengeValidation
Connected via ssh, I run this script as a local administrator on a computer in the domain
Hi @mshlmv, thanks for reaching out. I'm not seeing the Access Denied error in the output you posted. I do see a CryptographicException apparently thrown by Export-PluginArgs though. That error is likely the cause of the following error with Submit-ChallengeValidation. Can you try running your New-PACertificate call with Verbose and Debug output so I can hopefully get a better sense of where this is happening within Export-PluginArgs?
$ApiToken = 'XXX'
$DnsName = 'xxx.xxx.com'
$AdminCertEmail = '[email protected]'
Set-PAServer LE_PROD
$DebugPreference = 'Continue'
$newCert = New-PACertificate $DnsName -AcceptTOS -Install -Contact $AdminCertEmail -Plugin Selectel -PluginArgs $pArgs -Verbose
I'm sorry, I missed this line when copying.
OK, now full verbose output:
VERBOSE: Updating directory info from https://acme-v02.api.letsencrypt.org/directory
DEBUG: Requesting nonce from https://acme-v02.api.letsencrypt.org/acme/new-nonce
DEBUG: Saving PAServer to disk
DEBUG: Loading PAServer list from disk
DEBUG: Enabling cert validation
DEBUG: Loading PAAccount 607526636 from disk
DEBUG: Loading PAOrder list from disk
VERBOSE: Using ACME Server https://acme-v02.api.letsencrypt.org/directory
DEBUG: Loading PAAccount list from disk
VERBOSE: Using account 607526636
VERBOSE: Order name not specified, using 'xxx.xxx.com'
DEBUG: Loading PAOrder list from disk
DEBUG: Refreshing order 'xxx.xxx.com'
DEBUG: ACME Header:
{
"kid": "https://acme-v02.api.letsencrypt.org/acme/acct/607526636",
"alg": "ES256",
"nonce": "0002kcXxCVNYtFe-Tay6WPlMtKVfhJMenU5l9rMF0pav-i8",
"url": "https://acme-v02.api.letsencrypt.org/acme/order/607526636/101537792046"
}
DEBUG: ACME Payload: (empty)
DEBUG: Signing message using EC with SHA256
DEBUG: POST https://acme-v02.api.letsencrypt.org/acme/order/607526636/101537792046
{"payload":"","protected":"eyJraWQiOiJodHRwczovL2FjbWUtdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvYWNtZS9hY2N0LzYwNzUyNjYzNiIs
ImFsZyI6IkVTMjU2Iiwibm9uY2UiOiIwMDAya2NYeENWTll0RmUtVGF5NldQbE10S1ZmaEpNZW5VNWw5ck1GMHBhdi1pOCIsInVybCI6Imh0dHBzOi8
vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL29yZGVyLzYwNzUyNjYzNi8xMDE1Mzc3OTIwNDYifQ","signature":"6YJvjgPRAJEJJ
HyEPhJU8fv_7MyanspjKdHVIOkn5wU2XrLKVDLC0V6NeadXFatl8k1Gr1RAwz7A7nhWzIJ0RA"}
DEBUG: ACME Response:
{
"status": "pending",
"expires": "2022-07-04T12:39:48Z",
"identifiers": [
{
"type": "dns",
"value": "xxx.xxx.com"
}
],
"authorizations": [
"https://acme-v02.api.letsencrypt.org/acme/authz-v3/124245243236"
],
"finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/607526636/101537792046"
}
DEBUG: Updated nonce: 0002WUNBjNnrIohsm_Ve6cqWr-PNzzo5vPXX8BSsxlmonoY
DEBUG: Loading PAOrder list from disk
VERBOSE: Using existing order 'xxx.xxx.com' with status pending
DEBUG: Set order params:
{
"Plugin": [
"Selectel"
],
"Install": {
"IsPresent": true
},
"PluginArgs": {
"SelectelAdminToken": {
"Length": 31
}
}
}
DEBUG: Loading PAOrder list from disk
VERBOSE: Updating plugin args for plugin(s) Selectel
DEBUG: Exporting plugin args for order 'xxx.xxx.com' with plugins Selectel
DEBUG: Loading PAOrder list from disk
DEBUG: Attempting to load plugin Selectel
DEBUG: Removing old value for SelectelAdminToken
DEBUG: Adding new value for SelectelAdminToken
Export-PluginArgs : Access is denied.
At C:\Program Files\WindowsPowerShell\Modules\Posh-ACME\4.14.0\Public\Set-PAOrder.ps1:139 char:17
+ ... Export-PluginArgs -Order $order -PluginArgs $PluginArgs
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Export-PluginArgs], CryptographicException
+ FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Export-PluginArgs
DEBUG: ACME Header:
{
"kid": "https://acme-v02.api.letsencrypt.org/acme/acct/607526636",
"alg": "ES256",
"nonce": "0002WUNBjNnrIohsm_Ve6cqWr-PNzzo5vPXX8BSsxlmonoY",
"url": "https://acme-v02.api.letsencrypt.org/acme/authz-v3/124245243236"
}
DEBUG: ACME Payload: (empty)
DEBUG: Signing message using EC with SHA256
DEBUG: POST https://acme-v02.api.letsencrypt.org/acme/authz-v3/124245243236
{"payload":"","protected":"eyJraWQiOiJodHRwczovL2FjbWUtdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvYWNtZS9hY2N0LzYwNzUyNjYzNiIs
ImFsZyI6IkVTMjU2Iiwibm9uY2UiOiIwMDAyV1VOQmpObnJJb2hzbV9WZTZjcVdyLVBOenpvNXZQWFg4QlNzeGxtb25vWSIsInVybCI6Imh0dHBzOi8
vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2F1dGh6LXYzLzEyNDI0NTI0MzIzNiJ9","signature":"zNLXgs7Jl3LWdZZoKHDdhoS
lGiOlaLVuWRtbrfPtCV7mx-YjF1pCx_CG6VGIV456KxiMKm89eAEjWMXEfH1z0Q"}
DEBUG: ACME Response:
{
"identifier": {
"type": "dns",
"value": "xxx.xxx.com"
},
"status": "pending",
"expires": "2022-07-04T12:39:48Z",
"challenges": [
{
"type": "http-01",
"status": "pending",
"url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/124245243236/00RVaw",
"token": "hXc83dLae99UfFuLEtcQM4jseoxVILrWkUV23EO2nzA"
},
{
"type": "dns-01",
"status": "pending",
"url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/124245243236/FiEUww",
"token": "hXc83dLae99UfFuLEtcQM4jseoxVILrWkUV23EO2nzA"
},
{
"type": "tls-alpn-01",
"status": "pending",
"url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/124245243236/MBXugg",
"token": "hXc83dLae99UfFuLEtcQM4jseoxVILrWkUV23EO2nzA"
}
]
}
DEBUG: Updated nonce: 0002awnsXJl_BMFXhNp7GzCQpZyC06dpNPK-Ex8TLv5jODA
DEBUG: Plugin: Selectel
DEBUG: DnsAlias:
DEBUG: Loading PAOrder list from disk
VERBOSE: Publishing challenge for Domain xxx.xxx.com with Token hXc83dLae99UfFuLEtcQM4jseoxVILrWkUV23EO2nzA
using Plugin Selectel and DnsAlias ''.
DEBUG: Loading PAAccount list from disk
DEBUG: Calling Selectel plugin to add _acme-challenge.xxx.xxx.com TXT with value
ciTDUdz9i1BRxvJFI1T-38O5Tiq19776eZbdPVbDH8A
Submit-ChallengeValidation : Cannot bind argument to parameter 'SelectelAdminToken' because it is null.
At C:\Program Files\WindowsPowerShell\Modules\Posh-ACME\4.14.0\Public\New-PACertificate.ps1:242 char:9
+ Submit-ChallengeValidation
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Submit-ChallengeValidation], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Submit-ChallengeValidation
DEBUG: Refreshing order 'xxx.xxx.com'
DEBUG: ACME Header:
{
"kid": "https://acme-v02.api.letsencrypt.org/acme/acct/607526636",
"alg": "ES256",
"nonce": "0002awnsXJl_BMFXhNp7GzCQpZyC06dpNPK-Ex8TLv5jODA",
"url": "https://acme-v02.api.letsencrypt.org/acme/order/607526636/101537792046"
}
DEBUG: ACME Payload: (empty)
DEBUG: Signing message using EC with SHA256
DEBUG: POST https://acme-v02.api.letsencrypt.org/acme/order/607526636/101537792046
{"payload":"","protected":"eyJraWQiOiJodHRwczovL2FjbWUtdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvYWNtZS9hY2N0LzYwNzUyNjYzNiIs
ImFsZyI6IkVTMjU2Iiwibm9uY2UiOiIwMDAyYXduc1hKbF9CTUZYaE5wN0d6Q1FwWnlDMDZkcE5QSy1FeDhUTHY1ak9EQSIsInVybCI6Imh0dHBzOi8
vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL29yZGVyLzYwNzUyNjYzNi8xMDE1Mzc3OTIwNDYifQ","signature":"X9zDMs60B_leZ
lAUMR7dvSd1O5ETPU6k0DtKDw-dL1XalK5w0qR0_CcTyQfyrDjrWWAOXtlzFNYDkFnmu1DWNg"}
DEBUG: ACME Response:
{
"status": "pending",
"expires": "2022-07-04T12:39:48Z",
"identifiers": [
{
"type": "dns",
"value": "xxx.xxx.com"
}
],
"authorizations": [
"https://acme-v02.api.letsencrypt.org/acme/authz-v3/124245243236"
],
"finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/607526636/101537792046"
}
DEBUG: Updated nonce: 0002daI5Bpzc2wWcw8RwQ2DFWnQCimBok-trrLaopJjeDTY
DEBUG: Loading PAOrder list from disk
Ok, there's the Access Denied still seeming to happen during an export of the plugin args. It seems I don't have enough debug logging enable to know exactly which line inside Export-PluginArgs
is triggering the error. But my guess is it's happening when it tries to write the file to disk.
Are you using an alternate config location by any chance? Or is there any reason why the order's pluginargs.json file wouldn't be writable by the user running the module? You can find the exact folder location using (Get-PAOrder).Folder
.
No, the config is located by default in the user's home directory.
I guess the problem is with running the ConvertTo-SecureString
module inside Posh-ACME.
If I pass an API token from stdin, like this
$pArgs = @{
SelectelAdminToken = (Read-Host 'API key' -AsSecureString)
}
then everything works fine.
No, the config is located by default in the user's home directory.
Now I run the script as a domain administrator and it works fine
Why local administrator rights are not enough for this is not clear :(
The fact that it works with domain admin and not local admin is even more weird when using the default home directory location. The basic module functionality should work even with a non-admin account when writing to the home directory. Are home directories on this server mounted from a network location or synchronized with OneDrive? Something that would make them not as simple as just a folder structure on the local disk?
You could probably run some filesystem specific tests by like creating a folder in LOCALAPPDATA and trying to create a file in it.
$testdir = Join-Path $env:LOCALAPPDATA 'mytest'
if (-not (Test-Path $testdir -PathType Container)) {
New-Item -ItemType Directory -Path $testdir -Force -EA Stop
}
'test content' | Out-File (Join-Path $testdir 'myfile.txt') -Force -EA Stop
@mshlmv out of interest, what version of windows are you running and what malware/defender type protection is running? Any non-default settings you can think of?
@rmbolger thank you for guess. I tested it and it didn't lead me to a sad result, everything works fine :)
@webprofusion-chrisc thank you for your interest. I have a version of Windows Server 2019 core, a fresh installation without additional settings, security features (firewall) are disabled. Just join in the domain, the GPO is also missing.
I tested it and it didn't lead me to a sad result, everything works fine :)
By "everything", do you mean the cert issuance or just the test code I posted?
If the cert issuance still results in an error, you might try deleting the existing Posh-ACME
config folder from LOCALAPPDATA and effectively starting over. If there are some non-standard ACLs on something in there that would be causing this issue, it's a quick way to reset everything. Just remember to force re-import the module if you're in the same PowerShell session after you delete the folder (Import-Module Posh-ACME -Force
).
@rmbolger following your last advice I get this
rm -r C:\Users\local-admin\AppData\Local\Posh-ACME\
Import-Module Posh-ACME -Force
Set-PAServer LE_STAGE
Please review the Terms of Service here: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
$newCert = New-PACertificate $DnsName -AcceptTOS -Install -Contact $AdminCertEmail -Plugin Selectel
-PluginArgs $pArgs
Export-PluginArgs : Access is denied.
At C:\Program Files\WindowsPowerShell\Modules\Posh-ACME\4.14.0\Public\New-PAOrder.ps1:306 char:9
+ Export-PluginArgs -Order $order -PluginArgs $PluginArgs
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Export-PluginArgs], CryptographicException
+ FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Export-PluginArgs
cmdlet Add-DnsTxt at command pipeline position 1
Supply values for the following parameters:
SelectelAdminToken:
Now I'm testing it on a non-domain server and I don't get an error, but I still get a value request for the token
cmdlet Add-DnsTxt at command pipeline position 1
Supply values for the following parameters:
SelectelAdminToken:
On the non-domain server, had you setup your $pArgs
variable with the proper value first? If there were no other errors, that prompt usually just means the hashtable passed to -PluginArgs
is either null, empty, or has values that don't match the required parameter names for the plugin (or perhaps typo'd names).
I get prompt only in LE_STAGE environment, if I enable LE_PROD, everything works fine
After a series of experiments , I can draw several conclusions
On a non-domain computer, if you run Posh-ACME by connecting via SSH as a local administrator, then nothing works. If you connect via RDP by the same user, then everything works fine.
On a domain computer under a domain administrator, both SSH and RDP work. And it does not work under the local administrator in any way.
I can't say I've tested using Posh-ACME via SSH against a Windows box. But I don't see why the protocol used to connect would make a difference. I don't doubt the results of your tests. I just don't have the expertise to explain why it might be happening. The differences between a domain-joined system and non-domain-joined are also a mystery.
At the end of the day, what the module is doing under the hood for the Export-PluginArgs
function that is failing is just not that complicated. It's using native PowerShell functions to serialize some SecureString objects and write them to disk as JSON in the current user's LOCALAPPDATA. None of it requires UAC elevated permissions in the OS. It shouldn't require local or domain administrator permissions. Whatever is wrong feels very environment specific. Something about your OS deployment or security configuration is different than everyone else who seems to be working.
Out of curiosity, what OS version are we talking about here? What SSH server?
I'm also getting this error. I'm running the script as part of an ansible playbook and it's connecting via winrm. The server is running windows 2019, domain joined, and running on AWS.
I may have stumbled on the culprit after I started looking for other places you might get Access Denied during that function call. My current theory is that the Access Denied is actually happening on the calls to ConvertFrom-SecureString that use the Windows DPAPI libraries by default. This blog post explains a bit more about what might be going on.
https://blog.stangroome.com/2012/05/17/powershell-remoting-user-profiles-delegation-and-dpapi/
If I'm right, a workaround should be fairly simple. You'll need to enable UseAltPluginEncryption
on the PAAccount object being used to request the cert. This can either be done at account creation time using New-PAAccount -UseAltPluginEncryption -AcceptTOS
or after the fact using Set-PAAccount -UseAltPluginEncryption
. Once that is done, you can test it by either re-writing the plugin args in your existing PAOrder (Set-PAOrder -Plugin blah -PluginArgs $pArgs
) or just re-running your original New-PACertificate
command.
The UseAltPluginEncryption flag basically changes how the SecureString and PSCredential variables are saved to disk that doesn't rely on DPAPI anymore.
@Tim-Co or @mshlmv Were either of you able to confirm whether enabling the UseAltPluginEncryption
flag fixed the access denied issues when using the module over a remote connection?
I just ran into the same issue while setting up some new servers, and as above it was happening only when I was using PowerShell remoting (WinRM). -UseAltPluginEncryption
fixed the issue.
Thanks for the confirmation, @CaiB. I'm not sure if there's anything I can necessarily do in the module to avoid needing the Alt Plugin Encryption workaround. But I'll try to find a good place in the docs to mention it might be necessary when using PS remoting.
Added a FAQ entry about this on the doc site.