This is an automated email from the ASF dual-hosted git repository.
snazy 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 29ccdd179 STS roleArn: enable 3rd party STS services (#3619)
29ccdd179 is described below
commit 29ccdd179b23b470bf673e94aefd730fba2c09d0
Author: Robert Stupp <[email protected]>
AuthorDate: Tue Feb 3 11:38:04 2026 +0100
STS roleArn: enable 3rd party STS services (#3619)
Certain non-AWS STS service implementations use role ARNs that look quite
different from AWS ones.
This change shall enable those STS implementations.
Example role ARNs that currently fail:
* `urn:ecs:sts::s3:assumed-role/s3assumeRole/user1-105-temp`
* `urn:sgws:identity::12345:group/foo-bar-abcdef`
Related issue #2743
---
CHANGELOG.md | 2 ++
.../aws/AwsCredentialsStorageIntegration.java | 26 +++++++++++-----------
.../storage/aws/AwsStorageConfigurationInfo.java | 4 +---
.../aws/AwsStorageConfigurationInfoTest.java | 26 ++++++++++++++++++----
4 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02ffef1ed..34ef7108a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -68,6 +68,8 @@ request adding CHANGELOG notes for breaking (!) changes and
possibly other secti
### Fixes
+- Enable non-AWS STS role ARNs
+
### Commits
## [1.3.0-incubating]
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsCredentialsStorageIntegration.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsCredentialsStorageIntegration.java
index 3b43c5beb..0fe618284 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsCredentialsStorageIntegration.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsCredentialsStorageIntegration.java
@@ -93,7 +93,6 @@ public class AwsCredentialsStorageIntegration
realmConfig.getConfig(STORAGE_CREDENTIAL_DURATION_SECONDS);
AwsStorageConfigurationInfo storageConfig = config();
String region = storageConfig.getRegion();
- String accountId = storageConfig.getAwsAccountId();
StorageAccessConfig.Builder accessConfig = StorageAccessConfig.builder();
boolean includePrincipalNameInSubscopedCredential =
@@ -120,8 +119,7 @@ public class AwsCredentialsStorageIntegration
allowListOperation,
allowedReadLocations,
allowedWriteLocations,
- region,
- accountId)
+ region)
.toJson())
.durationSeconds(storageCredentialDurationSeconds);
@@ -215,8 +213,7 @@ public class AwsCredentialsStorageIntegration
boolean allowList,
Set<String> readLocations,
Set<String> writeLocations,
- String region,
- String accountId) {
+ String region) {
IamPolicy.Builder policyBuilder = IamPolicy.builder();
IamStatement.Builder allowGetObjectStatementBuilder =
IamStatement.builder()
@@ -261,7 +258,8 @@ public class AwsCredentialsStorageIntegration
.addResource(key));
});
- if (!writeLocations.isEmpty()) {
+ boolean canWrite = !writeLocations.isEmpty();
+ if (canWrite) {
IamStatement.Builder allowPutObjectStatementBuilder =
IamStatement.builder()
.effect(IamEffect.ALLOW)
@@ -275,13 +273,15 @@ public class AwsCredentialsStorageIntegration
arnPrefix +
StorageUtil.concatFilePrefixes(parseS3Path(uri), "*", "/")));
});
policyBuilder.addStatement(allowPutObjectStatementBuilder.build());
- if (shouldUseKms(storageConfigurationInfo)) {
- addKmsKeyPolicy(currentKmsKey, allowedKmsKeys, policyBuilder, true,
region, accountId);
- }
- } else {
- if (shouldUseKms(storageConfigurationInfo)) {
- addKmsKeyPolicy(currentKmsKey, allowedKmsKeys, policyBuilder, false,
region, accountId);
- }
+ }
+ if (shouldUseKms(storageConfigurationInfo)) {
+ addKmsKeyPolicy(
+ currentKmsKey,
+ allowedKmsKeys,
+ policyBuilder,
+ canWrite,
+ region,
+ storageConfigurationInfo.getAwsAccountId());
}
if (!bucketListStatementBuilder.isEmpty()) {
bucketListStatementBuilder
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 067140a59..1f28b5ef3 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
@@ -45,9 +45,7 @@ public abstract class AwsStorageConfigurationInfo extends
PolarisStorageConfigur
return ImmutableAwsStorageConfigurationInfo.builder();
}
- // 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/.+$";
+ @JsonIgnore public static final String ROLE_ARN_PATTERN =
"^.+:(.*):.+:.*:(.*):.+$";
private static final Pattern ROLE_ARN_PATTERN_COMPILED =
Pattern.compile(ROLE_ARN_PATTERN);
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
index f3fb3b348..4ea5eda6d 100644
---
a/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
@@ -22,8 +22,12 @@ package org.apache.polaris.core.storage.aws;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.URI;
+import java.util.stream.Stream;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
public class AwsStorageConfigurationInfoTest {
@@ -134,12 +138,14 @@ public class AwsStorageConfigurationInfoTest {
assertThat(newBuilder().kmsUnavailable(true).build().getKmsUnavailable()).isTrue();
}
- @Test
- public void testRoleArnParsing() {
+ @ParameterizedTest
+ @MethodSource
+ public void testRoleArnParsing(
+ String roleArn, String expectedAccountId, String expectedPartition) {
AwsStorageConfigurationInfo awsConfig =
AwsStorageConfigurationInfo.builder()
.addAllowedLocation("s3://bucket/path/to/warehouse")
- .roleARN("arn:aws:iam::012345678901:role/jdoe")
+ .roleARN(roleArn)
.region("us-east-2")
.build();
@@ -148,6 +154,18 @@ public class AwsStorageConfigurationInfoTest {
AwsStorageConfigurationInfo::getRoleARN,
AwsStorageConfigurationInfo::getAwsAccountId,
AwsStorageConfigurationInfo::getAwsPartition)
- .containsExactly("arn:aws:iam::012345678901:role/jdoe",
"012345678901", "aws");
+ .containsExactly(roleArn, expectedAccountId, expectedPartition);
+ }
+
+ static Stream<Arguments> testRoleArnParsing() {
+ return Stream.of(
+ Arguments.of("arn:aws:iam::012345678901:role/jdoe", "012345678901",
"aws"),
+ Arguments.of("arn:aws-us-gov:iam::012345678901:role/jdoe",
"012345678901", "aws-us-gov"),
+ Arguments.of("arn:aws-cn:iam::012345678901:role/jdoe", "012345678901",
"aws-cn"),
+ // Following are only there to have test coverage for non-AWS
role-ARNs/URNs. ARN specific
+ // parts are irrelevant for those URNs.
+ Arguments.of(
+ "urn:ecs:sts::namespace:assumed-role/s3assumeRole/user1-105-temp",
"namespace", "ecs"),
+ Arguments.of("urn:sgws:identity::12345:group/foo-bar-abcdef", "12345",
"sgws"));
}
}