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

dimas 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 1d7836624 Move realm header tests out of the integration tests module 
(#1151)
1d7836624 is described below

commit 1d7836624bf1cbb426f1f4e31c44a3f27ab639ab
Author: Dmitri Bourlatchkov <[email protected]>
AuthorDate: Tue Mar 11 11:02:30 2025 -0400

    Move realm header tests out of the integration tests module (#1151)
    
    * The `integration-test` module was not designed for multi-realm usage,
      therefore assumptions that root credentials from the test environment
      are valid for all realms does not necessarily hold.
    
    * Move the realm header tests to a new class that controls the Polaris
      server by bootstrapping (in-memory) under a specific Quarkus test
      profile.
    
    * Use different client ID/secret values to validate realm header parsing
      This is simpler than listing catalogs because credentials are required
      for all operations anyway.
---
 .../polaris/service/it/env/PolarisClient.java      |   4 +
 .../it/test/PolarisApplicationIntegrationTest.java |  63 -----------
 .../service/quarkus/admin/RealmHeaderTest.java     | 121 +++++++++++++++++++++
 3 files changed, 125 insertions(+), 63 deletions(-)

diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/env/PolarisClient.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/env/PolarisClient.java
index b4fce998e..163c217c2 100644
--- 
a/integration-tests/src/main/java/org/apache/polaris/service/it/env/PolarisClient.java
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/env/PolarisClient.java
@@ -102,6 +102,10 @@ public final class PolarisClient implements AutoCloseable {
         client, endpoints, obtainToken(credentials), 
endpoints.catalogApiEndpoint());
   }
 
+  public CatalogApi catalogApiPlain() {
+    return new CatalogApi(client, endpoints, null, 
endpoints.catalogApiEndpoint());
+  }
+
   /**
    * Requests an access token from the Polaris server for the client ID/secret 
pair that is part of
    * the given principal data object.
diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisApplicationIntegrationTest.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisApplicationIntegrationTest.java
index 48dbce059..638e4b582 100644
--- 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisApplicationIntegrationTest.java
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisApplicationIntegrationTest.java
@@ -27,7 +27,6 @@ import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.client.Entity;
 import jakarta.ws.rs.client.Invocation;
 import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Response.Status;
 import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Path;
@@ -57,14 +56,12 @@ import org.apache.iceberg.hadoop.HadoopFileIO;
 import org.apache.iceberg.io.ResolvingFileIO;
 import org.apache.iceberg.rest.RESTSessionCatalog;
 import org.apache.iceberg.rest.auth.OAuth2Properties;
-import org.apache.iceberg.rest.responses.ErrorResponse;
 import org.apache.iceberg.types.Types;
 import org.apache.iceberg.util.EnvironmentUtil;
 import org.apache.polaris.core.admin.model.AwsStorageConfigInfo;
 import org.apache.polaris.core.admin.model.Catalog;
 import org.apache.polaris.core.admin.model.CatalogProperties;
 import org.apache.polaris.core.admin.model.CatalogRole;
-import org.apache.polaris.core.admin.model.Catalogs;
 import org.apache.polaris.core.admin.model.ExternalCatalog;
 import org.apache.polaris.core.admin.model.FileStorageConfigInfo;
 import org.apache.polaris.core.admin.model.PolarisCatalog;
@@ -88,8 +85,6 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInfo;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.jupiter.api.io.TempDir;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
 
 /**
  * @implSpec This test expects the server to be configured with the following 
features configured:
@@ -651,62 +646,4 @@ public class PolarisApplicationIntegrationTest {
               });
     }
   }
-
-  @Test
-  public void testNoRealmHeader() {
-    try (Response response =
-        managementApi
-            .request(
-                "v1/catalogs", Map.of(), Map.of(), Map.of("Authorization", 
"Bearer " + authToken))
-            .get()) {
-      assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode());
-      Catalogs roles = response.readEntity(Catalogs.class);
-      
assertThat(roles.getCatalogs()).extracting(Catalog::getName).contains(internalCatalogName);
-    }
-  }
-
-  @ParameterizedTest
-  @ValueSource(strings = {"POLARIS", "OTHER"})
-  public void testRealmHeaderValid(String realmId) {
-    String catalogName = client.newEntityName("testRealmHeaderValid" + 
realmId);
-    createCatalog(catalogName, Catalog.TypeEnum.INTERNAL, principalRoleName);
-    try (Response response =
-        managementApi
-            .request(
-                "v1/catalogs",
-                Map.of(),
-                Map.of(),
-                Map.of(
-                    "Authorization", "Bearer " + authToken, 
endpoints.realmHeaderName(), realmId))
-            .get()) {
-      assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode());
-      Catalogs catalogsList = response.readEntity(Catalogs.class);
-      if ("POLARIS".equals(realmId)) {
-        
assertThat(catalogsList.getCatalogs()).extracting(Catalog::getName).contains(catalogName);
-      } else {
-        assertThat(catalogsList.getCatalogs()).isEmpty();
-      }
-    }
-  }
-
-  @Test
-  public void testRealmHeaderInvalid() {
-    try (Response response =
-        managementApi
-            .request(
-                "v1/catalogs",
-                Map.of(),
-                Map.of(),
-                Map.of(
-                    "Authorization", "Bearer " + authToken, 
endpoints.realmHeaderName(), "INVALID"))
-            .get()) {
-      
assertThat(response.getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode());
-      assertThat(response.readEntity(ErrorResponse.class))
-          .extracting(ErrorResponse::code, ErrorResponse::type, 
ErrorResponse::message)
-          .containsExactly(
-              Status.NOT_FOUND.getStatusCode(),
-              "UnresolvableRealmContextException",
-              "Unknown realm: INVALID");
-    }
-  }
 }
diff --git 
a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/RealmHeaderTest.java
 
b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/RealmHeaderTest.java
new file mode 100644
index 000000000..f062f9263
--- /dev/null
+++ 
b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/RealmHeaderTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.service.quarkus.admin;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.quarkus.test.junit.TestProfile;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.Response;
+import java.net.URI;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.rest.responses.ErrorResponse;
+import org.apache.polaris.service.it.env.PolarisApiEndpoints;
+import org.apache.polaris.service.it.env.PolarisClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RealmHeaderTest.Profile.class)
+public class RealmHeaderTest {
+  public static class Profile implements QuarkusTestProfile {
+    @Override
+    public Map<String, String> getConfigOverrides() {
+      return Map.of(
+          "polaris.realm-context.header-name",
+          REALM_HEADER,
+          "polaris.realm-context.realms",
+          "realm1,realm2",
+          "polaris.bootstrap.credentials",
+          "realm1,client1,secret1;realm2,client2,secret2");
+    }
+  }
+
+  private static final String REALM_HEADER = "test-header-r123";
+
+  private static final URI baseUri =
+      URI.create(
+          "http://localhost:";
+              + Objects.requireNonNull(
+                  Integer.getInteger("quarkus.http.test-port"),
+                  "System property not set correctly: 
quarkus.http.test-port"));
+
+  private Response request(String realm, String header, String clientId, 
String secret) {
+    try (PolarisClient client =
+        PolarisClient.polarisClient(new PolarisApiEndpoints(baseUri, realm, 
header))) {
+      return client
+          .catalogApiPlain()
+          .request("v1/oauth/tokens")
+          .post(
+              Entity.form(
+                  new MultivaluedHashMap<>(
+                      Map.of(
+                          "grant_type",
+                          "client_credentials",
+                          "scope",
+                          "PRINCIPAL_ROLE:ALL",
+                          "client_id",
+                          clientId,
+                          "client_secret",
+                          secret))));
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Test
+  public void testInvalidRealmHeaderValue() {
+    try (Response response = request("INVALID", REALM_HEADER, "dummy", 
"dummy")) {
+      
assertThat(response.getStatus()).isEqualTo(Response.Status.NOT_FOUND.getStatusCode());
+      assertThat(response.readEntity(ErrorResponse.class))
+          .extracting(ErrorResponse::code, ErrorResponse::type, 
ErrorResponse::message)
+          .containsExactly(
+              Response.Status.NOT_FOUND.getStatusCode(),
+              "UnresolvableRealmContextException",
+              "Unknown realm: INVALID");
+    }
+  }
+
+  @Test
+  public void testNoRealmHeader() {
+    try (Response response = request("fake-realm", "irrelevant-header", 
"client2", "secret2")) {
+      // The default realm is "realm2" so the second pair of secrets is not 
valid without
+      // an explicit header
+      
assertThat(response.getStatus()).isEqualTo(Response.Status.UNAUTHORIZED.getStatusCode());
+    }
+  }
+
+  @Test
+  public void testDefaultRealm() {
+    try (Response response = request("fake-realm", "irrelevant-header", 
"client1", "secret1")) {
+      // The default realm is "realm1", now credentials match
+      
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
+    }
+  }
+
+  @Test
+  public void testValidRealmHeaderDefaultRealm() {
+    try (Response response = request("realm2", REALM_HEADER, "client2", 
"secret2")) {
+      
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
+    }
+  }
+}

Reply via email to