You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2024/01/11 11:58:46 UTC

(camel) branch camel-3.x updated: CAMEL-20306 - Camel-CassandraQL: Add ObjectInputFilter String pattern parameter in CassandraAggregationRepository to be used in unmarshall operations (#12761)

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-3.x by this push:
     new 04a76404fc2 CAMEL-20306 - Camel-CassandraQL: Add ObjectInputFilter String pattern parameter in CassandraAggregationRepository to be used in unmarshall operations (#12761)
04a76404fc2 is described below

commit 04a76404fc2e64d63e89eb0c9f1dc716fd1b6a55
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Thu Jan 11 12:58:33 2024 +0100

    CAMEL-20306 - Camel-CassandraQL: Add ObjectInputFilter String pattern parameter in CassandraAggregationRepository to be used in unmarshall operations (#12761)
    
    * CAMEL-20306 - Camel-CassandraQL: Add ObjectInputFilter String pattern parameter in CassandraAggregationRepository to be used in unmarshall operations
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
    
    * CAMEL-20306 - Camel-CassandraQL: Add ObjectInputFilter String pattern parameter in CassandraAggregationRepository to be used in unmarshall operations - Docs
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
 .../src/main/docs/cql-component.adoc               |  4 ++
 .../cassandra/CassandraAggregationRepository.java  | 19 +++++++-
 .../aggregate/cassandra/CassandraCamelCodec.java   | 15 +++---
 .../cassandra/CassandraCamelCodecTest.java         | 56 ++++++++++++++++++++++
 .../test/java/org/malicious/example/Employee.java  | 46 ++++++++++++++++++
 5 files changed, 131 insertions(+), 9 deletions(-)

diff --git a/components/camel-cassandraql/src/main/docs/cql-component.adoc b/components/camel-cassandraql/src/main/docs/cql-component.adoc
index f5e342f5f3a..e08d7063bce 100644
--- a/components/camel-cassandraql/src/main/docs/cql-component.adoc
+++ b/components/camel-cassandraql/src/main/docs/cql-component.adoc
@@ -186,6 +186,10 @@ Alternatively, the `CassandraAggregationRepository` does not have a
 `LOCAL_QUORUM`…
 |=======================================================================
 
+While deserializing it's important to notice that the the unmarshallExchange method will allow only all java packages and subpackages
+and org.apache.camel packages and subpackages. The remaining classes will be blacklisted. So you'll need to change the filter in case of need.
+This could be accomplished by changing the deserializationFilter field on the repository.
+
 == Examples
 
 To insert something on a table you can use the following code:
diff --git a/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraAggregationRepository.java b/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraAggregationRepository.java
index 00277bbfccd..b64653a96f1 100644
--- a/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraAggregationRepository.java
+++ b/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraAggregationRepository.java
@@ -121,6 +121,14 @@ public class CassandraAggregationRepository extends ServiceSupport implements Re
 
     private boolean allowSerializedHeaders;
 
+    /**
+     * Sets a deserialization filter while reading Object from Aggregation Repository. By default the filter will allow
+     * all java packages and subpackages and all org.apache.camel packages and subpackages, while the remaining will be
+     * blacklisted and not deserialized. This parameter should be customized if you're using classes you trust to be
+     * deserialized.
+     */
+    private String deserializationFilter = "java.**;org.apache.camel.**;!*";
+
     public CassandraAggregationRepository() {
     }
 
@@ -211,7 +219,8 @@ public class CassandraAggregationRepository extends ServiceSupport implements Re
         Exchange exchange = null;
         if (row != null) {
             try {
-                exchange = exchangeCodec.unmarshallExchange(camelContext, row.getByteBuffer(exchangeColumn));
+                exchange = exchangeCodec.unmarshallExchange(camelContext, row.getByteBuffer(exchangeColumn),
+                        deserializationFilter);
             } catch (IOException iOException) {
                 throw new CassandraAggregationException("Failed to read exchange", exchange, iOException);
             } catch (ClassNotFoundException classNotFoundException) {
@@ -468,4 +477,12 @@ public class CassandraAggregationRepository extends ServiceSupport implements Re
     public void setAllowSerializedHeaders(boolean allowSerializedHeaders) {
         this.allowSerializedHeaders = allowSerializedHeaders;
     }
+
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
 }
diff --git a/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodec.java b/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodec.java
index b2bcfbf0b17..0c3d54387d4 100644
--- a/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodec.java
+++ b/components/camel-cassandraql/src/main/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodec.java
@@ -16,11 +16,7 @@
  */
 package org.apache.camel.processor.aggregate.cassandra;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
+import java.io.*;
 import java.nio.ByteBuffer;
 
 import org.apache.camel.CamelContext;
@@ -63,9 +59,10 @@ public class CassandraCamelCodec {
         return ByteBuffer.wrap(serialize(pe));
     }
 
-    public Exchange unmarshallExchange(CamelContext camelContext, ByteBuffer buffer)
+    public Exchange unmarshallExchange(CamelContext camelContext, ByteBuffer buffer, String deserializationFilter)
             throws IOException, ClassNotFoundException {
-        DefaultExchangeHolder pe = (DefaultExchangeHolder) deserialize(camelContext, new ByteBufferInputStream(buffer));
+        DefaultExchangeHolder pe
+                = (DefaultExchangeHolder) deserialize(camelContext, new ByteBufferInputStream(buffer), deserializationFilter);
         Exchange answer = new DefaultExchange(camelContext);
         DefaultExchangeHolder.unmarshal(answer, pe);
         // restore the from endpoint
@@ -87,9 +84,11 @@ public class CassandraCamelCodec {
         return bytesOut.toByteArray();
     }
 
-    private Object deserialize(CamelContext camelContext, InputStream bytes) throws IOException, ClassNotFoundException {
+    private Object deserialize(CamelContext camelContext, InputStream bytes, String deserializationFilter)
+            throws IOException, ClassNotFoundException {
         ClassLoader classLoader = camelContext.getApplicationContextClassLoader();
         ObjectInputStream objectIn = new ClassLoadingAwareObjectInputStream(classLoader, bytes);
+        objectIn.setObjectInputFilter(ObjectInputFilter.Config.createFilter(deserializationFilter));
         Object object = objectIn.readObject();
         objectIn.close();
         return object;
diff --git a/components/camel-cassandraql/src/test/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodecTest.java b/components/camel-cassandraql/src/test/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodecTest.java
new file mode 100644
index 00000000000..f7f08a7f664
--- /dev/null
+++ b/components/camel-cassandraql/src/test/java/org/apache/camel/processor/aggregate/cassandra/CassandraCamelCodecTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.processor.aggregate.cassandra;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.malicious.example.Employee;
+
+public class CassandraCamelCodecTest extends CamelTestSupport {
+
+    CassandraCamelCodec codec;
+
+    @Override
+    protected void startCamelContext() throws Exception {
+        super.startCamelContext();
+        codec = new CassandraCamelCodec();
+    }
+
+    @Test
+    public void shouldFailWithRejected() throws IOException, ClassNotFoundException {
+        Employee emp = new Employee("Mickey", "Mouse");
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+        oos.writeObject(emp);
+
+        oos.flush();
+        oos.close();
+
+        InputStream is = new ByteArrayInputStream(baos.toByteArray());
+        InvalidClassException thrown = Assertions.assertThrows(InvalidClassException.class, () -> {
+            codec.unmarshallExchange(context, ByteBuffer.wrap(is.readAllBytes()), "java.**;org.apache.camel.**;!*");
+        });
+
+        Assertions.assertEquals("filter status: REJECTED", thrown.getMessage());
+    }
+}
diff --git a/components/camel-cassandraql/src/test/java/org/malicious/example/Employee.java b/components/camel-cassandraql/src/test/java/org/malicious/example/Employee.java
new file mode 100644
index 00000000000..3850218d128
--- /dev/null
+++ b/components/camel-cassandraql/src/test/java/org/malicious/example/Employee.java
@@ -0,0 +1,46 @@
+/*
+ * 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.malicious.example;
+
+import java.io.Serializable;
+
+public class Employee implements Serializable {
+
+    String name;
+    String surname;
+
+    public Employee(String name, String surname) {
+        this.name = name;
+        this.surname = surname;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSurname() {
+        return surname;
+    }
+
+    public void setSurname(String surname) {
+        this.surname = surname;
+    }
+}