Andrea Cosentino created CAMEL-25368:
----------------------------------------
Summary: camel-spiffe: the documented SpiffeSecurityPolicy example
denies every request
Key: CAMEL-25368
URL: https://issues.apache.org/jira/browse/CAMEL-25368
Project: Camel
Issue Type: Bug
Components: camel-spiffe
Reporter: Andrea Cosentino
Assignee: Andrea Cosentino
Fix For: 4.23.0
The SpiffeSecurityPolicy section added in CAMEL-24735 ships an example that
cannot work, and the surrounding text does not say where the policy is usable
at all. Worth fixing before 4.23.0 ships, since a reader who copies the example
gets a route that denies all traffic and no indication why.
h3. The example never authorizes anything
{code:java}
from("netty-http:https://0.0.0.0:8443?sslContextParameters=#spiffeSsl")
.policy(spiffePolicy)
.to("direct:handleOrder");
{code}
Nothing sets {{clientAuthentication}} on the server parameters. Traced through
main:
* {{SSLContextServerParameters.getSSLEngineConfigurers}} adds its client-auth
configurer only {{if (this.getClientAuthentication() != null)}}, so an unset
value installs no configurer at all - neither {{setNeedClientAuth}} nor
{{setWantClientAuth}} is ever called, leaving the JSSE default of no client
authentication.
* {{SpiffeSSLContextParameters}} does not set it either; it only preserves
whatever the parent's {{serverParameters.clientAuthentication}} says.
* With no client certificate requested, {{SSLSession.getPeerCertificates()}}
throws {{SSLPeerUnverifiedException}}, which {{SpiffePeerIdentity}} catches and
turns into {{null}}.
* {{null}} is the fail-closed path, so the policy denies - every request, for
every peer.
The docs must show {{clientAuthentication=REQUIRE}} on the server
{{SSLContextServerParameters}}, and say that the server has to use
{{SpiffeSSLContextParameters}} rather than a plain truststore: a plain
truststore accepts any certificate chaining to the trust bundle, so the policy
would be authorizing an identity nobody constrained.
h3. The scope of the policy is not stated
The identity comes from an {{SSLSession}} on the message, and
{{NettyEndpoint.updateMessageHeader}} is the only place in the codebase that
puts one there (gated on {{configuration.isSsl()}}). So the policy works with
camel-netty and camel-netty-http and silently denies everything on
platform-http, jetty, undertow and servlet. The servlet certificate fallback
was dropped during the review of #27385, so there is no longer any non-netty
path. That belongs in the docs rather than being discovered in production.
h3. Negative tests
The 13 tests that shipped cover the allow paths and the plainly-absent-identity
denials. The denials that would actually be attacked are untested:
* a String-valued {{CamelNettySSLSession}} header, i.e. a sender trying to pass
an identity as text rather than an {{SSLSession}};
* near-miss SPIFFE IDs against the allow-list -
{{spiffe://example.org.evil/frontend}} and {{spiffe://example.org/frontend/x}}
against an accepted {{spiffe://example.org/frontend}};
* a malformed {{spiffe://}} URI SAN;
* a leaf certificate that is not an X509Certificate.
No behaviour change is proposed for the code itself - the first of those is
also the answer to the review question of whether {{sslSessionHeader}} should
be forced to start with {{Camel}}: it need not, because an {{SSLSession}} is a
Java object and a String header is already rejected. The tests pin that rather
than relying on the argument.
Follow-up to CAMEL-24735.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)