From dd642d779c136e5ac82d994cfde01d69abd16c59 Mon Sep 17 00:00:00 2001 From: Star Poon Date: Mon, 15 Apr 2024 23:28:39 +0900 Subject: [PATCH] Add test for authorization --- .../ha/security/TestAuthorization.java | 114 ++++++++++++++++++ .../test/resources/auth/auth-test-config.yml | 50 ++++++++ 2 files changed, 164 insertions(+) create mode 100644 gateway-ha/src/test/java/io/trino/gateway/ha/security/TestAuthorization.java create mode 100644 gateway-ha/src/test/resources/auth/auth-test-config.yml diff --git a/gateway-ha/src/test/java/io/trino/gateway/ha/security/TestAuthorization.java b/gateway-ha/src/test/java/io/trino/gateway/ha/security/TestAuthorization.java new file mode 100644 index 000000000..e683349c9 --- /dev/null +++ b/gateway-ha/src/test/java/io/trino/gateway/ha/security/TestAuthorization.java @@ -0,0 +1,114 @@ +/* + * Licensed 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 io.trino.gateway.ha.security; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.google.common.collect.ImmutableList; +import io.trino.gateway.ha.HaGatewayLauncher; +import io.trino.gateway.ha.HaGatewayTestUtils; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestInstance(Lifecycle.PER_CLASS) +public class TestAuthorization +{ + private static final OkHttpClient httpClient = new OkHttpClient(); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + int routerPort = 22000 + (int) (Math.random() * 1000); + + @BeforeAll + public void setup() + throws Exception + { + HaGatewayTestUtils.TestConfig testConfig = HaGatewayTestUtils.buildGatewayConfigAndSeedDb(routerPort, "auth/auth-test-config.yml"); + String[] args = {"server", testConfig.configFilePath()}; + HaGatewayLauncher.main(args); + } + + @Test + public void testUnauthorized() + throws IOException + { + try (Response response = makeRequest(Optional.empty())) { + assertThat(response.code()).isBetween(400, 499); + } + } + + @Test + public void testBadCredentials() + throws IOException + { + try (Response response = makeRequest(Optional.of("unknown:unknown"))) { + assertThat(response.code()).isBetween(400, 499); + } + } + + @Test + public void testGoodCredentials() + throws IOException + { + List adminRoleList = getRoles("admin1:admin1_password"); + assertThat(adminRoleList).containsAll(ImmutableList.of("ADMIN", "USER")); + + List userRoleList = getRoles("user1:password_user1"); + assertThat(userRoleList).containsAll(ImmutableList.of("USER", "API")); + } + + private List getRoles(String credentials) + throws IOException + { + try (Response response = makeRequest(Optional.of(credentials))) { + assertThat(response.code()).isEqualTo(200); + + JsonNode roles = objectMapper.readTree(response.body().string()).get("data").get("roles"); + assertThat(roles.isArray()).isTrue(); + + ObjectReader reader = objectMapper.readerFor(new TypeReference>() {}); + return reader.readValue(roles.toString()); + } + } + + private Response makeRequest(Optional credentials) + throws IOException + { + RequestBody emptyRequestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), ""); + Request.Builder builder = new Request.Builder() + .url("http://localhost:" + routerPort + "/userinfo") + .post(emptyRequestBody); + if (credentials.isPresent()) { + String encodedCredentials = "Basic " + Base64.getEncoder().encodeToString(credentials.orElseThrow().getBytes(StandardCharsets.ISO_8859_1)); + credentials.ifPresent(s -> builder.addHeader("Authorization", encodedCredentials)); + } + return httpClient.newCall(builder.build()).execute(); + } +} diff --git a/gateway-ha/src/test/resources/auth/auth-test-config.yml b/gateway-ha/src/test/resources/auth/auth-test-config.yml new file mode 100644 index 000000000..e3efbe23e --- /dev/null +++ b/gateway-ha/src/test/resources/auth/auth-test-config.yml @@ -0,0 +1,50 @@ +requestRouter: + port: REQUEST_ROUTER_PORT + name: testTrinoRouter + historySize: 1000 + +server: + applicationConnectors: + - type: http + port: APPLICATION_CONNECTOR_PORT + adminConnectors: + - type: http + port: ADMIN_CONNECTOR_PORT + +dataStore: + jdbcUrl: jdbc:h2:DB_FILE_PATH + user: sa + password: sa + driver: org.h2.Driver + +modules: + - io.trino.gateway.ha.module.HaGatewayProviderModule + +managedApps: + - io.trino.gateway.ha.GatewayManagedApp + +extraWhitelistPaths: + - "/v1/custom" + +logging: + type: external + +authorization: + admin: .*FOO.* + user: .*BAR.* + api: .*BAZ.* + +presetUsers: + admin1: + password: admin1_password + privileges: FOO_BAR + user1: + password: password_user1 + privileges: BAR_BAZ + +authentication: + defaultType: "form" + form: + selfSignKeyPair: + privateKeyRsa: src/test/resources/auth/test_private_key.pem + publicKeyRsa: src/test/resources/auth/test_public_key.pem