atiaomar1978-hub commented on code in PR #26026:
URL: https://github.com/apache/camel/pull/26026#discussion_r3911187879


##########
components/camel-avro/src/main/java/org/apache/camel/dataformat/avro/AvroDataFormat.java:
##########
@@ -135,6 +158,9 @@ protected Schema loadSchema(String className) throws 
CamelException, ClassNotFou
 
     @Override
     public void marshal(Exchange exchange, Object graph, OutputStream 
outputStream) throws Exception {
+        if (actualSchema == null) {

Review Comment:
   **Fixed in e7f7c32:** Trust graph class only when `actualSchema == null` 
(dynamic schema inference). Preconfigured schema/instance paths trust at init 
only.
   
   _AI-generated on behalf of @atiaomar1978-hub_



##########
components/camel-avro/src/main/java/org/apache/camel/avro/support/AvroClassSecuritySupport.java:
##########
@@ -0,0 +1,172 @@
+/*
+ * 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.avro.support;
+
+import java.util.Arrays;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.avro.util.ClassSecurityValidator;
+import org.apache.avro.util.ClassSecurityValidator.ClassSecurityPredicate;
+
+/**
+ * Configures Apache Avro {@link ClassSecurityValidator} with Camel trusted 
packages.
+ * <p>
+ * Avro 1.12+ validates classes resolved from schemas. Camel automatically 
trusts packages derived from configured
+ * protocol or schema classes. Additional packages can be configured through 
the {@code serializablePackages} endpoint
+ * option.
+ * <p>
+ * Trusted packages are stored in a JVM-wide registry shared by all Camel 
contexts in the process. Trust is cumulative
+ * and cannot be revoked in production.
+ */
+public final class AvroClassSecuritySupport {
+
+    private static final Set<String> TRUSTED_PACKAGES = 
ConcurrentHashMap.newKeySet();
+
+    private static final Set<String> TRUSTED_CLASSES = 
ConcurrentHashMap.newKeySet();
+
+    private static final Object LOCK = new Object();
+
+    private static final ClassSecurityPredicate CAMEL_TRUSTED = 
AvroClassSecuritySupport::isCamelTrusted;
+
+    private static volatile ClassSecurityPredicate baseValidator = 
ClassSecurityValidator.DEFAULT;
+
+    private static volatile ClassSecurityPredicate installedGlobal;
+
+    private static volatile NavigableSet<String> normalizedPackagePrefixes = 
new TreeSet<>();
+
+    private AvroClassSecuritySupport() {
+    }
+
+    /**
+     * Trusts Avro IPC classes required for camel-avro-rpc handshake.
+     */
+    public static void ensureAvroIpcPackagesTrusted() {
+        trustPackages("org.apache.avro.ipc");
+    }
+
+    /**
+     * Trusts the exact class name and its package for schema resolution.
+     */
+    public static void trustClassName(String className) {
+        if (className == null || className.isBlank()) {
+            return;
+        }
+        synchronized (LOCK) {
+            TRUSTED_CLASSES.add(className);
+            int lastDot = className.lastIndexOf('.');
+            if (lastDot > 0) {
+                TRUSTED_PACKAGES.add(normalizePackage(className.substring(0, 
lastDot)));
+            }
+            rebuildNormalizedPackagePrefixes();
+            refreshGlobal();
+        }
+    }
+
+    /**
+     * Trusts the comma-separated list of packages.
+     */
+    public static void trustPackages(String packages) {
+        if (packages == null || packages.isBlank()) {
+            return;
+        }
+        trustPackages(parsePackages(packages).toArray(String[]::new));
+    }
+
+    /**
+     * Trusts the given packages.
+     */
+    public static void trustPackages(String... packages) {
+        if (packages == null || packages.length == 0) {
+            return;
+        }
+        synchronized (LOCK) {
+            for (String pkg : packages) {
+                if (pkg != null && !pkg.isBlank()) {
+                    TRUSTED_PACKAGES.add(normalizePackage(pkg));
+                }
+            }
+            rebuildNormalizedPackagePrefixes();
+            refreshGlobal();
+        }
+    }
+
+    /**
+     * Clears Camel-managed trusted classes and packages. Intended for tests.
+     */
+    public static void resetForTesting() {
+        synchronized (LOCK) {
+            TRUSTED_PACKAGES.clear();
+            TRUSTED_CLASSES.clear();
+            normalizedPackagePrefixes = new TreeSet<>();
+            baseValidator = ClassSecurityValidator.DEFAULT;
+            installedGlobal = null;
+            ClassSecurityValidator.setGlobal(ClassSecurityValidator.DEFAULT);
+        }
+    }
+
+    private static void refreshGlobal() {
+        if (installedGlobal == null) {

Review Comment:
   **Fixed in e7f7c32:** First trust call captures existing 
`ClassSecurityValidator.getGlobal()` as base and composes Camel predicate on 
top.
   
   _AI-generated on behalf of @atiaomar1978-hub_



##########
components/camel-avro/src/main/java/org/apache/camel/avro/support/AvroClassSecuritySupport.java:
##########
@@ -0,0 +1,172 @@
+/*
+ * 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.avro.support;
+
+import java.util.Arrays;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.avro.util.ClassSecurityValidator;
+import org.apache.avro.util.ClassSecurityValidator.ClassSecurityPredicate;
+
+/**
+ * Configures Apache Avro {@link ClassSecurityValidator} with Camel trusted 
packages.
+ * <p>
+ * Avro 1.12+ validates classes resolved from schemas. Camel automatically 
trusts packages derived from configured
+ * protocol or schema classes. Additional packages can be configured through 
the {@code serializablePackages} endpoint
+ * option.
+ * <p>
+ * Trusted packages are stored in a JVM-wide registry shared by all Camel 
contexts in the process. Trust is cumulative
+ * and cannot be revoked in production.
+ */
+public final class AvroClassSecuritySupport {
+
+    private static final Set<String> TRUSTED_PACKAGES = 
ConcurrentHashMap.newKeySet();
+
+    private static final Set<String> TRUSTED_CLASSES = 
ConcurrentHashMap.newKeySet();
+
+    private static final Object LOCK = new Object();
+
+    private static final ClassSecurityPredicate CAMEL_TRUSTED = 
AvroClassSecuritySupport::isCamelTrusted;
+
+    private static volatile ClassSecurityPredicate baseValidator = 
ClassSecurityValidator.DEFAULT;
+
+    private static volatile ClassSecurityPredicate installedGlobal;
+
+    private static volatile NavigableSet<String> normalizedPackagePrefixes = 
new TreeSet<>();
+
+    private AvroClassSecuritySupport() {
+    }
+
+    /**
+     * Trusts Avro IPC classes required for camel-avro-rpc handshake.
+     */
+    public static void ensureAvroIpcPackagesTrusted() {
+        trustPackages("org.apache.avro.ipc");
+    }
+
+    /**
+     * Trusts the exact class name and its package for schema resolution.
+     */
+    public static void trustClassName(String className) {
+        if (className == null || className.isBlank()) {
+            return;
+        }
+        synchronized (LOCK) {
+            TRUSTED_CLASSES.add(className);
+            int lastDot = className.lastIndexOf('.');
+            if (lastDot > 0) {
+                TRUSTED_PACKAGES.add(normalizePackage(className.substring(0, 
lastDot)));
+            }
+            rebuildNormalizedPackagePrefixes();
+            refreshGlobal();
+        }
+    }
+
+    /**
+     * Trusts the comma-separated list of packages.
+     */
+    public static void trustPackages(String packages) {
+        if (packages == null || packages.isBlank()) {
+            return;
+        }
+        trustPackages(parsePackages(packages).toArray(String[]::new));
+    }
+
+    /**
+     * Trusts the given packages.
+     */
+    public static void trustPackages(String... packages) {
+        if (packages == null || packages.length == 0) {
+            return;
+        }
+        synchronized (LOCK) {
+            for (String pkg : packages) {
+                if (pkg != null && !pkg.isBlank()) {
+                    TRUSTED_PACKAGES.add(normalizePackage(pkg));
+                }
+            }
+            rebuildNormalizedPackagePrefixes();
+            refreshGlobal();
+        }
+    }
+
+    /**
+     * Clears Camel-managed trusted classes and packages. Intended for tests.
+     */
+    public static void resetForTesting() {
+        synchronized (LOCK) {
+            TRUSTED_PACKAGES.clear();
+            TRUSTED_CLASSES.clear();
+            normalizedPackagePrefixes = new TreeSet<>();
+            baseValidator = ClassSecurityValidator.DEFAULT;
+            installedGlobal = null;
+            ClassSecurityValidator.setGlobal(ClassSecurityValidator.DEFAULT);
+        }
+    }
+
+    private static void refreshGlobal() {
+        if (installedGlobal == null) {
+            ClassSecurityPredicate current = 
ClassSecurityValidator.getGlobal();
+            if (current != null && current != ClassSecurityValidator.DEFAULT) {
+                baseValidator = current;
+            }
+        }
+        installedGlobal = ClassSecurityValidator.composite(baseValidator, 
CAMEL_TRUSTED);
+        ClassSecurityValidator.setGlobal(installedGlobal);
+    }
+
+    private static boolean isCamelTrusted(Class<?> clazz) {
+        String className = clazz.getName();
+        if (TRUSTED_CLASSES.contains(className)) {
+            return true;
+        }
+        NavigableSet<String> packages = normalizedPackagePrefixes;
+        String lower = packages.lower(className);
+        return lower != null && className.startsWith(lower);
+    }
+
+    private static void rebuildNormalizedPackagePrefixes() {
+        NavigableSet<String> normalized = new TreeSet<>();

Review Comment:
   **Fixed in e7f7c32:** Normalized package prefixes cached in 
`normalizedPackagePrefixes`, rebuilt only when allowlist mutates.
   
   _AI-generated on behalf of @atiaomar1978-hub_



##########
core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/AvroDataFormat.java:
##########
@@ -120,6 +120,10 @@ public class AvroDataFormat extends DataFormatDefinition 
implements ContentTypeH
     @Metadata(label = "advanced", javaType = "java.lang.Boolean", defaultValue 
= "true",
               description = "When not disabled, the SchemaResolver will be 
looked up into the registry.")
     private String autoDiscoverSchemaResolver;
+    @XmlAttribute

Review Comment:
   **Fixed in e7f7c32:** Added `serializablePackages` to core model with full 
regen (catalog, YAML, XML schema, reifier). Usable from XML/YAML/fluent DSL.
   
   _AI-generated on behalf of @atiaomar1978-hub_



##########
catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/avro.json:
##########
@@ -33,7 +33,8 @@
     "bridgeErrorHandler": { "index": 6, "kind": "property", "displayName": 
"Bridge Error Handler", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Allows for bridging the consumer to the Camel routing Error Handler, which 
mean any exceptions (if possible) occurred while the Camel consumer is trying 
to pickup incoming messages, or the likes, will now be processed as a message 
and handled by the routing Error Handler. Important: This is only possible if 
the 3rd party component allows Camel to be alerted if an exception was thrown. 
Some components handle this internally only, and therefore bridgeErrorHandler 
is not possible. In other situations we may improve the Camel component to hook 
into the 3rd party component and make this possible for future releases. By 
default the consumer will use the org.apache.camel.spi.ExceptionHandler to d
 eal with exceptions, that will be logged at WARN or ERROR level and ignored." 
},
     "lazyStartProducer": { "index": 7, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"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." },
     "autowiredEnabled": { "index": 8, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"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." },
-    "configuration": { "index": 9, "kind": "property", "displayName": 
"Configuration", "group": "advanced", "label": "advanced", "required": false, 
"type": "object", "javaType": 
"org.apache.camel.component.avro.AvroConfiguration", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a shared 
AvroConfiguration to configure options once" }
+    "configuration": { "index": 9, "kind": "property", "displayName": 
"Configuration", "group": "advanced", "label": "advanced", "required": false, 
"type": "object", "javaType": 
"org.apache.camel.component.avro.AvroConfiguration", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a shared 
AvroConfiguration to configure options once" },
+    "serializablePackages": { "index": 10, "kind": "property", "displayName": 
"Serializable Packages", "group": "security", "label": "security", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "security": "insecure:serialization", 
"configurationClass": "org.apache.camel.component.avro.AvroConfiguration", 
"configurationField": "configuration", "description": "Comma-separated list of 
additional packages that contain trusted Avro model classes. Avro 1.12 
validates classes resolved from schemas; Camel automatically trusts 
org.apache.avro for IPC and packages derived from the configured protocol. Use 
this option for any additional model packages not inferred from the protocol." }

Review Comment:
   **Fixed in e7f7c32:** Regenerated catalog + endpoint/component DSL — 
`serializablePackages` now present for RPC component.
   
   _AI-generated on behalf of @atiaomar1978-hub_



-- 
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