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

jerryshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 3b41249d04 [#12755] fix(bundles): Exclude optional WildFly OpenSSL 
implementation (#13289)
3b41249d04 is described below

commit 3b41249d04ef9986434663236c89a87f88709272
Author: Bharath Krishna <[email protected]>
AuthorDate: Thu Sep 17 23:36:46 2026 -0700

    [#12755] fix(bundles): Exclude optional WildFly OpenSSL implementation 
(#13289)
    
    ### What changes were proposed in this pull request?
    
    Exclude `org.wildfly.openssl:wildfly-openssl` from the AWS and Azure
    shaded bundle JARs. Remove the AWS relocation rule for that provider so
    references retain the original package name when a user installs a
    compatible provider separately.
    
    Add two focused tests per bundle to verify the packaged contents and TLS
    initialization. Document the requirement for users who explicitly select
    OpenSSL.
    
    ### Why are the changes needed?
    
    The bundles include WildFly OpenSSL 1.1.3.Final, whose
    `DirectByteBufferDeallocator` implementation carries an
    [LGPL-2.1-or-later source
    
header](https://github.com/wildfly-security/wildfly-openssl/blob/1.1.3.Final/java/src/main/java/org/wildfly/openssl/util/DirectByteBufferDeallocator.java).
    The [ASF third-party license
    policy](https://www.apache.org/legal/resolved.html#category-x) prohibits
    distributing Category X components, including LGPL code. The provider
    can remain an optional, separately installed component.
    
    Related to #12755.
    
    ### Does this PR introduce _any_ user-facing change?
    
    The AWS and Azure bundles no longer contain the WildFly OpenSSL
    provider. AWS's default TLS mode uses Java's built-in JSSE
    implementation; Azure's default mode falls back to JSSE when the
    provider is absent.
    
    Users explicitly setting `fs.s3a.ssl.channel.mode` or
    `fs.azure.ssl.channel.mode` to `OpenSSL` must install a compatible
    provider separately.
    
    ### How was this patch tested?
    
    On JDK 17, all four bundle tests passed. They inspect the actual shaded
    JARs for WildFly implementation entries and initialize Hadoop's TLS
    factory in an isolated classloader, checking AWS's default JSSE mode and
    Azure's fallback to JSSE. Spotless and RAT also passed.
    
    ```shell
    ./gradlew :bundles:aws-bundle:test :bundles:azure-bundle:test -PskipITs
    ./gradlew :bundles:aws-bundle:spotlessCheck 
:bundles:azure-bundle:spotlessCheck rat
    ```
    
    These tests cover packaging and TLS factory initialization, not live
    cloud requests or compatibility with separately installed providers.
---
 bundles/aws-bundle/build.gradle.kts                | 14 ++++-
 .../apache/gravitino/bundles/TestAwsBundleTls.java | 61 ++++++++++++++++++++++
 bundles/azure-bundle/build.gradle.kts              | 13 +++++
 .../gravitino/bundles/TestAzureBundleTls.java      | 61 ++++++++++++++++++++++
 docs/fileset-catalog-with-adls.md                  |  4 ++
 docs/fileset-catalog-with-s3.md                    |  4 ++
 6 files changed, 156 insertions(+), 1 deletion(-)

diff --git a/bundles/aws-bundle/build.gradle.kts 
b/bundles/aws-bundle/build.gradle.kts
index b7ee492719..7056bea806 100644
--- a/bundles/aws-bundle/build.gradle.kts
+++ b/bundles/aws-bundle/build.gradle.kts
@@ -33,6 +33,10 @@ dependencies {
   implementation(libs.aws.sts)
   implementation(libs.hadoop3.client.api)
   implementation(libs.hadoop3.client.runtime)
+
+  testImplementation(libs.junit.jupiter.api)
+  testImplementation(libs.slf4j.api)
+  testRuntimeOnly(libs.junit.jupiter.engine)
 }
 
 tasks.withType(ShadowJar::class.java) {
@@ -42,6 +46,8 @@ tasks.withType(ShadowJar::class.java) {
 
   dependencies {
     exclude(dependency("org.slf4j:slf4j-api"))
+    // The optional OpenSSL provider contains LGPL code. Hadoop's default mode 
falls back to JSSE.
+    exclude(dependency("org.wildfly.openssl:wildfly-openssl"))
 
     // Exclude Gravitino modules to prevent class duplication and "Split 
Packages" issues.
     // These modules (api, common, catalogs) are already provided by the 
Gravitino server and gravitino-filesystem-hadoop3-runtime.
@@ -63,7 +69,6 @@ tasks.withType(ShadowJar::class.java) {
   relocate("org.apache.http", 
"org.apache.gravitino.aws.shaded.org.apache.http")
   relocate("org.checkerframework", 
"org.apache.gravitino.aws.shaded.org.checkerframework")
   relocate("org.reactivestreams", 
"org.apache.gravitino.aws.shaded.org.reactivestreams")
-  relocate("org.wildfly.openssl", 
"org.apache.gravitino.aws.shaded.org.wildfly.openssl")
 
   mergeServiceFiles()
 }
@@ -76,3 +81,10 @@ tasks.jar {
 tasks.compileJava {
   dependsOn(":catalogs:catalog-fileset:runtimeJars")
 }
+
+tasks.test {
+  val bundle = tasks.named<ShadowJar>("shadowJar")
+  dependsOn(bundle)
+  inputs.file(bundle.flatMap { it.archiveFile })
+  doFirst { systemProperty("shadowJarPath", 
bundle.get().archiveFile.get().asFile.absolutePath) }
+}
diff --git 
a/bundles/aws-bundle/src/test/java/org/apache/gravitino/bundles/TestAwsBundleTls.java
 
b/bundles/aws-bundle/src/test/java/org/apache/gravitino/bundles/TestAwsBundleTls.java
new file mode 100644
index 0000000000..49106cb93a
--- /dev/null
+++ 
b/bundles/aws-bundle/src/test/java/org/apache/gravitino/bundles/TestAwsBundleTls.java
@@ -0,0 +1,61 @@
+/*
+ * 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.gravitino.bundles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.jar.JarFile;
+import org.junit.jupiter.api.Test;
+import org.slf4j.LoggerFactory;
+
+class TestAwsBundleTls {
+  private static final File BUNDLE = new 
File(System.getProperty("shadowJarPath"));
+
+  @Test
+  void testBundleExcludesWildFlyImplementation() throws Exception {
+    try (JarFile jar = new JarFile(BUNDLE)) {
+      assertFalse(
+          jar.stream().anyMatch(entry -> 
entry.getName().contains("org/wildfly/openssl/")),
+          BUNDLE.getName());
+    }
+  }
+
+  @Test
+  void testDefaultJsseModeWorksWithoutWildFly() throws Exception {
+    URL[] urls = {
+      BUNDLE.toURI().toURL(),
+      LoggerFactory.class.getProtectionDomain().getCodeSource().getLocation()
+    };
+    // The ordinary test classpath also contains unshaded Hadoop and the 
optional provider.
+    try (URLClassLoader loader = new URLClassLoader(urls, 
ClassLoader.getPlatformClassLoader())) {
+      Class<?> factory =
+          
loader.loadClass("org.apache.hadoop.security.ssl.DelegatingSSLSocketFactory");
+      Class<?> mode = loader.loadClass(factory.getName() + "$SSLChannelMode");
+      factory
+          .getMethod("initializeDefaultFactory", mode)
+          .invoke(null, mode.getField("Default_JSSE").get(null));
+      Object instance = factory.getMethod("getDefaultFactory").invoke(null);
+      assertEquals("Default_JSSE", 
factory.getMethod("getChannelMode").invoke(instance).toString());
+    }
+  }
+}
diff --git a/bundles/azure-bundle/build.gradle.kts 
b/bundles/azure-bundle/build.gradle.kts
index 632cc83d53..b2574b544b 100644
--- a/bundles/azure-bundle/build.gradle.kts
+++ b/bundles/azure-bundle/build.gradle.kts
@@ -36,6 +36,10 @@ dependencies {
   implementation(libs.hadoop3.abs)
   implementation(libs.hadoop3.client.api)
   implementation(libs.hadoop3.client.runtime)
+
+  testImplementation(libs.junit.jupiter.api)
+  testImplementation(libs.slf4j.api)
+  testRuntimeOnly(libs.junit.jupiter.engine)
 }
 
 tasks.withType(ShadowJar::class.java) {
@@ -45,6 +49,8 @@ tasks.withType(ShadowJar::class.java) {
 
   dependencies {
     exclude(dependency("org.slf4j:slf4j-api"))
+    // The optional OpenSSL provider contains LGPL code. Hadoop's default mode 
falls back to JSSE.
+    exclude(dependency("org.wildfly.openssl:wildfly-openssl"))
 
     // Exclude Gravitino modules to prevent class duplication and "Split 
Packages" issues.
     // These modules (api, common, catalogs) are already provided by the 
Gravitino server and gravitino-filesystem-hadoop3-runtime.
@@ -87,3 +93,10 @@ tasks.jar {
 tasks.compileJava {
   dependsOn(":catalogs:catalog-fileset:runtimeJars")
 }
+
+tasks.test {
+  val bundle = tasks.named<ShadowJar>("shadowJar")
+  dependsOn(bundle)
+  inputs.file(bundle.flatMap { it.archiveFile })
+  doFirst { systemProperty("shadowJarPath", 
bundle.get().archiveFile.get().asFile.absolutePath) }
+}
diff --git 
a/bundles/azure-bundle/src/test/java/org/apache/gravitino/bundles/TestAzureBundleTls.java
 
b/bundles/azure-bundle/src/test/java/org/apache/gravitino/bundles/TestAzureBundleTls.java
new file mode 100644
index 0000000000..fd00e0d8c5
--- /dev/null
+++ 
b/bundles/azure-bundle/src/test/java/org/apache/gravitino/bundles/TestAzureBundleTls.java
@@ -0,0 +1,61 @@
+/*
+ * 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.gravitino.bundles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.jar.JarFile;
+import org.junit.jupiter.api.Test;
+import org.slf4j.LoggerFactory;
+
+class TestAzureBundleTls {
+  private static final File BUNDLE = new 
File(System.getProperty("shadowJarPath"));
+
+  @Test
+  void testBundleExcludesWildFlyImplementation() throws Exception {
+    try (JarFile jar = new JarFile(BUNDLE)) {
+      assertFalse(
+          jar.stream().anyMatch(entry -> 
entry.getName().contains("org/wildfly/openssl/")),
+          BUNDLE.getName());
+    }
+  }
+
+  @Test
+  void testDefaultModeFallsBackToJsse() throws Exception {
+    URL[] urls = {
+      BUNDLE.toURI().toURL(),
+      LoggerFactory.class.getProtectionDomain().getCodeSource().getLocation()
+    };
+    // The ordinary test classpath also contains unshaded Hadoop and the 
optional provider.
+    try (URLClassLoader loader = new URLClassLoader(urls, 
ClassLoader.getPlatformClassLoader())) {
+      Class<?> factory =
+          
loader.loadClass("org.apache.hadoop.security.ssl.DelegatingSSLSocketFactory");
+      Class<?> mode = loader.loadClass(factory.getName() + "$SSLChannelMode");
+      factory
+          .getMethod("initializeDefaultFactory", mode)
+          .invoke(null, mode.getField("Default").get(null));
+      Object instance = factory.getMethod("getDefaultFactory").invoke(null);
+      assertEquals("Default_JSSE", 
factory.getMethod("getChannelMode").invoke(instance).toString());
+    }
+  }
+}
diff --git a/docs/fileset-catalog-with-adls.md 
b/docs/fileset-catalog-with-adls.md
index be3fa2f83e..9c0a076300 100644
--- a/docs/fileset-catalog-with-adls.md
+++ b/docs/fileset-catalog-with-adls.md
@@ -32,6 +32,10 @@ The catalog automatically loads the Azure Data Lake Storage 
filesystem provider
 classpath. The deprecated `filesystem-providers` and 
`default-filesystem-provider` catalog
 properties do not need to be set.
 
+The bundle uses JSSE for TLS and does not include the optional WildFly OpenSSL 
provider.
+If you explicitly set Hadoop's `fs.azure.ssl.channel.mode` to `OpenSSL`, 
install a compatible
+provider separately on the catalog or client classpath. The default mode does 
not require it.
+
 ## Azure Data Lake Storage Properties
 
 These properties are needed in addition to the shared
diff --git a/docs/fileset-catalog-with-s3.md b/docs/fileset-catalog-with-s3.md
index bc523ce2fa..39ea40e600 100644
--- a/docs/fileset-catalog-with-s3.md
+++ b/docs/fileset-catalog-with-s3.md
@@ -32,6 +32,10 @@ The catalog automatically loads the Amazon S3 filesystem 
provider once the bundl
 classpath. The deprecated `filesystem-providers` and 
`default-filesystem-provider` catalog
 properties do not need to be set.
 
+The bundle uses JSSE for TLS and does not include the optional WildFly OpenSSL 
provider.
+If you explicitly set Hadoop's `fs.s3a.ssl.channel.mode` to `OpenSSL`, install 
a compatible
+provider separately on the catalog or client classpath. The default mode does 
not require it.
+
 ## Amazon S3 Properties
 
 These properties are needed in addition to the shared

Reply via email to