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

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


The following commit(s) were added to refs/heads/branch-1.3 by this push:
     new 6550504638 [Cherry-pick to branch-1.3] [#12270] fix(glue): Ignore 
blank AWS static credentials (#12271) (#12361)
6550504638 is described below

commit 6550504638ecd1f4e06194f441ff0a608adb4b06
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Aug 5 19:09:23 2026 +0800

    [Cherry-pick to branch-1.3] [#12270] fix(glue): Ignore blank AWS static 
credentials (#12271) (#12361)
    
    **Cherry-pick Information:**
    - Original commit: 97da744f36787c49dfdd4a52711c84d15664b875
    - Target branch: `branch-1.3`
    - Status: ✅ Clean cherry-pick (no conflicts)
    
    Co-authored-by: Xu Bai <[email protected]>
---
 .../gravitino/catalog/glue/GlueClientProvider.java |  26 ++++--
 .../catalog/glue/GlueIcebergTableHelper.java       |  25 ++---
 .../catalog/glue/TestGlueIcebergTableHelper.java   | 101 +++++++++++++++++++++
 3 files changed, 131 insertions(+), 21 deletions(-)

diff --git 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueClientProvider.java
 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueClientProvider.java
index 8f4aa666c2..3c792449e4 100644
--- 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueClientProvider.java
+++ 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueClientProvider.java
@@ -74,17 +74,9 @@ public final class GlueClientProvider {
     //   6. EC2 instance profile (IMDSv2)
     String accessKey = config.get(GlueConstants.AWS_ACCESS_KEY_ID);
     String secretKey = config.get(GlueConstants.AWS_SECRET_ACCESS_KEY);
-    boolean hasAccessKey = StringUtils.isNotBlank(accessKey);
-    boolean hasSecretKey = StringUtils.isNotBlank(secretKey);
-    Preconditions.checkArgument(
-        hasAccessKey == hasSecretKey,
-        "Both '%s' and '%s' must be set together. "
-            + "Either provide both keys for static authentication, "
-            + "or omit both to use the default credential chain.",
-        GlueConstants.AWS_ACCESS_KEY_ID,
-        GlueConstants.AWS_SECRET_ACCESS_KEY);
+    boolean hasStaticCredentials = hasAwsStaticCredentials(accessKey, 
secretKey);
 
-    if (hasAccessKey) {
+    if (hasStaticCredentials) {
       builder.credentialsProvider(
           
StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, 
secretKey)));
     } else {
@@ -99,4 +91,18 @@ public final class GlueClientProvider {
 
     return builder.build();
   }
+
+  static boolean hasAwsStaticCredentials(String accessKey, String secretKey) {
+    boolean hasAccessKey = StringUtils.isNotBlank(accessKey);
+    boolean hasSecretKey = StringUtils.isNotBlank(secretKey);
+    Preconditions.checkArgument(
+        hasAccessKey == hasSecretKey,
+        "Both '%s' and '%s' must be set together. "
+            + "Either provide both keys for static authentication, "
+            + "or omit both to use the default credential chain.",
+        GlueConstants.AWS_ACCESS_KEY_ID,
+        GlueConstants.AWS_SECRET_ACCESS_KEY);
+
+    return hasAccessKey;
+  }
 }
diff --git 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
index d8bb3f6b05..9d9d59d4af 100644
--- 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
+++ 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
@@ -143,6 +143,15 @@ final class GlueIcebergTableHelper {
    * @throws IllegalArgumentException if {@code aws-region} or {@code 
warehouse} is not configured
    */
   static Catalog createGlueCatalog(Map<String, String> config) {
+    Map<String, String> icebergProps = buildIcebergCatalogProperties(config);
+
+    GlueCatalog glueCatalog = new GlueCatalog();
+    glueCatalog.initialize("gravitino-glue-iceberg", icebergProps);
+    LOG.info("Initialized Iceberg GlueCatalog for region {}", 
config.get(GlueConstants.AWS_REGION));
+    return glueCatalog;
+  }
+
+  static Map<String, String> buildIcebergCatalogProperties(Map<String, String> 
config) {
     String region = config.get(GlueConstants.AWS_REGION);
     Preconditions.checkArgument(region != null, "AWS region is required for 
Iceberg Glue catalog");
 
@@ -164,11 +173,14 @@ final class GlueIcebergTableHelper {
 
     String accessKey = config.get(GlueConstants.AWS_ACCESS_KEY_ID);
     String secretKey = config.get(GlueConstants.AWS_SECRET_ACCESS_KEY);
-    if (accessKey != null && secretKey != null) {
+    boolean hasCredential = 
GlueClientProvider.hasAwsStaticCredentials(accessKey, secretKey);
+    if (hasCredential) {
       icebergProps.put(
           CLIENT_CREDENTIALS_PROVIDER, 
GravitinoGlueCredentialsProvider.class.getName());
       icebergProps.put(CLIENT_CREDENTIALS_PROVIDER_ACCESS_KEY_ID, accessKey);
       icebergProps.put(CLIENT_CREDENTIALS_PROVIDER_SECRET_ACCESS_KEY, 
secretKey);
+      icebergProps.put(IcebergConstants.ICEBERG_S3_ACCESS_KEY_ID, accessKey);
+      icebergProps.put(IcebergConstants.ICEBERG_S3_SECRET_ACCESS_KEY, 
secretKey);
     }
 
     String endpoint = config.get(GlueConstants.AWS_GLUE_ENDPOINT);
@@ -176,17 +188,8 @@ final class GlueIcebergTableHelper {
       icebergProps.put(GLUE_ENDPOINT, endpoint);
     }
 
-    if (accessKey != null && secretKey != null) {
-      icebergProps.put(IcebergConstants.ICEBERG_S3_ACCESS_KEY_ID, accessKey);
-      icebergProps.put(IcebergConstants.ICEBERG_S3_SECRET_ACCESS_KEY, 
secretKey);
-    }
-
     icebergProps.put(IcebergConstants.IO_IMPL, 
"org.apache.iceberg.aws.s3.S3FileIO");
-
-    GlueCatalog glueCatalog = new GlueCatalog();
-    glueCatalog.initialize("gravitino-glue-iceberg", icebergProps);
-    LOG.info("Initialized Iceberg GlueCatalog for region {}", region);
-    return glueCatalog;
+    return icebergProps;
   }
 
   /**
diff --git 
a/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueIcebergTableHelper.java
 
b/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueIcebergTableHelper.java
index e3f3f3bb8b..5e1bce6029 100644
--- 
a/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueIcebergTableHelper.java
+++ 
b/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueIcebergTableHelper.java
@@ -22,12 +22,16 @@ import static 
org.apache.gravitino.catalog.glue.GlueIcebergTableHelper.fromIcebe
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.io.IOException;
 import java.util.HashMap;
+import java.util.Map;
+import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
 import org.apache.gravitino.meta.AuditInfo;
 import org.apache.gravitino.rel.Column;
 import org.apache.gravitino.rel.types.Types;
@@ -35,6 +39,8 @@ import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.SortOrder;
 import org.apache.iceberg.Table;
+import org.apache.iceberg.aws.AwsClientProperties;
+import org.apache.iceberg.aws.glue.GlueCatalog;
 import org.apache.iceberg.catalog.Catalog;
 import org.apache.iceberg.catalog.TableIdentifier;
 import org.apache.iceberg.types.Types.BooleanType;
@@ -235,4 +241,99 @@ class TestGlueIcebergTableHelper {
     assertEquals(Types.TimeType.of(6), cols[1].dataType());
     assertEquals(Types.DecimalType.of(10, 2), cols[2].dataType());
   }
+
+  @Test
+  void testCreateGlueCatalog() throws IOException {
+    Map<String, String> config = new HashMap<>();
+    config.put(GlueConstants.AWS_REGION, "us-east-1");
+    config.put(GlueConstants.WAREHOUSE, "s3://test-bucket/warehouse");
+
+    Catalog catalog = GlueIcebergTableHelper.createGlueCatalog(config);
+    GlueCatalog glueCatalog = assertInstanceOf(GlueCatalog.class, catalog);
+    glueCatalog.close();
+  }
+
+  @Test
+  void testBuildIcebergCatalogPropertiesWithoutStaticCredentials() {
+    Map<String, String> config = new HashMap<>();
+    config.put(GlueConstants.AWS_REGION, "us-east-1");
+    config.put(GlueConstants.WAREHOUSE, "s3://test-bucket/warehouse");
+
+    Map<String, String> icebergProps = 
GlueIcebergTableHelper.buildIcebergCatalogProperties(config);
+    
assertFalse(icebergProps.containsKey(AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER));
+    assertFalse(
+        icebergProps.containsKey(
+            AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER + 
".access-key-id"));
+    assertFalse(
+        icebergProps.containsKey(
+            AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER + 
".secret-access-key"));
+    
assertFalse(icebergProps.containsKey(IcebergConstants.ICEBERG_S3_ACCESS_KEY_ID));
+    
assertFalse(icebergProps.containsKey(IcebergConstants.ICEBERG_S3_SECRET_ACCESS_KEY));
+
+    config.put(GlueConstants.AWS_ACCESS_KEY_ID, "");
+    config.put(GlueConstants.AWS_SECRET_ACCESS_KEY, " ");
+    icebergProps = 
GlueIcebergTableHelper.buildIcebergCatalogProperties(config);
+    
assertFalse(icebergProps.containsKey(AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER));
+    assertFalse(
+        icebergProps.containsKey(
+            AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER + 
".access-key-id"));
+    assertFalse(
+        icebergProps.containsKey(
+            AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER + 
".secret-access-key"));
+    
assertFalse(icebergProps.containsKey(IcebergConstants.ICEBERG_S3_ACCESS_KEY_ID));
+    
assertFalse(icebergProps.containsKey(IcebergConstants.ICEBERG_S3_SECRET_ACCESS_KEY));
+  }
+
+  @Test
+  void testBuildIcebergCatalogPropertiesWithStaticCredentials() {
+    Map<String, String> config = new HashMap<>();
+    config.put(GlueConstants.AWS_REGION, "us-east-1");
+    config.put(GlueConstants.WAREHOUSE, "s3://test-bucket/warehouse");
+    config.put(GlueConstants.AWS_ACCESS_KEY_ID, "test-access-key");
+    config.put(GlueConstants.AWS_SECRET_ACCESS_KEY, "test-secret-key");
+
+    Map<String, String> icebergProps = 
GlueIcebergTableHelper.buildIcebergCatalogProperties(config);
+    assertEquals(
+        GravitinoGlueCredentialsProvider.class.getName(),
+        icebergProps.get(AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER));
+    assertEquals(
+        "test-access-key",
+        icebergProps.get(AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER + 
".access-key-id"));
+    assertEquals(
+        "test-secret-key",
+        icebergProps.get(AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER + 
".secret-access-key"));
+    assertEquals("test-access-key", 
icebergProps.get(IcebergConstants.ICEBERG_S3_ACCESS_KEY_ID));
+    assertEquals(
+        "test-secret-key", 
icebergProps.get(IcebergConstants.ICEBERG_S3_SECRET_ACCESS_KEY));
+  }
+
+  @Test
+  void testBuildIcebergCatalogPropertiesWithOnlyAccessKey() {
+    Map<String, String> config = new HashMap<>();
+    config.put(GlueConstants.AWS_REGION, "us-east-1");
+    config.put(GlueConstants.WAREHOUSE, "s3://test-bucket/warehouse");
+    config.put(GlueConstants.AWS_ACCESS_KEY_ID, "test-access-key");
+
+    assertEquals(
+        "Both 'aws-access-key-id' and 'aws-secret-access-key' must be set 
together. Either provide both keys for static authentication, or omit both to 
use the default credential chain.",
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> 
GlueIcebergTableHelper.buildIcebergCatalogProperties(config))
+            .getMessage());
+  }
+
+  @Test
+  void testBuildIcebergCatalogPropertiesWithOnlySecretKey() {
+    Map<String, String> config = new HashMap<>();
+    config.put(GlueConstants.AWS_REGION, "us-east-1");
+    config.put(GlueConstants.WAREHOUSE, "s3://test-bucket/warehouse");
+    config.put(GlueConstants.AWS_SECRET_ACCESS_KEY, "test-secret-key");
+
+    assertEquals(
+        "Both 'aws-access-key-id' and 'aws-secret-access-key' must be set 
together. Either provide both keys for static authentication, or omit both to 
use the default credential chain.",
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> 
GlueIcebergTableHelper.buildIcebergCatalogProperties(config))
+            .getMessage());
+  }
 }

Reply via email to