Skip to content

Commit 083f99e

Browse files
committed
test(auth): mint per-realm token in RateLimiterFilterTest
Access tokens are bound to per-realm principal secret hashes. Reusing a POLARIS admin token against POLARIS2 correctly returns 401. Bootstrap both realms with known credentials and obtain a POLARIS2 token for the cross-realm rate-limit isolation assertion.
1 parent d851be7 commit 083f99e

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

runtime/service/src/test/java/org/apache/polaris/service/ratelimiter/RateLimiterFilterTest.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@
3030
import jakarta.inject.Inject;
3131
import jakarta.ws.rs.client.Client;
3232
import jakarta.ws.rs.client.ClientBuilder;
33+
import jakarta.ws.rs.client.Entity;
3334
import jakarta.ws.rs.core.MediaType;
35+
import jakarta.ws.rs.core.MultivaluedHashMap;
3436
import jakarta.ws.rs.core.Response;
3537
import jakarta.ws.rs.core.Response.Status;
3638
import java.util.Map;
3739
import java.util.Set;
3840
import java.util.function.Consumer;
3941
import org.apache.iceberg.rest.responses.ErrorResponse;
4042
import org.apache.iceberg.rest.responses.ErrorResponseParser;
43+
import org.apache.iceberg.rest.responses.OAuthTokenResponse;
4144
import org.apache.polaris.service.events.EventAttributes;
4245
import org.apache.polaris.service.events.PolarisEvent;
4346
import org.apache.polaris.service.events.PolarisEventType;
@@ -80,6 +83,11 @@ public Map<String, String> getConfigOverrides() {
8083
.put("polaris.rate-limiter.token-bucket.type", "default")
8184
.put("polaris.metrics.tags.environment", "prod")
8285
.put("polaris.realm-context.realms", "POLARIS,POLARIS2")
86+
// Bootstrapping both realms with known credentials so each realm can mint its own
87+
// access token. Tokens are bound to per-realm secret hashes and cannot be shared.
88+
.put(
89+
"polaris.bootstrap.credentials",
90+
"POLARIS,test-admin,test-secret;POLARIS2,test-admin2,test-secret2")
8391
.put("polaris.metrics.realm-id-tag.enable-in-api-metrics", "true")
8492
.put("polaris.metrics.realm-id-tag.enable-in-http-metrics", "true")
8593
.put("polaris.authentication.token-broker.type", "symmetric-key")
@@ -138,10 +146,14 @@ public void testRateLimiter() {
138146
requestAsserter.accept(Status.TOO_MANY_REQUESTS);
139147
}
140148

141-
// Ensure that a different realm identifier gets a separate limit
149+
// Ensure that a different realm identifier gets a separate limit. Access tokens are
150+
// bound to per-realm principal secrets, so mint a token for POLARIS2 rather than reusing
151+
// the POLARIS admin token (which would correctly return 401 after credentials binding).
142152
MockRateLimiter.allowProceed = true;
153+
String polaris2Token =
154+
obtainAccessTokenForRealm(polarisEndpoints, "POLARIS2", "test-admin2", "test-secret2");
143155
Consumer<Status> requestAsserter2 =
144-
constructRequestAsserter(polarisEndpoints, adminToken, "POLARIS2");
156+
constructRequestAsserter(polarisEndpoints, polaris2Token, "POLARIS2");
145157
requestAsserter2.accept(Status.OK);
146158
}
147159

@@ -243,4 +255,27 @@ private static Consumer<Status> constructRequestAsserter(
243255
}
244256
};
245257
}
258+
259+
/**
260+
* Mints an access token in the given realm using client credentials. Realm must be bootstrapped
261+
* with those credentials (see {@link Profile}).
262+
*/
263+
private static String obtainAccessTokenForRealm(
264+
PolarisApiEndpoints endpoints, String realm, String clientId, String clientSecret) {
265+
MultivaluedHashMap<String, String> form = new MultivaluedHashMap<>();
266+
form.add("grant_type", "client_credentials");
267+
form.add("client_id", clientId);
268+
form.add("client_secret", clientSecret);
269+
form.add("scope", "PRINCIPAL_ROLE:ALL");
270+
try (Client httpClient = ClientBuilder.newBuilder().build();
271+
Response response =
272+
httpClient
273+
.target(String.format("%s/v1/oauth/tokens", endpoints.catalogApiEndpoint()))
274+
.request(MediaType.APPLICATION_JSON_TYPE)
275+
.header("Polaris-Realm", realm)
276+
.post(Entity.form(form))) {
277+
assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode());
278+
return response.readEntity(OAuthTokenResponse.class).token();
279+
}
280+
}
246281
}

0 commit comments

Comments
 (0)