feat: web dashboard, client ACL, hot-applied settings, and bounded certificate cache - #58
Closed
mprasodjo wants to merge 1 commit into
Closed
feat: web dashboard, client ACL, hot-applied settings, and bounded certificate cache#58mprasodjo wants to merge 1 commit into
mprasodjo wants to merge 1 commit into
Conversation
…d cert cache Fork of esnet/acme-proxy with an operational layer on top: - Admin web dashboard (login + sessions) on a dedicated port: overview, domain-grouped certificate history with per-domain request details (client IPs, timestamps, status, failure reasons), failed-request analysis, revocation history, certificate cache management with per-domain cache deletion, live ACME request log, ACL editor, settings editor. HTTPS shares the client-facing :443 certificate (same key and identity resolved through the cert cache) so no extra upstream issuance; background renewal swaps certs without restart. - File-based client ACL (IPs/CIDRs, '#' comments, hot reload, X-Forwarded-For aware, fail-closed) enforced at the ACME API layer. - Dashboard settings tab edits ca.json and applies changes without a daemon restart: atomic config swap, ACME account re-registration on upstream identity change, challenge provider rebuild, dynamic concurrency semaphore, dashboard listener rebind, manual TLS swap. Validated end-to-end before write; backup per save. - Bounded certificate cache (cert_cache_max_age, default 30 days) and proxy-own-cert age bound (tls_max_age_days) to stay safely inside upstream rate limits such as Let's Encrypt 5 certs/week/name. - HTTP-01 challenge listener closes when idle. - '#' comments supported in ca.json; dashboard and acl as top-level config blocks. - go-acme/lego upgraded to v5.4.1.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds an operational layer on top of acme-proxy: an admin web dashboard, a client access-control list, hot-applied runtime settings, and a rate-limit-safe certificate cache. It also upgrades lego to v5, supports
#comments inca.json, and refreshes the documentation.What's New
1. Transient HTTP-01 challenge listener
The shared HTTP-01 challenge server on port 80 now starts only when a certificate request begins and closes itself as soon as the last challenge completes. Port 80 is no longer held open for the lifetime of the process, it is only exposed while a challenge is actually being served.
2. Admin web dashboard
An optional, login-protected web console (
dashboardblock inca.json, enabled whenport> 0) served from the same process on its own listener:issuance/failure/revocation counts, certificates expiring within 7 days, recent activity feed
domain-grouped master/detail view: every issuance record per domain with client IPs, timestamps, status, failure reasons, validity windows; server-side search and pagination
full failure reason per request (no truncation), source IP, requested names
the dashboard serves the same certificate as the client-facing
:443listener, same key and identity resolved through the shared cert cache, so enabling it never causes an extra upstream issuance; renewal happens in the background and swaps without restart3. Client ACL
An optional file-based allow-list (
acl.file) gates every ACME API request:#comments supportedX-Forwarded-Foraware for reverse-proxy deployments; fails closed (deny all, logged) if the configured file becomes unreadable4. Hot-applied runtime settings
The dashboard's Settings tab edits a safe subset of
ca.jsonand applies changes without restarting the daemon: upstream CA identity (with automatic ACME account re-registration), challenge type/DNS provider, timeouts, cache bounds, concurrency limit (live semaphore resize), dashboard credentials and listener (rebind with graceful drain). Saves are validated end-to-end before anything is written; every save keeps a backup atca.json.bak-settings. You need to Restart when you change bind ip address.5. Bounded certificate cache
cert_cache_max_age(default 30 days): cached certificates stop being served once they exceed this age, forcing a fresh issuance. This bounds the renewal cadence so upstream per-name rate limits (e.g. Let's Encrypt's 5 certs/week) are never tripped by stale cache reusedashboard.tls_max_age_days(default 30): same bound for the proxy's own certificate, with background renewal and atomic swap6. Configuration ergonomics
ca.jsonsupports#comments outside string literals (string-aware stripper in the config loader); the_comment_*field workaround is gonedashboardandaclare top-level config blocks, outsideauthorityAbout the
fork/certificatesdirectoryThis PR carries a vendored copy of smallstep/certificates in-tree under
fork/, replacing the current module redirect(
replace github.com/smallstep/certificates => github.com/esnet/certificates v0.30.2-patch.2).Why: the new features require small hooks inside step-ca itself, a per-request metadata hook (client IP / CSR / serial), an optional per-request ACL gate in the ACME middleware,
#comment support in the config loader, and a persistent CA TLS key. Vendoring keeps this branch fully self-contained and reviewable in one place.Scope: the copy is based on
esnet/certificates v0.30.2-patch.2; the actual delta is small and self-contained:acme/api/meta_hooks.go(new)RequestMetaHook+RequestACLHookvariablesacme/api/{handler,order,revoke}.goacme/challenge.goSkipChallengeValidationtoggle (proxy deployments)authority/config/config.go#comment stripping inLoadConfiguration; exportedLoadedFilepathauthority/tls.gotls_key.pemnext toca.json) so restarts reuse the cached upstream certificateca/ca.goSkipChallengeValidationfrom configFor maintainers: if you prefer keeping step-ca patches in
esnet/certificates(the current pattern), these nine files can be contributed there as a follow-up tag instead, happy to split this PR or prepare the module patch separately. The in-tree copy is offered purely to keep this contribution self-contained.Upgrade Notes / Breaking Changes
acme.ExtendedAccount, dns01 client options,challenge.Providersignatures)dashboard/acllive at the top level ofca.json_comment_*fields are no longer needed; use#commentsadmin/kambing, change them via settings or config before exposing the dashboardTesting
go test -race ./externalcas,gitleaks,govulncheck,staticcheckall pass (repo pre-commit hooks)Documentation
README.mdanddocs/content/configuration.mddocument the dashboard, ACL, runtime settings, bounded cache,#comments, and the new config blocks.Notes
On going: TLS-ALPN-01 challenge to have same behaviour such as HTTP-01 challenge.
Dashboard Screenshot