Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export-PluginArgs : Access is denied #442

Closed
mshlmv opened this issue Jun 27, 2022 · 21 comments
Closed

Export-PluginArgs : Access is denied #442

mshlmv opened this issue Jun 27, 2022 · 21 comments
Assignees
Labels
bug Something isn't working

Comments

@mshlmv
Copy link

mshlmv commented Jun 27, 2022

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 = 'admin@xxx.com'

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

@rmbolger rmbolger self-assigned this Jun 27, 2022
@rmbolger rmbolger added the bug Something isn't working label Jun 27, 2022
@rmbolger
Copy link
Owner

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 = 'admin@xxx.com'

Set-PAServer LE_PROD

$DebugPreference = 'Continue'
$newCert = New-PACertificate $DnsName -AcceptTOS -Install -Contact $AdminCertEmail -Plugin Selectel -PluginArgs $pArgs -Verbose

@mshlmv
Copy link
Author

mshlmv commented Jun 28, 2022

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

@rmbolger
Copy link
Owner

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.

@mshlmv

This comment was marked as outdated.

@mshlmv
Copy link
Author

mshlmv commented Jun 29, 2022

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 :(

@rmbolger
Copy link
Owner

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

@webprofusion-chrisc
Copy link
Contributor

@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?

@mshlmv
Copy link
Author

mshlmv commented Jun 30, 2022

@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.

@rmbolger
Copy link
Owner

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).

@mshlmv
Copy link
Author

mshlmv commented Jul 4, 2022

@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:

@mshlmv
Copy link
Author

mshlmv commented Jul 4, 2022

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:

@rmbolger
Copy link
Owner

rmbolger commented Jul 4, 2022

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).

@mshlmv
Copy link
Author

mshlmv commented Jul 5, 2022

I get prompt only in LE_STAGE environment, if I enable LE_PROD, everything works fine

@mshlmv
Copy link
Author

mshlmv commented Jul 5, 2022

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.

@rmbolger
Copy link
Owner

rmbolger commented Jul 6, 2022

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?

@Tim-Co
Copy link

Tim-Co commented Jul 26, 2022

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.

@rmbolger
Copy link
Owner

rmbolger commented Jul 27, 2022

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.

@rmbolger
Copy link
Owner

@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?

@CaiB
Copy link
Contributor

CaiB commented Mar 5, 2023

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.

@rmbolger
Copy link
Owner

rmbolger commented Mar 5, 2023

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.

@rmbolger
Copy link
Owner

Added a FAQ entry about this on the doc site.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants