oscerd commented on code in PR #25621:
URL: https://github.com/apache/camel/pull/25621#discussion_r3870811330


##########
components/camel-spiffe/src/main/java/org/apache/camel/component/spiffe/SpiffeProducer.java:
##########
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.spiffe;
+
+import java.util.Arrays;
+
+import io.spiffe.svid.jwtsvid.JwtSvid;
+import io.spiffe.svid.x509svid.X509Svid;
+import io.spiffe.workloadapi.WorkloadApiClient;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+
+public class SpiffeProducer extends DefaultProducer {
+
+    public SpiffeProducer(final SpiffeEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    public SpiffeEndpoint getEndpoint() {
+        return (SpiffeEndpoint) super.getEndpoint();
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        final WorkloadApiClient client = getEndpoint().getWorkloadApiClient();
+        switch (determineOperation(exchange)) {
+            case fetchX509Svid -> fetchX509Svid(client, exchange);
+            case fetchJwtSvid -> fetchJwtSvid(client, exchange);
+            case validateJwtSvid -> validateJwtSvid(client, exchange);
+            default -> throw new IllegalArgumentException("Unsupported 
operation");
+        }
+    }
+
+    private void fetchX509Svid(WorkloadApiClient client, Exchange exchange) 
throws Exception {
+        X509Svid svid = client.fetchX509Context().getDefaultSvid();
+        Message message = getMessageForResponse(exchange);
+        message.setBody(svid);
+        message.setHeader(SpiffeConstants.SPIFFE_ID, 
svid.getSpiffeId().toString());
+    }
+
+    private void fetchJwtSvid(WorkloadApiClient client, Exchange exchange) 
throws Exception {
+        String[] audiences = resolveAudiences(exchange);
+        JwtSvid svid = audiences.length > 1
+                ? client.fetchJwtSvid(audiences[0], 
Arrays.copyOfRange(audiences, 1, audiences.length))
+                : client.fetchJwtSvid(audiences[0]);
+        Message message = getMessageForResponse(exchange);
+        message.setBody(svid.getToken());
+        message.setHeader(SpiffeConstants.SPIFFE_ID, 
svid.getSpiffeId().toString());
+        message.setHeader(SpiffeConstants.EXPIRY, svid.getExpiry());
+    }
+
+    private void validateJwtSvid(WorkloadApiClient client, Exchange exchange) 
throws Exception {
+        String token = exchange.getIn().getHeader(SpiffeConstants.TOKEN, 
String.class);
+        if (ObjectHelper.isEmpty(token)) {
+            token = exchange.getIn().getBody(String.class);
+        }
+        if (ObjectHelper.isEmpty(token)) {
+            throw new IllegalArgumentException(
+                    "A JWT-SVID token is required for validateJwtSvid (set the 
CamelSpiffeToken header or the body)");
+        }
+        String[] audiences = resolveAudiences(exchange);
+        JwtSvid svid = client.validateJwtSvid(token, audiences[0]);
+        Message message = getMessageForResponse(exchange);
+        message.setBody(svid);

Review Comment:
   Documented in 7bb3361. The `audience` option description now states that 
validateJwtSvid validates against a single audience — when several 
comma-separated audiences are given only the first is used for validation, 
while fetchJwtSvid requests all of them. I chose documentation over a runtime 
warning to avoid per-message log noise.



##########
components/camel-spiffe/src/main/java/org/apache/camel/component/spiffe/SpiffeProducer.java:
##########
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.spiffe;
+
+import java.util.Arrays;
+
+import io.spiffe.svid.jwtsvid.JwtSvid;
+import io.spiffe.svid.x509svid.X509Svid;
+import io.spiffe.workloadapi.WorkloadApiClient;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+
+public class SpiffeProducer extends DefaultProducer {
+
+    public SpiffeProducer(final SpiffeEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    public SpiffeEndpoint getEndpoint() {
+        return (SpiffeEndpoint) super.getEndpoint();
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        final WorkloadApiClient client = getEndpoint().getWorkloadApiClient();
+        switch (determineOperation(exchange)) {
+            case fetchX509Svid -> fetchX509Svid(client, exchange);
+            case fetchJwtSvid -> fetchJwtSvid(client, exchange);
+            case validateJwtSvid -> validateJwtSvid(client, exchange);
+            default -> throw new IllegalArgumentException("Unsupported 
operation");
+        }
+    }
+
+    private void fetchX509Svid(WorkloadApiClient client, Exchange exchange) 
throws Exception {
+        X509Svid svid = client.fetchX509Context().getDefaultSvid();
+        Message message = getMessageForResponse(exchange);
+        message.setBody(svid);
+        message.setHeader(SpiffeConstants.SPIFFE_ID, 
svid.getSpiffeId().toString());
+    }
+
+    private void fetchJwtSvid(WorkloadApiClient client, Exchange exchange) 
throws Exception {
+        String[] audiences = resolveAudiences(exchange);
+        JwtSvid svid = audiences.length > 1
+                ? client.fetchJwtSvid(audiences[0], 
Arrays.copyOfRange(audiences, 1, audiences.length))
+                : client.fetchJwtSvid(audiences[0]);
+        Message message = getMessageForResponse(exchange);
+        message.setBody(svid.getToken());
+        message.setHeader(SpiffeConstants.SPIFFE_ID, 
svid.getSpiffeId().toString());
+        message.setHeader(SpiffeConstants.EXPIRY, svid.getExpiry());
+    }
+
+    private void validateJwtSvid(WorkloadApiClient client, Exchange exchange) 
throws Exception {
+        String token = exchange.getIn().getHeader(SpiffeConstants.TOKEN, 
String.class);
+        if (ObjectHelper.isEmpty(token)) {
+            token = exchange.getIn().getBody(String.class);
+        }
+        if (ObjectHelper.isEmpty(token)) {
+            throw new IllegalArgumentException(
+                    "A JWT-SVID token is required for validateJwtSvid (set the 
CamelSpiffeToken header or the body)");
+        }
+        String[] audiences = resolveAudiences(exchange);
+        JwtSvid svid = client.validateJwtSvid(token, audiences[0]);
+        Message message = getMessageForResponse(exchange);
+        message.setBody(svid);
+        message.setHeader(SpiffeConstants.SPIFFE_ID, 
svid.getSpiffeId().toString());
+    }
+
+    private SpiffeOperation determineOperation(Exchange exchange) {
+        SpiffeOperation operation
+                = exchange.getIn().getHeader(SpiffeConstants.OPERATION, 
SpiffeOperation.class);
+        return operation != null ? operation : 
getEndpoint().getConfiguration().getOperation();
+    }
+
+    private String[] resolveAudiences(Exchange exchange) {
+        String audience = exchange.getIn().getHeader(SpiffeConstants.AUDIENCE, 
String.class);
+        if (ObjectHelper.isEmpty(audience)) {
+            audience = getEndpoint().getConfiguration().getAudience();
+        }
+        if (ObjectHelper.isEmpty(audience)) {
+            throw new IllegalArgumentException(
+                    "At least one audience is required (set the audience 
option or the CamelSpiffeAudience header)");
+        }

Review Comment:
   Applied in 7bb3361. `resolveAudiences` now trims and filters out blank 
entries (`Arrays.stream(...).map(String::trim).filter(s -> !s.isEmpty())`) and 
throws if nothing non-blank remains, so an input like `aud1,,aud2` no longer 
yields an empty audience. I also extended the multi-audience test to include a 
blank element (`aud1, , aud2, aud3`).



##########
components/camel-spiffe/src/main/java/org/apache/camel/component/spiffe/SpiffeConfiguration.java:
##########
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.spiffe;
+
+import io.spiffe.workloadapi.WorkloadApiClient;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+
+@UriParams
+public class SpiffeConfiguration implements Cloneable {
+
+    @UriParam(defaultValue = "fetchX509Svid")
+    private SpiffeOperation operation = SpiffeOperation.fetchX509Svid;
+
+    @UriParam(label = "security")
+    private String spiffeSocketPath;
+
+    @UriParam
+    private String audience;
+
+    @UriParam(label = "advanced", description = "An existing WorkloadApiClient 
to use. When set, the component does not"
+                                                + " create or close its own 
client and spiffeSocketPath is ignored.")
+    private WorkloadApiClient workloadApiClient;
+
+    /**
+     * The operation to perform on the SPIFFE Workload API.
+     */

Review Comment:
   Added in 7bb3361 — via a separate `@Metadata(autowired = true)` rather than 
on `@UriParam` (that annotation has no `autowired` attribute; `@Metadata` is 
where the AWS/Azure SDK-client options carry it). The client is now autowired 
from the registry and the generated `spiffe.json` reflects `"autowired": true`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to