From 8c9661bae48486a0348757a6ab5208806bc1f0ef Mon Sep 17 00:00:00 2001 From: Andrew Yager Date: Wed, 27 May 2026 18:14:21 +1000 Subject: [PATCH] Docs: reflect Repair-AcmeDnsCredential auto-recovery + ARI cleanup README's "Renewals Silently Failing" callout and the matching troubleshooting.md section both said the script prompts for the acme-dns /register password. With the auto-recovery change in this PR that's no longer the default path: running as the same admin that registered the domain unwraps the password from the existing DPAPI blob automatically. The docs also didn't mention the new ARI cache cleanup or the interactive renewal prompt. - README: drop "will prompt" wording; note the auto-recovery precondition (run as original user), the ARI cleanup, and the renewal prompt; simplify the example. - troubleshooting.md: same description update plus an unattended-mode example using -Password + -RunRenewal Yes. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 13 ++++++------- docs/troubleshooting.md | 9 +++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f785368..c573390 100644 --- a/README.md +++ b/README.md @@ -257,12 +257,13 @@ Toolkit versions ≤ v1.0.3 stored acme-dns credentials using DPAPI in `CurrentU - `%ProgramData%\win-acme\acme-v02.api.letsencrypt.org\Log\log-*.txt` contains `ConvertTo-SecureString : ... CryptographicException` and `Failed to decrypt password. This usually means the credential was stored by a different user or on a different machine.` - The credential JSON in `%ProgramData%\WinCertManager\Config\acme-dns\` reports `"StorageMethod": "DPAPI"` -**Fix:** `scripts/Recovery/Repair-AcmeDnsCredential.ps1` re-encrypts the credential under DPAPI `LocalMachine` scope (so SYSTEM can decrypt it) without changing the acme-dns subdomain registration — no DNS changes required. Run it once per affected host. Toolkit ≥ v1.0.4 stores new credentials in `LocalMachine` scope by default, so fresh installs are unaffected. +**Fix:** `scripts/Recovery/Repair-AcmeDnsCredential.ps1` re-encrypts the credential under DPAPI `LocalMachine` scope (so SYSTEM can decrypt it) without changing the acme-dns subdomain registration — no DNS changes required. Run it once per affected host as the same admin that originally registered the domain; the script then recovers the password from the existing DPAPI blob automatically, so you don't need it from a password manager. It also clears any stale win-acme ARI cache entries that may be holding a "replacement" slot for the failed cert and offers to run the renewal interactively. Toolkit ≥ v1.0.4 stores new credentials in `LocalMachine` scope by default, so fresh installs are unaffected. -> **Verify the script before running it.** Open it in a text editor or run `Get-AuthenticodeSignature` against a copy from a signed release ZIP. The script will prompt for the original acme-dns password (the `password` field returned by `/register`, retrievable from your password manager). +> **Verify the script before running it.** Open it in a text editor or run `Get-AuthenticodeSignature` against a copy from a signed release ZIP. If you're running as a different operator from the one that originally registered the domain, the script will fall back to prompting for the `password` field returned by `/register` (retrievable from your password manager). ```powershell -# On the affected host, in an elevated PowerShell session: +# On the affected host, in an elevated PowerShell session, +# signed in as the admin that originally registered the domain: $url = 'https://raw.githubusercontent.com/realworldtech/wincertmanager/main/scripts/Recovery/Repair-AcmeDnsCredential.ps1' $dest = Join-Path $env:TEMP 'Repair-AcmeDnsCredential.ps1' Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing @@ -270,11 +271,9 @@ Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing # REVIEW the file before executing: notepad $dest -# Then run for the affected domain (will prompt for the acme-dns password): +# Then run for the affected domain. Auto-recovers the password, +# clears the ARI cache, and prompts to run wacs.exe --renew: & $dest -Domain 'dc01.internal.example.com' - -# After repair, force a renewal to confirm: -& 'C:\Tools\win-acme\wacs.exe' --renew --force --verbose ``` If you prefer a signed copy, download the latest release ZIP from the [Releases page](https://github.com/realworldtech/wincertmanager/releases), verify the SHA256, and run the script from `scripts/Recovery/` inside the extracted directory. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 0c3e180..ebc8397 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -194,17 +194,18 @@ The renewal log will show the error inside `Get-AcmeDnsCredential.ps1` while run **Solutions:** -For cause 1 (DPAPI scope mismatch), use the recovery tool to re-encrypt under machine scope without losing the existing acme-dns subdomain registration (no DNS changes needed): +For cause 1 (DPAPI scope mismatch), use the recovery tool to re-encrypt under machine scope without losing the existing acme-dns subdomain registration (no DNS changes needed). Run it as the same admin that originally registered the domain — the script then unwraps the password from the existing CurrentUser DPAPI blob and you don't need to supply it: ```powershell .\scripts\Recovery\Repair-AcmeDnsCredential.ps1 -Domain "example.com" -# Prompts for the original acme-dns password from /register ``` -After the repair, force a renewal to confirm: +The script also clears stale win-acme ARI cache entries for the domain (so the next `new-order` doesn't fail with `urn:ietf:params:acme:error:alreadyReplaced` because of leftover pending orders from earlier failed attempts) and prompts to run `wacs.exe --renew --force --verbose` immediately. For unattended runs, pass `-RunRenewal Yes` (or `No`) to skip the prompt; if you're running as a different operator from the one that registered, pass `-Password` (a `[SecureString]`) explicitly: ```powershell -C:\Tools\win-acme\wacs.exe --renew --force --verbose +# Unattended, original user not available: +$pw = ConvertTo-SecureString $env:ACMEDNS_PASSWORD -AsPlainText -Force +.\scripts\Recovery\Repair-AcmeDnsCredential.ps1 -Password $pw -RunRenewal Yes -Confirm:$false ``` Toolkit ≥ v1.0.4 registers new credentials with `StorageMethod = DPAPI-LocalMachine` by default, so this issue does not affect fresh installs. Existing legacy installs only need the repair script run once.