SPIFFE
Since Camel 4.23
Only producer is supported
The SPIFFE component integrates with the SPIFFE (Secure Production Identity Framework For Everyone) Workload API to provide cryptographic workload identity to Camel routes. It talks to a local SPIFFE Workload API endpoint — for example the one exposed by a SPIRE agent — to fetch and validate SVIDs (SPIFFE Verifiable Identity Documents):
-
X.509-SVID: an X.509 certificate whose SPIFFE ID is encoded as a URI SAN, used for mutual TLS.
-
JWT-SVID: a JWT whose subject is the SPIFFE ID, used as a bearer token for workload-to-workload authentication.
Maven users will need to add the following dependency to their pom.xml.
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spiffe</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency> Configuring Options
Camel components are configured on two separate levels:
-
component level
-
endpoint level
Configuring Component Options
At the component level, you set general and shared configurations that are, then, inherited by the endpoints. It is the highest configuration level.
For example, a component may have security settings, credentials for authentication, urls for network connection and so forth.
Some components only have a few options, and others may have many. Because components typically have pre-configured defaults that are commonly used, then you may often only need to configure a few options on a component; or none at all.
You can configure components using:
-
the Component DSL.
-
in a configuration file (
application.properties,*.yamlfiles, etc). -
directly in the Java code.
Configuring Endpoint Options
You usually spend more time setting up endpoints because they have many options. These options help you customize what you want the endpoint to do. The options are also categorized into whether the endpoint is used as a consumer (from), as a producer (to), or both.
Configuring endpoints is most often done directly in the endpoint URI as path and query parameters. You can also use the Endpoint DSL and DataFormat DSL as a type safe way of configuring endpoints and data formats in Java.
A good practice when configuring options is to use Property Placeholders.
Property placeholders provide a few benefits:
-
They help prevent using hardcoded urls, port numbers, sensitive information, and other settings.
-
They allow externalizing the configuration from the code.
-
They help the code to become more flexible and reusable.
The following two sections list all the options, firstly for the component followed by the endpoint.
Component Options
The SPIFFE component supports the following options which are listed below.
| Name | Description | Default | Type |
|---|---|---|---|
The comma-separated audience(s) to request for a JWT-SVID (fetchJwtSvid) or to validate against (validateJwtSvid). fetchJwtSvid requests all of them and can be overridden per-message with the CamelSpiffeAudience header; validateJwtSvid ignores that header and uses this configuration only, accepting the token if it matches any of the configured audiences, trying each in turn. | String | ||
The component configuration. | SpiffeConfiguration | ||
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | boolean | |
The operation to perform on the SPIFFE Workload API. Enum values:
| fetchX509Svid | SpiffeOperation | |
Whether validateJwtSvid leaves the application body untouched and publishes the verified identity through the CamelSpiffeJwtIdentity exchange property. In this mode the token must be in CamelSpiffeToken or an Authorization Bearer header: the body is never read as a token. The default returns the JwtSvid in the body as before. | false | boolean | |
Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. | true | boolean | |
Autowired An existing WorkloadApiClient to use. When set, the component does not create or close its own client and spiffeSocketPath is ignored. | WorkloadApiClient | ||
Whether the CamelSpiffeOperation header may override the configured operation. Disabled by default: the operation decides whether this endpoint validates a token or mints one, so a message that can set it can turn a validator into an endpoint that hands out this workload’s own JWT-SVID. Enable it only on routes whose input is trusted. | false | boolean | |
The address of the SPIFFE Workload API endpoint (for example unix:///tmp/agent.sock or tcp://127.0.0.1:8082). When not set, the SPIFFE_ENDPOINT_SOCKET environment variable is used. | String | ||
What the fetchX509Svid operation returns in the message body. Defaults to chain: the X.509 certificate chain without the private key, so a route never handles key material unless it asks for it. Choose svid to get the whole X509Svid including the private key (needed for programmatic mTLS), or id to leave the body untouched. The SPIFFE ID and expiry are exposed through the CamelSpiffeSpiffeId and CamelSpiffeExpiry headers in every case. Enum values:
| chain | SpiffeX509Response |
Endpoint Options
The SPIFFE endpoint is configured using URI syntax:
spiffe:label
With the following path and query parameters:
Query Parameters
| Name | Description | Default | Type |
|---|---|---|---|
The comma-separated audience(s) to request for a JWT-SVID (fetchJwtSvid) or to validate against (validateJwtSvid). fetchJwtSvid requests all of them and can be overridden per-message with the CamelSpiffeAudience header; validateJwtSvid ignores that header and uses this configuration only, accepting the token if it matches any of the configured audiences, trying each in turn. | String | ||
The operation to perform on the SPIFFE Workload API. Enum values:
| fetchX509Svid | SpiffeOperation | |
Whether validateJwtSvid leaves the application body untouched and publishes the verified identity through the CamelSpiffeJwtIdentity exchange property. In this mode the token must be in CamelSpiffeToken or an Authorization Bearer header: the body is never read as a token. The default returns the JwtSvid in the body as before. | false | boolean | |
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | boolean | |
Autowired An existing WorkloadApiClient to use. When set, the component does not create or close its own client and spiffeSocketPath is ignored. | WorkloadApiClient | ||
Whether the CamelSpiffeOperation header may override the configured operation. Disabled by default: the operation decides whether this endpoint validates a token or mints one, so a message that can set it can turn a validator into an endpoint that hands out this workload’s own JWT-SVID. Enable it only on routes whose input is trusted. | false | boolean | |
The address of the SPIFFE Workload API endpoint (for example unix:///tmp/agent.sock or tcp://127.0.0.1:8082). When not set, the SPIFFE_ENDPOINT_SOCKET environment variable is used. | String | ||
What the fetchX509Svid operation returns in the message body. Defaults to chain: the X.509 certificate chain without the private key, so a route never handles key material unless it asks for it. Choose svid to get the whole X509Svid including the private key (needed for programmatic mTLS), or id to leave the body untouched. The SPIFFE ID and expiry are exposed through the CamelSpiffeSpiffeId and CamelSpiffeExpiry headers in every case. Enum values:
| chain | SpiffeX509Response |
Message Headers
The SPIFFE component supports the following message header(s), which is/are listed below:
| Name | Description | Default | Type |
|---|---|---|---|
CamelSpiffeOperation (producer) Constant: | Overrides the operation to be used by the producer. Ignored unless the endpoint sets allowOperationHeader=true, because the operation decides whether the endpoint validates a token or mints one. | SpiffeOperation or String | |
CamelSpiffeAudience (producer) Constant: | The comma-separated audience(s) for the fetchJwtSvid operation. Ignored by validateJwtSvid, which always validates against the configured audience: there the audience is the check that binds the token to this workload, not a parameter. | String | |
| Constant: | The JWT-SVID token to validate, for the validateJwtSvid operation. | String | |
CamelSpiffeSpiffeId (producer) Constant: | The SPIFFE ID of the returned SVID. | String | |
| Constant: | The expiry of the returned SVID: the token expiry for fetchJwtSvid or validateJwtSvid, or the leaf certificate’s notAfter for fetchX509Svid. | Date |
Message Body
The message body at each side of the SPIFFE component: Consumer is the body of the messages the consumer creates, Consumer reply the bodies a consumer that answers its caller can reply with, Producer input the bodies the producer can send or write, and Producer output the body after the producer.
| Side | Body | Description |
|---|---|---|
Producer input |
| Only validateJwtSvid reads the body: the token as text, when neither the CamelSpiffeToken header nor an Authorization: Bearer header carries it. The fetch operations ignore the body. |
Producer output |
| fetchX509Svid: the certificate chain without the private key; the X509Svid with its private key with x509Response=svid, or the body kept with x509Response=id. fetchJwtSvid: the token. validateJwtSvid: the validated JwtSvid. The SPIFFE ID is in the CamelSpiffeSpiffeId header.
Not known when |
The bodies are the ones with the default options. A side that is not listed is not known, and tooling does not guess it. The carriers, the sides and the tools that use them are described in Message Body Types.
Workload API endpoint
The address of the SPIFFE Workload API is taken from the spiffeSocketPath option, or, when that is not set, from the standard SPIFFE_ENDPOINT_SOCKET environment variable — for example unix:///tmp/spire-agent/public/api.sock. For advanced scenarios an already-configured io.spiffe.workloadapi.WorkloadApiClient can be supplied through the workloadApiClient option; in that case the component neither creates nor closes the client.
Operations
The component supports the following producer operations:
-
fetchX509Svid— fetches the default X.509-SVID from the Workload API. By default (x509Response=chain) the message body is set to the certificate chain only (aList<java.security.cert.X509Certificate>, without the private key), so a route never handles key material unless it asks for it. Setx509Response=svidto get the wholeio.spiffe.svid.x509svid.X509Svidincluding the private key (needed for programmatic mTLS), orx509Response=idto leave the body untouched. In every case theCamelSpiffeSpiffeIdandCamelSpiffeExpiry(the leaf certificate’s expiry) headers carry the identity. -
fetchJwtSvid— fetches a JWT-SVID for the configuredaudience(or theCamelSpiffeAudienceheader). The message body is set to the JWT token string, with theCamelSpiffeSpiffeIdandCamelSpiffeExpiryheaders. -
validateJwtSvid— validates a JWT-SVID against theaudience. The token is taken from the first of: theCamelSpiffeTokenheader, anAuthorization: Bearer <token>header (the scheme matched case-insensitively), or the message body. TheAuthorizationheader is tried before the body so a request payload on aPOST/PUTis not mistaken for the token; this lets aplatform-httproute validate an incoming bearer token without a bean to strip the scheme. On success the message body is set to the validatedio.spiffe.svid.jwtsvid.JwtSvid, so a route that needs the original request payload afterwards must keep a copy before validating (or validate a bodiless request). When several audiences are configured the token is accepted if it matches any of them — the Workload API validates one audience at a time, so each is tried in turn.
| The |
Example
Fetch a JWT-SVID for an outbound call:
from("direct:start")
.to("spiffe:identity?operation=fetchJwtSvid&audience=spiffe://example.org/backend")
.setHeader("Authorization", simple("Bearer ${body}"))
.to("http://backend.example.org/api"); Validate an incoming bearer token on a platform-http route, without a bean to strip the scheme:
- route:
from:
uri: "platform-http:/api"
steps:
# the Authorization: Bearer <token> header is picked up automatically; validation replaces the body with the
# JwtSvid, so this fits a request whose payload is not needed afterwards
- to:
uri: "spiffe:auth?operation=validateJwtSvid&audience=spiffe://example.org/api"
# the token is a credential; drop it before the exchange goes further
- removeHeaders:
pattern: "Authorization"
- to:
uri: "direct:handleRequest" A missing token fails with IllegalArgumentException; a rejected one (invalid, expired, or a wrong audience) fails with io.spiffe.exception.JwtSvidException. Catch both — onException(io.spiffe.exception.JwtSvidException.class, IllegalArgumentException.class) — to answer 401.
Preserve an application body during JWT validation
Set preserveBody=true on validateJwtSvid to validate a request without replacing or reading its body. In this mode supply the token through CamelSpiffeToken or Authorization: Bearer; there is no body-token fallback, including when the header is missing. The default remains preserveBody=false, which returns the SDK JwtSvid in the body.
After validation the CamelSpiffeJwtIdentity exchange property contains a SpiffeJwtIdentity with getters for spiffeId, expiry (Instant), audience and claims. It contains no bearer token. Claims are copied into unmodifiable maps/lists and omitted from toString, but can still contain sensitive application data: select only the fields a downstream authorization policy needs. The identity property and identity/expiry output headers are cleared before each validation, including one that fails.
-
Java
-
XML
-
YAML
from("platform-http:/orders")
.to("spiffe:auth?operation=validateJwtSvid&audience=spiffe://example.org/orders&preserveBody=true")
.removeHeaders("Authorization")
.setProperty("subject", simple("${exchangeProperty.CamelSpiffeJwtIdentity.spiffeId}"))
.to("direct:handleOrder"); <route>
<from uri="platform-http:/orders"/>
<to uri="spiffe:auth?operation=validateJwtSvid&audience=spiffe://example.org/orders&preserveBody=true"/>
<removeHeaders pattern="Authorization"/>
<setProperty name="subject"><simple>${exchangeProperty.CamelSpiffeJwtIdentity.spiffeId}</simple></setProperty>
<to uri="direct:handleOrder"/>
</route> - route:
from:
uri: platform-http:/orders
steps:
- to:
uri: "spiffe:auth?operation=validateJwtSvid&audience=spiffe://example.org/orders&preserveBody=true"
- removeHeaders:
pattern: Authorization
- setProperty:
name: subject
simple: "${exchangeProperty.CamelSpiffeJwtIdentity.spiffeId}"
- to:
uri: direct:handleOrder Protect a route segment with a JWT-SVID policy
SpiffeJwtSecurityPolicy combines audience validation with an explicit identity rule, preserves the application body, and throws CamelAuthorizationException before the guarded processor runs for missing, rejected or unauthorized tokens. Set audience and exactly one of acceptedSpiffeIds or acceptAnySpiffeId=true. Audience and identity rules come from policy configuration; message headers cannot override them. The policy reads tokens from the same two headers as body-preserving producer validation and never from the body.
Each guarded processor owns an endpoint-managed Workload API client, released when its route stops and recreated on restart. The policy starts from the configuration of the spiffe component, so the camel.component.spiffe.* settings and a client autowired on the component apply to it; its own workloadApiClient and spiffeSocketPath options take precedence, and SPIFFE_ENDPOINT_SOCKET is used when neither names a client or a socket. An injected workloadApiClient remains owned by its supplier and is never closed by the policy.
-
Java
-
XML
-
YAML
SpiffeJwtSecurityPolicy jwtPolicy = new SpiffeJwtSecurityPolicy();
jwtPolicy.setAudience("spiffe://example.org/orders");
jwtPolicy.setAcceptedSpiffeIds("spiffe://example.org/frontend");
getContext().getRegistry().bind("jwtPolicy", jwtPolicy);
from("platform-http:/orders")
.policy(jwtPolicy)
.removeHeaders("Authorization")
.to("direct:handleOrder"); <bean id="jwtPolicy" class="org.apache.camel.component.spiffe.SpiffeJwtSecurityPolicy">
<property name="audience" value="spiffe://example.org/orders"/>
<property name="acceptedSpiffeIds" value="spiffe://example.org/frontend"/>
</bean>
<route>
<from uri="platform-http:/orders"/>
<policy ref="jwtPolicy">
<removeHeaders pattern="Authorization"/>
<to uri="direct:handleOrder"/>
</policy>
</route> - beans:
- name: jwtPolicy
type: org.apache.camel.component.spiffe.SpiffeJwtSecurityPolicy
properties:
audience: spiffe://example.org/orders
acceptedSpiffeIds: spiffe://example.org/frontend
- route:
from:
uri: platform-http:/orders
steps:
- policy:
ref: jwtPolicy
steps:
- removeHeaders:
pattern: Authorization
- to:
uri: direct:handleOrder The successful policy publishes the same token-free CamelSpiffeJwtIdentity property, and nothing else: unlike the producer, it sets no CamelSpiffeSpiffeId or CamelSpiffeExpiry header, so the identity is a value the route established, which a sender cannot put on the message, and it does not travel to outbound producers. Check the property, not a header, further down the route. Extract verified fields into exchange properties to compose with OPA or OpenFGA; for example, copy its spiffeId into subject, use includeProperties=subject with OPA, or a configured OpenFGA user expression based on that property. Choosing acceptAnySpiffeId asserts that audience validation is sufficient at this step and leaves finer authorization to the downstream policy. Always remove credential headers before forwarding requests to an unrelated destination.
Mutual TLS with SPIFFE (SSLContextParameters)
For X.509-based zero-trust mTLS, the component provides org.apache.camel.component.spiffe.SpiffeSSLContextParameters, an SSLContextParameters whose SSLContext is backed by the SPIFFE Workload API. The X.509-SVID and trust bundles are fetched live and rotated automatically, so any Camel component that accepts an sslContextParameters reference (camel-http, camel-netty-http, camel-jetty, camel-vertx-http, …) can obtain SPIFFE mTLS.
Peer authentication must be constrained explicitly: set acceptedSpiffeIds to an allow-list of peer SPIFFE IDs, or acceptAnySpiffeId=true to accept any SVID that validates against the trust bundle. The two are mutually exclusive, and setting neither fails closed.
Because it extends SSLContextParameters, the inherited configuration is still honoured: set serverParameters.clientAuthentication (for a server that must require client certificates), cipherSuites and secureSocketProtocols as usual, and the base handshake protocol comes from secureSocketProtocol (default TLSv1.3). The underlying X509Source is created lazily (bounded by initTimeout, default 30s), closed on CamelContext shutdown, and the cached context is invalidated at the same time so a restarted context rebuilds a fresh source.
SpiffeSSLContextParameters also implements AutoCloseable for standalone use. When neither the createSSLContext argument nor the parameters instance supplies a CamelContext, use try-with-resources or call close() explicitly to release the Workload API watcher. Closing invalidates the cached context and is idempotent; a subsequent createSSLContext call creates a new source. Stop using existing SSL contexts and TLS connections before closing their parameters.
-
Java
-
YAML
SpiffeSSLContextParameters ssl = new SpiffeSSLContextParameters();
// ssl.setSpiffeSocketPath("unix:///tmp/spire-agent/public/api.sock"); // or SPIFFE_ENDPOINT_SOCKET
ssl.setAcceptedSpiffeIds("spiffe://example.org/backend");
getCamelContext().getRegistry().bind("spiffeSsl", ssl);
from("direct:start")
.to("https://backend.example.org/api?sslContextParameters=#spiffeSsl"); - beans:
- name: spiffeSsl
type: org.apache.camel.component.spiffe.SpiffeSSLContextParameters
properties:
# spiffeSocketPath: unix:///tmp/spire-agent/public/api.sock # or SPIFFE_ENDPOINT_SOCKET
acceptedSpiffeIds: spiffe://example.org/backend
- route:
from:
uri: direct:start
steps:
- to:
uri: https://backend.example.org/api
parameters:
sslContextParameters: "#spiffeSsl" Authorizing a route on the peer SPIFFE ID (SpiffeSecurityPolicy)
SpiffeSSLContextParameters decides which peers may connect; org.apache.camel.component.spiffe.SpiffeSecurityPolicy decides what a given peer may reach. It is an AuthorizationPolicy - the SPIFFE sibling of ShiroSecurityPolicy, KeycloakSecurityPolicy and OpaSecurityPolicy - that wraps a route segment and authorizes it on the caller’s verified SPIFFE ID:
-
Java
-
YAML
// the server must REQUIRE a client certificate, or the policy has no verified peer to authorize
SpiffeSSLContextParameters serverSsl = new SpiffeSSLContextParameters();
serverSsl.setAcceptedSpiffeIds("spiffe://example.org/frontend");
SSLContextServerParameters serverParameters = new SSLContextServerParameters();
serverParameters.setClientAuthentication(ClientAuthentication.REQUIRE.name());
serverSsl.setServerParameters(serverParameters);
getCamelContext().getRegistry().bind("spiffeSsl", serverSsl);
SpiffeSecurityPolicy spiffePolicy = new SpiffeSecurityPolicy("spiffe://example.org/frontend");
getCamelContext().getRegistry().bind("spiffePolicy", spiffePolicy);
from("netty-http:https://0.0.0.0:8443?sslContextParameters=#spiffeSsl")
.policy(spiffePolicy)
.to("direct:handleOrder"); - beans:
- name: spiffeSsl
type: org.apache.camel.component.spiffe.SpiffeSSLContextParameters
properties:
acceptedSpiffeIds: spiffe://example.org/frontend
# the server must REQUIRE a client certificate, or the policy has no verified peer to authorize
serverParameters:
clientAuthentication: REQUIRE
- name: spiffePolicy
type: org.apache.camel.component.spiffe.SpiffeSecurityPolicy
properties:
acceptedSpiffeIds: spiffe://example.org/frontend
- route:
from:
uri: netty-http:https://0.0.0.0:8443
parameters:
sslContextParameters: "#spiffeSsl"
steps:
- policy:
ref: spiffePolicy
steps:
- to:
uri: direct:handleOrder | A few things about the server side decide whether, and for which peers, this policy can work.
Only camel-netty and camel-netty-http put the |
The peer SPIFFE ID is taken from the verified TLS peer certificate the consumer put on the exchange - the CamelNettySSLSession header for camel-netty-http - and never from a message header a sender could set (see the Security notes below). A peer that is not on the acceptedSpiffeIds allow-list, or that presents no verified SVID at all, is denied with a CamelAuthorizationException, so the route stops and the regular onException machinery applies.
Set exactly one of:
-
acceptedSpiffeIds- a comma-separated allow-list of the peer SPIFFE IDs this segment authorizes; -
acceptAnySpiffeId=true- authorize any peer that presents a verified SVID, leaving the which-peer decision to a downstream policy. It still fails closed when no verified peer certificate is present.
Setting both is rejected and setting neither fails closed, mirroring SpiffeSSLContextParameters.
The policy answers "is the peer who they claim to be"; it is designed to compose with camel-opa ("may they do this") rather than duplicate it. On a successful authorization the verified SPIFFE ID is stored as the CamelSpiffePeerId exchange property, so an OPA policy downstream can forward it to a Rego rule through its includeProperties option:
-
Java
-
YAML
from("netty-http:https://0.0.0.0:8443?sslContextParameters=#spiffeSsl")
.policy(spiffePolicy) // authenticates the peer, sets CamelSpiffePeerId
.policy(opaPolicy) // opaPolicy.setIncludeProperties("CamelSpiffePeerId")
.to("direct:handleOrder"); - beans:
- name: opaPolicy
type: org.apache.camel.component.opa.security.OpaSecurityPolicy
properties:
policyPath: authz/orders/allow
includeProperties: CamelSpiffePeerId
- route:
from:
uri: netty-http:https://0.0.0.0:8443
parameters:
sslContextParameters: "#spiffeSsl"
steps:
# authenticates the peer, and sets the CamelSpiffePeerId exchange property
- policy:
ref: spiffePolicy
steps:
- policy:
ref: opaPolicy
steps:
- to:
uri: direct:handleOrder For a TLS consumer that exposes the SSLSession under a different header name, set sslSessionHeader accordingly. The identity is always read from the verified SSLSession, never from a certificate object placed on a message header - nothing would prove the TLS layer had verified such a certificate.
Security notes
-
The operation comes from the endpoint.
CamelSpiffeOperationis ignored unless the endpoint setsallowOperationHeader=true. The operation decides whether this endpoint validates a token or mints one, so a message able to set it could turn a validator into an endpoint that hands out this workload’s own JWT-SVID. -
A validation always uses the configured audience.
CamelSpiffeAudienceis honoured byfetchJwtSvid, where the audience is a genuine per-message parameter ("mint me a token for X"), and ignored byvalidateJwtSvid, where the audience is the check that binds the token to this workload. Letting a message choose it would allow a JWT-SVID minted for a different service to validate successfully. -
Strip the component’s headers on untrusted ingress. As with any Camel component, a consumer that does not apply a
HeaderFilterStrategyblockingCamel*lets a sender populate the header map. CallremoveHeaders("CamelSpiffe*")before thespiffe:endpoint when the message comes from an untrusted producer. -
Key material reaches the message.
fetchX509Svidplaces anX509Svid- which carries the private key - on the body, andfetchJwtSvidplaces the bearer token. Do not log or trace the body for those operations. -
Constrain the peer.
SpiffeSSLContextParametersrequires either anacceptedSpiffeIdsallow-list oracceptAnySpiffeId=true; it fails closed when neither is given. Prefer the allow-list -acceptAnySpiffeIdaccepts any SVID that chains to the trust bundle, which authenticates the trust domain but not the peer. -
The authorization decision is made on the certificate, not a header.
SpiffeSecurityPolicyreads the peer SPIFFE ID from the verified TLS peer certificate (theCamelNettySSLSessionheader for camel-netty-http), so a sender cannot assert an identity by setting a header - and it requires mutual TLS, failing closed when the peer presented no verified certificate. The verified id it publishes is theCamelSpiffePeerIdexchange property, never a header, so it likewise cannot be injected by an inbound message.