This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 58f3f65dd28d CAMEL-22511: camel-kamelet - Secret options may not be
auto RAW() substituted (#19516)
58f3f65dd28d is described below
commit 58f3f65dd28d9ad4f44576e74f383c994cf834fe
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Oct 10 12:01:46 2025 +0200
CAMEL-22511: camel-kamelet - Secret options may not be auto RAW()
substituted (#19516)
---
.../camel/component/kamelet/KameletComponent.java | 7 +
.../kamelet/KameletGlobalPropertiesTest.java | 6 +-
.../model/RouteTemplateParameterDefinition.java | 1 +
.../ROOT/pages/camel-4x-upgrade-guide-4_14.adoc | 11 +
.../ROOT/pages/camel-4x-upgrade-guide-4_16.adoc | 5 +
dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml | 10 +
.../camel/dsl/yaml/KameletRoutesBuilderLoader.java | 1 -
.../camel/yaml/dsl/kamelet/AwsRawSecretTest.java | 66 ++++++
.../kamelets/my-aws-s3-source.kamelet.yaml | 231 +++++++++++++++++++++
9 files changed, 334 insertions(+), 4 deletions(-)
diff --git
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
index ea7afb027471..241daa024827 100644
---
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
+++
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
@@ -101,6 +101,13 @@ public class KameletComponent extends DefaultComponent {
public KameletComponent() {
}
+ @Override
+ public boolean useRawUri() {
+ // must use raw because sensitive information need to be preserved
when building URIs
+ // as otherwise a kamelet would encode parameters (also sensitive
which leads to wrong passwords)
+ return true;
+ }
+
public void addKameletEip(String key, Processor callback) {
kameletEips.put(key, callback);
}
diff --git
a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletGlobalPropertiesTest.java
b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletGlobalPropertiesTest.java
index 461a936ba281..3a899d04c7f2 100644
---
a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletGlobalPropertiesTest.java
+++
b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletGlobalPropertiesTest.java
@@ -119,14 +119,14 @@ public class KameletGlobalPropertiesTest extends
CamelTestSupport {
@Test
public void urlEncodingIsRespected() {
-
assertThat(context.getEndpoint("kamelet:timer-source?message=Hello+Kamelets&period=1000",
KameletEndpoint.class)
+ assertThat(context.getEndpoint("kamelet:timer-source?message=Hello
Kamelets&period=1000", KameletEndpoint.class)
.getKameletProperties())
.containsEntry("message", "Hello Kamelets");
-
assertThat(context.getEndpoint("kamelet:timer-source?message=Hi%20Kamelets&period=1000",
KameletEndpoint.class)
+ assertThat(context.getEndpoint("kamelet:timer-source?message=Hi
Kamelets&period=1000", KameletEndpoint.class)
.getKameletProperties())
.containsEntry("message", "Hi Kamelets");
assertThat(context
-
.getEndpoint("kamelet:timer-source?message=messaging.knative.dev%2Fv1beta1&period=1000",
KameletEndpoint.class)
+
.getEndpoint("kamelet:timer-source?message=messaging.knative.dev/v1beta1&period=1000",
KameletEndpoint.class)
.getKameletProperties())
.containsEntry("message", "messaging.knative.dev/v1beta1");
}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateParameterDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateParameterDefinition.java
index 854d2b4074ab..942e5ede6cc1 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateParameterDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateParameterDefinition.java
@@ -98,4 +98,5 @@ public class RouteTemplateParameterDefinition {
public void setDescription(String description) {
this.description = description;
}
+
}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
index c330507638b8..cb4a8c345185 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
@@ -11,6 +11,17 @@ Note that manual migration is still required.
See the xref:camel-upgrade-recipes-tool.adoc[documentation] page for details.
====
+== Upgrading from 4.14.1 to 4.14.2
+
+=== camel-kamelet
+
+The kamelet component is now parsing endpoint parameters using _raw mode_ to
ensure when using sensitive parameters
+such as access keys, passwords etc. they are not URI encoded.
+
+== Upgrading from 4.10.0 to 4.10.1
+
+No changes
+
== Upgrading Camel 4.13 to 4.14
=== camel-core
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc
index 1027be035bb9..2a081cefa188 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc
@@ -13,6 +13,11 @@ See the xref:camel-upgrade-recipes-tool.adoc[documentation]
page for details.
== Upgrading Camel 4.15 to 4.16
+=== camel-kamelet
+
+The kamelet component is now parsing endpoint parameters using _raw mode_ to
ensure when using sensitive parameters
+such as access keys, passwords etc. they are not URI encoded.
+
=== camel-infinispan
The `queryBuilder` option on `camel-infinispan` endpoint has been migrated to
no longer use the deprecated query factory
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
b/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
index 57cf8873fdd6..d0db1efe967b 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
@@ -200,6 +200,11 @@
<artifactId>camel-platform-http</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-aws2-s3</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
@@ -243,6 +248,11 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/KameletRoutesBuilderLoader.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/KameletRoutesBuilderLoader.java
index 2c993ccf2272..22baf4968b7d 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/KameletRoutesBuilderLoader.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/KameletRoutesBuilderLoader.java
@@ -78,7 +78,6 @@ public class KameletRoutesBuilderLoader extends
YamlRoutesBuilderLoaderSupport {
rtpd.setName(key);
rtpd.setDefaultValue(asText(def));
rtpd.setRequired(required.contains(key));
-
rtd.getTemplateParameters().add(rtpd);
}
}
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/yaml/dsl/kamelet/AwsRawSecretTest.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/yaml/dsl/kamelet/AwsRawSecretTest.java
new file mode 100644
index 000000000000..357a1eb25c83
--- /dev/null
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/yaml/dsl/kamelet/AwsRawSecretTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.yaml.dsl.kamelet;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.s3.AWS2S3Endpoint;
+import org.apache.camel.impl.engine.DefaultSupervisingRouteController;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class AwsRawSecretTest extends CamelTestSupport {
+
+ private static final String KEY_1 = "my@+id";
+ private static final String KEY_2 = "my%^+|key";
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testAwsRawSecret() throws Exception {
+ context.addRoutes(createRouteBuilder());
+ context.setAutoStartup(false);
+ // cannot startup as ca
+ context.setRouteController(new DefaultSupervisingRouteController());
+ context.start();
+
+ Endpoint e = context.getEndpoints().stream().filter(p -> p instanceof
AWS2S3Endpoint).findFirst().orElse(null);
+ AWS2S3Endpoint a = Assertions.assertInstanceOf(AWS2S3Endpoint.class,
e);
+ Assertions.assertEquals(KEY_1, a.getConfiguration().getAccessKey());
+ Assertions.assertEquals(KEY_2, a.getConfiguration().getSecretKey());
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
context.getPropertiesComponent().addInitialProperty("aws.accessKeyId", KEY_1);
+
context.getPropertiesComponent().addInitialProperty("aws.secretAccessKey",
KEY_2);
+
+
from("kamelet:my-aws-s3-source?accessKey={{aws.accessKeyId}}&bucketNameOrArn=mybucket®ion=eu-south-2&autoCreateBucket=false&cheeseKey={{aws.secretAccessKey}}")
+ .autoStartup(false).routeId("myroute")
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/my-aws-s3-source.kamelet.yaml
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/my-aws-s3-source.kamelet.yaml
new file mode 100644
index 000000000000..da5316d9cfe9
--- /dev/null
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/my-aws-s3-source.kamelet.yaml
@@ -0,0 +1,231 @@
+#
+# 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.
+#
+
+apiVersion: camel.apache.org/v1
+kind: Kamelet
+metadata:
+ name: my-aws-s3-source
+ annotations:
+ camel.apache.org/kamelet.support.level: "Stable"
+ camel.apache.org/catalog.version: "4.15.0-SNAPSHOT"
+ camel.apache.org/kamelet.icon:
"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAyNDguMiAzMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxzdHlsZT4uc3QyOHtmaWxsOiM4YzMxMjN9LnN0Mjl7ZmlsbDojZTA1MjQzfTwvc3R5bGU+PHBhdGggY2xhc3M9InN0MjgiIGQ9Ik0yMCA1Mi4xTDAgNjJ2MTc1LjVsMjAgOS45LjEtLjFWNTIuMmwtLjEtLjEiLz48cGF0aCBjbGFzcz0ic3QyOSIgZD0iTTEyNyAyMjJMMjAgMjQ3LjVWNTIuMUwxMjcgNzd2MTQ1Ii8+PHBhdGggY2xhc3M9InN0MjgiIG
[...]
+ camel.apache.org/provider: "Apache Software Foundation"
+ camel.apache.org/kamelet.group: "AWS S3"
+ camel.apache.org/kamelet.namespace: "AWS"
+ labels:
+ camel.apache.org/kamelet.type: "source"
+spec:
+ definition:
+ title: "My AWS S3 Source"
+ description: Receive data from an Amazon S3 Bucket.
+ required:
+ - bucketNameOrArn
+ - region
+ type: object
+ properties:
+ bucketNameOrArn:
+ title: Bucket Name
+ description: The S3 Bucket name or Amazon Resource Name (ARN).
+ type: string
+ deleteAfterRead:
+ title: Auto-delete Objects
+ description: Specifies to delete objects after consuming them.
+ type: boolean
+ default: true
+ moveAfterRead:
+ title: Move Objects After Delete
+ description: Move objects from S3 bucket to a different bucket after
they have been retrieved.
+ type: boolean
+ default: false
+ destinationBucket:
+ title: Destination Bucket
+ description: Define the destination bucket where an object must be
moved when moveAfterRead is set to true.
+ type: string
+ destinationBucketPrefix:
+ title: Destination Bucket Prefix
+ description: Define the destination bucket prefix to use when an
object must be moved, and moveAfterRead is set to true.
+ type: string
+ destinationBucketSuffix:
+ title: Destination Bucket Suffix
+ description: Define the destination bucket suffix to use when an
object must be moved, and moveAfterRead is set to true.
+ type: string
+ accessKey:
+ title: Access Key
+ description: The access key obtained from AWS.
+ type: string
+ format: password
+ x-descriptors:
+ - urn:camel:group:credentials
+ cheeseKey:
+ title: Secret Key
+ description: The secret key obtained from AWS.
+ type: string
+ format: password
+ x-descriptors:
+ - urn:camel:group:credentials
+ region:
+ title: AWS Region
+ description: The AWS region to access.
+ type: string
+ enum: ["ap-south-1", "eu-south-1", "us-gov-east-1", "me-central-1",
"ca-central-1", "eu-central-1", "us-iso-west-1", "us-west-1", "us-west-2",
"af-south-1", "eu-north-1", "eu-west-3", "eu-west-2", "eu-west-1",
"ap-northeast-3", "ap-northeast-2", "ap-northeast-1", "me-south-1",
"sa-east-1", "ap-east-1", "cn-north-1", "us-gov-west-1", "ap-southeast-1",
"ap-southeast-2", "us-iso-east-1", "ap-southeast-3", "us-east-1", "us-east-2",
"cn-northwest-1", "us-isob-east-1", "aws-global", "a [...]
+ autoCreateBucket:
+ title: Autocreate Bucket
+ description: Specifies to automatically create the S3 bucket.
+ type: boolean
+ default: false
+ prefix:
+ title: Prefix
+ description: The AWS S3 bucket prefix to consider while searching.
+ type: string
+ example: 'folder/'
+ ignoreBody:
+ title: Ignore Body
+ description: If true, the S3 Object body is ignored. Setting this to
true overrides any behavior defined by the `includeBody` option. If false, the
S3 object is put in the body.
+ type: boolean
+ default: false
+ useDefaultCredentialsProvider:
+ title: Default Credentials Provider
+ description: If true, the S3 client loads credentials through a
default credentials provider. If false, it uses the basic authentication method
(access key and secret key).
+ type: boolean
+ default: false
+ useProfileCredentialsProvider:
+ title: Profile Credentials Provider
+ description: Set whether the S3 client should expect to load
credentials through a profile credentials provider.
+ type: boolean
+ default: false
+ useSessionCredentials:
+ title: Session Credentials
+ description: Set whether the S3 client should expect to use Session
Credentials. This is useful in situation in which the user needs to assume a
IAM role for doing operations in S3.
+ type: boolean
+ default: false
+ profileCredentialsName:
+ title: Profile Credentials Name
+ description: If using a profile credentials provider this parameter
sets the profile name.
+ type: string
+ sessionToken:
+ title: Session Token
+ description: Amazon AWS Session Token used when the user needs to
assume a IAM role.
+ type: string
+ format: password
+ x-descriptors:
+ - urn:camel:group:credentials
+ uriEndpointOverride:
+ title: Overwrite Endpoint URI
+ description: The overriding endpoint URI. To use this option, you must
also select the `overrideEndpoint` option.
+ type: string
+ overrideEndpoint:
+ title: Endpoint Overwrite
+ description: Select this option to override the endpoint URI. To use
this option, you must also provide a URI for the `uriEndpointOverride` option.
+ type: boolean
+ default: false
+ forcePathStyle:
+ title: Force Path Style
+ description: Forces path style when accessing AWS S3 buckets.
+ type: boolean
+ default: false
+ delay:
+ title: Delay
+ description: The number of milliseconds before the next poll of the
selected bucket.
+ type: integer
+ default: 500
+ maxMessagesPerPoll:
+ title: Max Messages Per Poll
+ description: Gets the maximum number of messages as a limit to poll at
each polling. Gets the maximum number of messages as a limit to poll at each
polling. The default value is 10. Use 0 or a negative number to set it as
unlimited.
+ type: integer
+ default: 10
+ dataTypes:
+ out:
+ default: binary
+ headers:
+ CamelAwsS3BucketName:
+ title: S3 Bucket Name
+ description: The bucket name which has been used to retrieve objects
+ type: string
+ CamelAwsS3Key:
+ title: S3 Key
+ description: The key under which the retrieved object is stored.
+ type: string
+ CamelAwsS3ContentType:
+ title: Content Type
+ description: The content type of the retrieved object.
+ default: application/octet-stream
+ type: string
+ CamelAwsS3ETag:
+ title: ETag Value
+ description: The hex encoded 128-bit MD5 digest of the associated
object according to RFC 1864.
+ type: string
+ types:
+ binary:
+ format: "application-octet-stream"
+ description: Default binary representation of the S3 object
retrieved from the bucket.
+ mediaType: application/octet-stream
+ cloudevents:
+ format: "aws2-s3:application-cloudevents"
+ description: Output data type represents AWS S3 get object response
as CloudEvent V1. The data type sets Camel specific CloudEvent headers on the
exchange with respective data from the S3 bucket and its derived object.
+ headers:
+ CamelCloudEventID:
+ title: CloudEvent ID
+ description: The Camel exchange id set as event id
+ type: string
+ CamelCloudEventType:
+ title: CloudEvent Type
+ description: The event type
+ default: "org.apache.camel.event.aws.s3.getObject"
+ type: string
+ CamelCloudEventSource:
+ title: CloudEvent Source
+ description: The event source. By default, the S3 bucket name
with prefix "aws.s3.bucket.".
+ type: string
+ CamelCloudEventSubject:
+ title: CloudEvent Subject
+ description: The event subject. Usually the S3 key.
+ type: string
+ CamelCloudEventTime:
+ title: CloudEvent Time
+ description: The exchange creation timestamp as event time.
+ type: string
+ dependencies:
+ - "camel:core"
+ - "camel:aws2-s3"
+ - "camel:kamelet"
+ template:
+ from:
+ uri: "aws2-s3:{{bucketNameOrArn}}"
+ parameters:
+ autoCreateBucket: "{{autoCreateBucket}}"
+ secretKey: "{{?cheeseKey}}"
+ accessKey: "{{?accessKey}}"
+ region: "{{region}}"
+ ignoreBody: "{{ignoreBody}}"
+ deleteAfterRead: "{{deleteAfterRead}}"
+ moveAfterRead: "{{moveAfterRead}}"
+ destinationBucket: "{{?destinationBucket}}"
+ destinationBucketPrefix: "{{?destinationBucketPrefix}}"
+ destinationBucketSuffix: "{{?destinationBucketSuffix}}"
+ prefix: "{{?prefix}}"
+ useDefaultCredentialsProvider: "{{useDefaultCredentialsProvider}}"
+ useProfileCredentialsProvider: "{{useProfileCredentialsProvider}}"
+ useSessionCredentials: "{{useSessionCredentials}}"
+ uriEndpointOverride: "{{?uriEndpointOverride}}"
+ profileCredentialsName: "{{?profileCredentialsName}}"
+ sessionToken: "{{?sessionToken}}"
+ overrideEndpoint: "{{overrideEndpoint}}"
+ forcePathStyle: "{{forcePathStyle}}"
+ delay: "{{delay}}"
+ maxMessagesPerPoll: "{{maxMessagesPerPoll}}"
+ steps:
+ - to: "kamelet:sink"