Skip to content

Commit fb30a53

Browse files
committed
handle null identity, refactor tests
1 parent f589967 commit fb30a53

File tree

4 files changed

+17
-60
lines changed

4 files changed

+17
-60
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ request adding CHANGELOG notes for breaking (!) changes and possibly other secti
5757
- Added `--no-sts` flag to CLI to support S3-compatible storage systems that do not have Security Token Service available.
5858
- Support credential vending for federated catalogs. `ALLOW_FEDERATED_CATALOGS_CREDENTIAL_VENDING` (default: true) was added to toggle this feature.
5959
- Enhanced catalog federation with SigV4 authentication support, additional authentication types for credential vending, and location-based access restrictions to block credential vending for remote tables outside allowed location lists.
60+
- Added `topologySpreadConstraints` support in Helm chart.
6061
- Added support for including principal name in subscoped credentials. `INCLUDE_PRINCIPAL_NAME_IN_SUBSCOPED_CREDENTIAL` (default: false) can be used to toggle this feature. If enabled, cached credentials issued to one principal will no longer be available for others.
6162

6263
### Changes

polaris-core/src/test/java/org/apache/polaris/core/storage/cache/StorageCredentialCacheTest.java

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,7 @@ public void testCacheHit() {
161161
Assertions.assertThat(storageCredentialCache.getEstimatedSize()).isEqualTo(1);
162162
}
163163

