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&region=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"

Reply via email to