Summary
listen_mode's plaintext variants appear to be unused, while being documented
as supported. The net effect is that our configuration docs advertise a way to
serve the control-plane API in cleartext.
Evidence
crates/api-core/src/cfg/file.rs defines
ListenMode { PlaintextHttp1, PlaintextHttp2, Tls }, defaulting to Tls.
- Nothing in
deploy/, helm/, or the test suite selects a plaintext variant.
crates/api-core/src/test_support/default_config.rs sets Tls.
- Both variants are documented as supported, in
crates/api-core/src/cfg/README.md and
book/src/configuration/configurability.md.
Why this is more than tidiness
On a plaintext listener the accept path attaches
ConnectionAttributes { peer_certificates: vec![], .. }, so no client
certificate ever reaches the authn middleware. Machine mTLS therefore
authenticates nobody.
Combined with the [node_auth] section, that makes a validation guarantee
weaker than it reads. NodeAuthConfig::validate refuses
enabled = false + mtls_enabled = false on the grounds that it would leave
nodes with no way to authenticate — but on a plaintext listener,
mtls_enabled = true satisfies the check while authenticating nobody. Bearer
tokens are refused over plaintext explicitly at startup; machine mTLS has no
equivalent guard, because adding one would effectively make TLS mandatory
(mtls_enabled defaults to true) and break local plaintext development.
That asymmetry is currently documented rather than enforced, in
cfg/README.md and docs/design/machine-identity/node-auth-jwt.md.
Options
- Remove the plaintext variants and the
listen_mode field, making TLS
unconditional. Breaking for anyone who sets it, and the book would need
updating in step. Would also let the listen_mode check drop out of the
node-auth startup preflight, since it would become structurally impossible
to fail.
- Keep them, document the supported use case (TLS terminated by a sidecar
or service mesh would be the obvious one), and emit a startup warning when a
plaintext mode is selected so it is at least visible in logs.
Deciding between these needs someone who knows whether plaintext has a real
deployment use. Nothing in-tree indicates one, but absence of evidence in the
repo is not conclusive.
Note
#[serde(other)] on the Tls variant means an unrecognized listen_mode
value silently becomes Tls, so a typo cannot accidentally select plaintext.
That part fails safe.
Provenance
Noticed while reviewing #4718 (node-auth bearer JWTs), which added the first
code that refuses a plaintext listener — and only for the bearer half.
Summary
listen_mode's plaintext variants appear to be unused, while being documentedas supported. The net effect is that our configuration docs advertise a way to
serve the control-plane API in cleartext.
Evidence
crates/api-core/src/cfg/file.rsdefinesListenMode { PlaintextHttp1, PlaintextHttp2, Tls }, defaulting toTls.deploy/,helm/, or the test suite selects a plaintext variant.crates/api-core/src/test_support/default_config.rssetsTls.crates/api-core/src/cfg/README.mdandbook/src/configuration/configurability.md.Why this is more than tidiness
On a plaintext listener the accept path attaches
ConnectionAttributes { peer_certificates: vec![], .. }, so no clientcertificate ever reaches the authn middleware. Machine mTLS therefore
authenticates nobody.
Combined with the
[node_auth]section, that makes a validation guaranteeweaker than it reads.
NodeAuthConfig::validaterefusesenabled = false+mtls_enabled = falseon the grounds that it would leavenodes with no way to authenticate — but on a plaintext listener,
mtls_enabled = truesatisfies the check while authenticating nobody. Bearertokens are refused over plaintext explicitly at startup; machine mTLS has no
equivalent guard, because adding one would effectively make TLS mandatory
(
mtls_enableddefaults totrue) and break local plaintext development.That asymmetry is currently documented rather than enforced, in
cfg/README.mdanddocs/design/machine-identity/node-auth-jwt.md.Options
listen_modefield, making TLSunconditional. Breaking for anyone who sets it, and the book would need
updating in step. Would also let the
listen_modecheck drop out of thenode-auth startup preflight, since it would become structurally impossible
to fail.
or service mesh would be the obvious one), and emit a startup warning when a
plaintext mode is selected so it is at least visible in logs.
Deciding between these needs someone who knows whether plaintext has a real
deployment use. Nothing in-tree indicates one, but absence of evidence in the
repo is not conclusive.
Note
#[serde(other)]on theTlsvariant means an unrecognizedlisten_modevalue silently becomes
Tls, so a typo cannot accidentally select plaintext.That part fails safe.
Provenance
Noticed while reviewing #4718 (node-auth bearer JWTs), which added the first
code that refuses a plaintext listener — and only for the bearer half.