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

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


The following commit(s) were added to refs/heads/main by this push:
     new 034959e23 Core: made the ARN role regex more generic (#3005)
034959e23 is described below

commit 034959e23059e19da455320eabc34af6814b1e43
Author: cccs-cat001 <[email protected]>
AuthorDate: Fri Nov 7 15:33:09 2025 -0500

    Core: made the ARN role regex more generic (#3005)
---
 CHANGELOG.md                                       |  1 +
 .../storage/aws/AwsStorageConfigurationInfo.java   |  6 ++--
 .../polaris/service/entity/CatalogEntityTest.java  | 33 ++++++++++++++++++++--
 3 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a4d0c891..0e6fb7e78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,6 +53,7 @@ request adding CHANGELOG notes for breaking (!) changes and 
possibly other secti
 ### Changes
 
 - `client.region` is no longer considered a "credential" property (related to 
Iceberg REST Catalog API).
+- Relaxed the requirements for S3 storage's ARN to allow Polaris to connect to 
more non-AWS S3 storage appliances. 
 
 ### Deprecations
 
diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
index b3d7d6079..69c669222 100644
--- 
a/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
@@ -44,9 +44,9 @@ public abstract class AwsStorageConfigurationInfo extends 
PolarisStorageConfigur
     return ImmutableAwsStorageConfigurationInfo.builder();
   }
 
-  // Technically, it should be 
^arn:(aws|aws-cn|aws-us-gov):iam::(\d{12}):role/.+$,
-  @JsonIgnore
-  public static final String ROLE_ARN_PATTERN = 
"^arn:(aws|aws-us-gov):iam::(\\d{12}):role/.+$";
+  // Technically, it should be 
^arn:(aws|aws-cn|aws-us-gov):iam::(\d{12}):role/.+$, but we've
+  // generalized it to support non-aws S3 implementations
+  @JsonIgnore public static final String ROLE_ARN_PATTERN = 
"^.+:(.*):iam:.*:(.*):role/.+$";
 
   private static final Pattern ROLE_ARN_PATTERN_COMPILED = 
Pattern.compile(ROLE_ARN_PATTERN);
 
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/entity/CatalogEntityTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/entity/CatalogEntityTest.java
index 47e61f573..5c3c220c8 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/entity/CatalogEntityTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/entity/CatalogEntityTest.java
@@ -255,7 +255,7 @@ public class CatalogEntityTest {
   }
 
   @ParameterizedTest
-  @ValueSource(strings = {"", "arn:aws:iam::0123456:role/jdoe", "aws-cn"})
+  @ValueSource(strings = {"", "arn:aws:iam:0123456:role/jdoe", "aws-cn"})
   public void testInvalidArn(String roleArn) {
     String basedLocation = "s3://externally-owned-bucket";
     AwsStorageConfigInfo awsStorageConfigModel =
@@ -278,13 +278,42 @@ public class CatalogEntityTest {
         switch (roleArn) {
           case "" -> "ARN must not be empty";
           case "aws-cn" -> "AWS China is temporarily not supported";
-          default -> "Invalid role ARN format: arn:aws:iam::0123456:role/jdoe";
+          default -> "Invalid role ARN format: arn:aws:iam:0123456:role/jdoe";
         };
     Assertions.assertThatThrownBy(() -> CatalogEntity.fromCatalog(realmConfig, 
awsCatalog))
         .isInstanceOf(IllegalArgumentException.class)
         .hasMessage(expectedMessage);
   }
 
+  @ParameterizedTest
+  @ValueSource(
+      strings = {
+        "arn:aws:iam::012345678911:role/rollerblade",
+        "test:test:iam:region:accountid:role/rollerblade",
+        "a::iam:::role/rollerblade"
+      })
+  public void testValidArn(String roleArn) {
+    String basedLocation = "s3://externally-owned-bucket";
+    AwsStorageConfigInfo awsStorageConfigModel =
+        AwsStorageConfigInfo.builder()
+            .setRoleArn(roleArn)
+            .setExternalId("externalId")
+            .setStorageType(StorageConfigInfo.StorageTypeEnum.S3)
+            .setAllowedLocations(List.of(basedLocation))
+            .build();
+
+    CatalogProperties prop = new CatalogProperties(basedLocation);
+    Catalog awsCatalog =
+        PolarisCatalog.builder()
+            .setType(Catalog.TypeEnum.INTERNAL)
+            .setName("name")
+            .setProperties(prop)
+            .setStorageConfigInfo(awsStorageConfigModel)
+            .build();
+    Assertions.assertThatNoException()
+        .isThrownBy(() -> CatalogEntity.fromCatalog(realmConfig, awsCatalog));
+  }
+
   @Test
   public void testCatalogTypeDefaultsToInternal() {
     String baseLocation = "s3://test-bucket/path";

Reply via email to