Authenticate every request by client certificate - #457
Open
silug wants to merge 2 commits into
Open
Conversation
OpenVoxDB accepted any request that reached it whenever [puppetdb] certificate-allowlist was unset, because wrap-cert-authn returned the handler unwrapped in that case. The HTTPS listener is configured with client-auth = want rather than need, so a client presenting no certificate at all could read the whole database, submit commands for any certname, and delete node data. The allowlist was also bypassed for cleartext requests, since kitchensink's cn-whitelist->authorizer authorizes any request whose scheme is :http. An operator who configured an allowlist got no enforcement on the cleartext port, and no indication of that. Authentication is now always applied. A request must present a certificate signed by OpenVoxDB's CA, and where an allowlist is configured its CN must appear there, with the allowlist checked locally rather than through the scheme-sensitive kitchensink helper. A cleartext connection cannot present a certificate, so cleartext requests are exempt only when they come from a loopback address, which is what the shipped configuration expects: [jetty] host defaults to localhost and the port exists for local administration and the performance dashboard. Operators who terminate authentication elsewhere, such as behind a reverse proxy on another host, can set the new [puppetdb] allow-unauthenticated-cleartext to exempt the port entirely; that logs a warning at startup. This is a breaking change for deployments that rely on unauthenticated access: anonymous HTTPS clients and remote cleartext clients are now rejected with a 403 rather than served. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steven Pritchard <steven.pritchard@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR closes authentication bypasses by ensuring certificate-based authentication is enforced consistently, including when the certificate allowlist is unset and for requests arriving over cleartext HTTP.
Changes:
- Reworks
wrap-cert-authnto always require a client certificate (and optionally enforce a CN allowlist), independent of request scheme. - Adds a loopback-only exemption for cleartext HTTP plus a new
allow-unauthenticated-cleartextconfig override (with startup warning). - Updates tests and documentation to reflect the new authentication behavior and configuration.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/puppetlabs/puppetdb/middleware_test.clj | Expands middleware tests to cover allowlist behavior, unauthenticated HTTPS rejection, and cleartext exemptions. |
| src/puppetlabs/puppetdb/pdb_routing.clj | Wires new allow-unauthenticated-cleartext setting into middleware and logs a warning when enabled. |
| src/puppetlabs/puppetdb/middleware.clj | Implements always-on cert authentication, allowlist enforcement independent of scheme, and loopback logic for cleartext. |
| src/puppetlabs/puppetdb/config.clj | Introduces allow-unauthenticated-cleartext configuration key and schema output type. |
| documentation/maintain_and_tune.markdown | Updates dashboard access guidance to account for loopback-only cleartext behavior and new config option. |
| documentation/configure.markdown | Documents allowlist behavior and adds docs for allow-unauthenticated-cleartext. |
| config.sample.ini | Adds the new allow-unauthenticated-cleartext option to the sample config. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Make reject-unauthenticated-request and loopback-request? private, as both are only used within middleware.clj, and cover the defaulting and boolean coercion of allow-unauthenticated-cleartext in config-test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steven Pritchard <steven.pritchard@gmail.com>
silug
marked this pull request as ready for review
August 4, 2026 19:59
austb
approved these changes
Aug 6, 2026
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.
Pull Request (PR) description
OpenVoxDB accepted any request that reached it whenever [puppetdb] certificate-allowlist was unset, because wrap-cert-authn returned the handler unwrapped in that case. The HTTPS listener is configured with client-auth = want rather than need, so a client presenting no certificate at all could read the whole database, submit commands for any certname, and delete node data.
The allowlist was also bypassed for cleartext requests, since kitchensink's cn-whitelist->authorizer authorizes any request whose scheme is :http. An operator who configured an allowlist got no enforcement on the cleartext port, and no indication of that.
Authentication is now always applied. A request must present a certificate signed by OpenVoxDB's CA, and where an allowlist is configured its CN must appear there, with the allowlist checked locally rather than through the scheme-sensitive kitchensink helper.
A cleartext connection cannot present a certificate, so cleartext requests are exempt only when they come from a loopback address, which is what the shipped configuration expects: [jetty] host defaults to localhost and the port exists for local administration and the performance dashboard. Operators who terminate authentication elsewhere, such as behind a reverse proxy on another host, can set the new [puppetdb] allow-unauthenticated-cleartext to exempt the port entirely; that logs a warning at startup.
This is a breaking change for deployments that rely on unauthenticated access: anonymous HTTPS clients and remote cleartext clients are now rejected with a 403 rather than served.
Generated by Claude Code
This Pull Request (PR) fixes the following issues
N/A