164-
@Test
165-
public void testCacheMissForAnotherPrincipal() {
166-
164+
private void testCacheForAnotherPrincipal(boolean hitExpected) {
167165
List<ScopedCredentialsResult> mockedScopedCreds =
168166
getFakeScopedCreds(3, /* expireSoon= */ false);
169167
Mockito.when(
@@ -196,7 +194,6 @@ public void testCacheMissForAnotherPrincipal() {
196194
Optional.empty());
197195
Assertions.assertThat(storageCredentialCache.getEstimatedSize()).isEqualTo(1);
198196

199-
// subscope for the same entity and same allowed locations, will hit the cache
200197
storageCredentialCache.getOrGenerateSubScopeCreds(
201198
storageCredentialsVendor,
202199
polarisEntity,
@@ -205,11 +202,16 @@ public void testCacheMissForAnotherPrincipal() {
205202
Set.of("s3://bucket3/path", "s3://bucket4/path"),
206203
anotherPolarisPrincipal,
207204
Optional.empty());
208-
Assertions.assertThat(storageCredentialCache.getEstimatedSize()).isEqualTo(1);
205+
Assertions.assertThat(storageCredentialCache.getEstimatedSize()).isEqualTo(hitExpected ? 1 : 2);
209206
}
210207

211208
@Test
212209
public void testCacheHitForAnotherPrincipal() {
210+
testCacheForAnotherPrincipal(true);
211+
}
212+
213+
@Test
214+
public void testCacheMissForAnotherPrincipal() {
213215
Mockito.when(storageCredentialsVendor.getRealmConfig())
214216
.thenReturn(
215217
new RealmConfigImpl(
@@ -227,48 +229,7 @@ public String getConfiguration(@Nonnull RealmContext ctx, String configName) {
227229
},
228230
() -> "realm"));
229231

230-
List<ScopedCredentialsResult> mockedScopedCreds =
231-
getFakeScopedCreds(3, /* expireSoon= */ false);
232-
Mockito.when(
233-
storageCredentialsVendor.getSubscopedCredsForEntity(
234-
Mockito.any(),
235-
Mockito.anyBoolean(),
236-
Mockito.anySet(),
237-
Mockito.anySet(),
238-
Mockito.any(),
239-
Mockito.any()))
240-
.thenReturn(mockedScopedCreds.get(0))
241-
.thenReturn(mockedScopedCreds.get(1))
242-
.thenReturn(mockedScopedCreds.get(1));
243-
PolarisBaseEntity baseEntity =
244-
new PolarisBaseEntity(
245-
1, 2, PolarisEntityType.CATALOG, PolarisEntitySubType.ICEBERG_TABLE, 0, "name");
246-
PolarisEntity polarisEntity = new PolarisEntity(baseEntity);
247-
PolarisPrincipal polarisPrincipal = PolarisPrincipal.of("principal", Map.of(), Set.of());
248-
PolarisPrincipal anotherPolarisPrincipal =
249-
PolarisPrincipal.of("anotherPrincipal", Map.of(), Set.of());
250-
251-
// add an item to the cache
252-
storageCredentialCache.getOrGenerateSubScopeCreds(
253-
storageCredentialsVendor,
254-
polarisEntity,
255-
true,
256-
Set.of("s3://bucket1/path", "s3://bucket2/path"),
257-
Set.of("s3://bucket3/path", "s3://bucket4/path"),
258-
polarisPrincipal,
259-
Optional.empty());
260-
Assertions.assertThat(storageCredentialCache.getEstimatedSize()).isEqualTo(1);
261-
262-
// subscope for the same entity and same allowed locations, will hit the cache
263-
storageCredentialCache.getOrGenerateSubScopeCreds(
264-
storageCredentialsVendor,
265-
polarisEntity,
266-
true,
267-
Set.of("s3://bucket1/path", "s3://bucket2/path"),
268-
Set.of("s3://bucket3/path", "s3://bucket4/path"),
269-
anotherPolarisPrincipal,
270-
Optional.empty());
271-
Assertions.assertThat(storageCredentialCache.getEstimatedSize()).isEqualTo(2);
232+
testCacheForAnotherPrincipal(false);
272233
}
273234

274235
@RepeatedTest(10)

polaris-core/src/test/java/org/apache/polaris/service/storage/aws/AwsCredentialsStorageIntegrationTest.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,10 @@ public void testGetSubscopedCreds(String scheme) {
140140
"/namespace/table/credentials");
141141
}
142142

143+
// uses different realm config with INCLUDE_PRINCIPAL_NAME_IN_SUBSCOPED_CREDENTIAL set to true
144+
// tests that the resulting role session name includes principal name
143145
@Test
144-
public void testGetSubscopedCredsWithNameInclude() {
146+
public void testGetSubscopedCredsRoleSessionNameWithPrincipalIncluded() {
145147
StsClient stsClient = Mockito.mock(StsClient.class);
146148
String roleARN = "arn:aws:iam::012345678901:role/jdoe";
147149
String externalId = "externalId";
@@ -173,18 +175,6 @@ public void testGetSubscopedCredsWithNameInclude() {
173175
Set.of(warehouseDir + "/namespace/table"),
174176
POLARIS_PRINCIPAL,
175177
Optional.of("/namespace/table/credentials"));
176-
assertThat(storageAccessConfig.credentials())
177-
.isNotEmpty()
178-
.containsEntry(StorageAccessProperty.AWS_TOKEN.getPropertyName(), "sess")
179-
.containsEntry(StorageAccessProperty.AWS_KEY_ID.getPropertyName(), "accessKey")
180-
.containsEntry(StorageAccessProperty.AWS_SECRET_KEY.getPropertyName(), "secretKey")
181-
.containsEntry(
182-
StorageAccessProperty.AWS_SESSION_TOKEN_EXPIRES_AT_MS.getPropertyName(),
183-
String.valueOf(EXPIRE_TIME.toEpochMilli()));
184-
assertThat(storageAccessConfig.extraProperties())
185-
.containsEntry(
186-
StorageAccessProperty.AWS_REFRESH_CREDENTIALS_ENDPOINT.getPropertyName(),
187-
"/namespace/table/credentials");
188178
}
189179

190180
@ParameterizedTest

runtime/service/src/main/java/org/apache/polaris/service/context/catalog/PolarisPrincipalHolder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import io.quarkus.security.identity.SecurityIdentity;
2424
import jakarta.enterprise.context.RequestScoped;
2525
import jakarta.enterprise.inject.Produces;
26+
import jakarta.enterprise.inject.UnsatisfiedResolutionException;
2627
import java.security.Principal;
2728
import java.util.concurrent.atomic.AtomicReference;
2829
import org.apache.polaris.core.PolarisDiagnostics;
@@ -46,6 +47,10 @@ public PolarisPrincipal get(
4647
SecurityIdentity identity =
4748
currentIdentityAssociation.getDeferredIdentity().subscribeAsCompletionStage().getNow(null);
4849

50+
if (identity == null) {
51+
throw new UnsatisfiedResolutionException("Not authenticated");
52+
}
53+
4954
Principal userPrincipal = identity.getPrincipal();
5055

5156
diagnostics.check(

0 commit comments

Comments
 (0)