From 6a9256b0a91332b70738c30e2c706d18886e5f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Tue, 7 Dec 2021 09:39:58 +0100 Subject: [PATCH 01/11] Extract identity building to bearer authenticators --- .../security/AbstractBearerAuthenticator.java | 22 +++--------------- .../server/security/jwt/JwtAuthenticator.java | 21 ++++++++++++----- .../security/oauth2/OAuth2Authenticator.java | 23 +++++++++++++------ 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/core/trino-main/src/main/java/io/trino/server/security/AbstractBearerAuthenticator.java b/core/trino-main/src/main/java/io/trino/server/security/AbstractBearerAuthenticator.java index dfcc30519450..611099332534 100644 --- a/core/trino-main/src/main/java/io/trino/server/security/AbstractBearerAuthenticator.java +++ b/core/trino-main/src/main/java/io/trino/server/security/AbstractBearerAuthenticator.java @@ -18,24 +18,15 @@ import javax.ws.rs.container.ContainerRequestContext; -import java.security.Principal; import java.util.List; import java.util.Optional; import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static java.lang.String.format; -import static java.util.Objects.requireNonNull; public abstract class AbstractBearerAuthenticator implements Authenticator { - private final UserMapping userMapping; - - protected AbstractBearerAuthenticator(UserMapping userMapping) - { - this.userMapping = requireNonNull(userMapping, "userMapping is null"); - } - @Override public Identity authenticate(ContainerRequestContext request) throws AuthenticationException @@ -47,15 +38,7 @@ public Identity authenticate(ContainerRequestContext request, String token) throws AuthenticationException { try { - Optional principal = extractPrincipalFromToken(token); - if (principal.isEmpty()) { - throw needAuthentication(request, "Invalid credentials"); - } - - String authenticatedUser = userMapping.mapUser(principal.get().getName()); - return Identity.forUser(authenticatedUser) - .withPrincipal(principal.get()) - .build(); + return createIdentity(token).orElseThrow(() -> needAuthentication(request, "Invalid credentials")); } catch (JwtException | UserMappingException e) { throw needAuthentication(request, e.getMessage()); @@ -88,7 +71,8 @@ public String extractToken(ContainerRequestContext request) return token; } - protected abstract Optional extractPrincipalFromToken(String token); + protected abstract Optional createIdentity(String token) + throws UserMappingException; protected abstract AuthenticationException needAuthentication(ContainerRequestContext request, String message); } diff --git a/core/trino-main/src/main/java/io/trino/server/security/jwt/JwtAuthenticator.java b/core/trino-main/src/main/java/io/trino/server/security/jwt/JwtAuthenticator.java index 1fb38a9b348b..5989470f0384 100644 --- a/core/trino-main/src/main/java/io/trino/server/security/jwt/JwtAuthenticator.java +++ b/core/trino-main/src/main/java/io/trino/server/security/jwt/JwtAuthenticator.java @@ -19,12 +19,14 @@ import io.jsonwebtoken.SigningKeyResolver; import io.trino.server.security.AbstractBearerAuthenticator; import io.trino.server.security.AuthenticationException; +import io.trino.server.security.UserMapping; +import io.trino.server.security.UserMappingException; import io.trino.spi.security.BasicPrincipal; +import io.trino.spi.security.Identity; import javax.inject.Inject; import javax.ws.rs.container.ContainerRequestContext; -import java.security.Principal; import java.util.Optional; import static io.trino.server.security.UserMapping.createUserMapping; @@ -34,11 +36,11 @@ public class JwtAuthenticator { private final JwtParser jwtParser; private final String principalField; + private final UserMapping userMapping; @Inject public JwtAuthenticator(JwtAuthenticatorConfig config, SigningKeyResolver signingKeyResolver) { - super(createUserMapping(config.getUserMappingPattern(), config.getUserMappingFile())); principalField = config.getPrincipalField(); JwtParserBuilder jwtParser = Jwts.parserBuilder() @@ -51,15 +53,22 @@ public JwtAuthenticator(JwtAuthenticatorConfig config, SigningKeyResolver signin jwtParser.requireAudience(config.getRequiredAudience()); } this.jwtParser = jwtParser.build(); + userMapping = createUserMapping(config.getUserMappingPattern(), config.getUserMappingFile()); } @Override - protected Optional extractPrincipalFromToken(String token) + protected Optional createIdentity(String token) + throws UserMappingException { - return Optional.ofNullable(jwtParser.parseClaimsJws(token) + Optional principal = Optional.ofNullable(jwtParser.parseClaimsJws(token) .getBody() - .get(principalField, String.class)) - .map(BasicPrincipal::new); + .get(principalField, String.class)); + if (principal.isEmpty()) { + return Optional.empty(); + } + return Optional.of(Identity.forUser(userMapping.mapUser(principal.get())) + .withPrincipal(new BasicPrincipal(principal.get())) + .build()); } @Override diff --git a/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java b/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java index 0482b9393099..2d076912b729 100644 --- a/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java +++ b/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java @@ -15,13 +15,16 @@ import io.trino.server.security.AbstractBearerAuthenticator; import io.trino.server.security.AuthenticationException; +import io.trino.server.security.UserMapping; +import io.trino.server.security.UserMappingException; import io.trino.spi.security.BasicPrincipal; +import io.trino.spi.security.Identity; import javax.inject.Inject; import javax.ws.rs.container.ContainerRequestContext; import java.net.URI; -import java.security.Principal; +import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -36,23 +39,29 @@ public class OAuth2Authenticator { private final OAuth2Service service; private final String principalField; + private final UserMapping userMapping; @Inject public OAuth2Authenticator(OAuth2Service service, OAuth2Config config) { - super(createUserMapping(config.getUserMappingPattern(), config.getUserMappingFile())); this.service = requireNonNull(service, "service is null"); this.principalField = config.getPrincipalField(); + userMapping = createUserMapping(config.getUserMappingPattern(), config.getUserMappingFile()); } @Override - protected Optional extractPrincipalFromToken(String token) + protected Optional createIdentity(String token) + throws UserMappingException { try { - return service.convertTokenToClaims(token) - .map(claims -> claims.get(principalField)) - .map(String.class::cast) - .map(BasicPrincipal::new); + Optional> claims = service.convertTokenToClaims(token); + if (claims.isEmpty()) { + return Optional.empty(); + } + String principal = (String) claims.get().get(principalField); + return Optional.of(Identity.forUser(userMapping.mapUser(principal)) + .withPrincipal(new BasicPrincipal(principal)) + .build()); } catch (ChallengeFailedException e) { return Optional.empty(); From 576f658551872b18285767aea7bf6a665702723c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Wed, 8 Dec 2021 09:26:06 +0100 Subject: [PATCH 02/11] Assert additional fields from identity --- .../java/io/trino/server/security/TestResourceSecurity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index 55ce3f382052..7bca8ed8f7b5 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -293,18 +293,19 @@ public void testPasswordAuthenticatorUserMapping() // Normally this would result in an impersonation check to the X-Trino-User, but the password // authenticator has a hack to clear X-Trino-User in this case. Request request = new Request.Builder() - .url(getLocation(httpServerInfo.getHttpsUri(), "/username")) + .url(getLocation(httpServerInfo.getHttpsUri(), "/identity")) .addHeader("Authorization", Credentials.basic(TEST_USER_LOGIN, TEST_PASSWORD)) .addHeader("X-Trino-User", TEST_USER_LOGIN) .build(); try (Response response = client.newCall(request).execute()) { assertEquals(response.code(), SC_OK); assertEquals(response.header("user"), TEST_USER); + assertEquals(response.header("principal"), TEST_USER_LOGIN); } } } - @javax.ws.rs.Path("/username") + @javax.ws.rs.Path("/identity") public static class TestResource { private final HttpRequestSessionContextFactory sessionContextFactory; @@ -322,6 +323,7 @@ public javax.ws.rs.core.Response echoToken(@Context HttpServletRequest servletRe Identity identity = sessionContextFactory.extractAuthorizedIdentity(servletRequest, httpHeaders, Optional.empty()); return javax.ws.rs.core.Response.ok() .header("user", identity.getUser()) + .header("principal", identity.getPrincipal().map(Principal::getName).orElse(null)) .build(); } } From 27117b2f9a3387956600b2954a0f703309e9a6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Wed, 8 Dec 2021 09:28:27 +0100 Subject: [PATCH 03/11] Move TestResource --- .../server/security/TestResourceSecurity.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index 7bca8ed8f7b5..bd46cf95f717 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -305,29 +305,6 @@ public void testPasswordAuthenticatorUserMapping() } } - @javax.ws.rs.Path("/identity") - public static class TestResource - { - private final HttpRequestSessionContextFactory sessionContextFactory; - - @Inject - public TestResource(AccessControl accessControl) - { - this.sessionContextFactory = new HttpRequestSessionContextFactory(createTestMetadataManager(), ImmutableSet::of, accessControl); - } - - @ResourceSecurity(AUTHENTICATED_USER) - @GET - public javax.ws.rs.core.Response echoToken(@Context HttpServletRequest servletRequest, @Context HttpHeaders httpHeaders) - { - Identity identity = sessionContextFactory.extractAuthorizedIdentity(servletRequest, httpHeaders, Optional.empty()); - return javax.ws.rs.core.Response.ok() - .header("user", identity.getUser()) - .header("principal", identity.getPrincipal().map(Principal::getName).orElse(null)) - .build(); - } - } - @Test public void testPasswordAuthenticatorWithInsecureHttp() throws Exception @@ -744,6 +721,29 @@ private static String getOauthToken(OkHttpClient client, String url) } } + @javax.ws.rs.Path("/identity") + public static class TestResource + { + private final HttpRequestSessionContextFactory sessionContextFactory; + + @Inject + public TestResource(AccessControl accessControl) + { + this.sessionContextFactory = new HttpRequestSessionContextFactory(createTestMetadataManager(), ImmutableSet::of, accessControl); + } + + @ResourceSecurity(AUTHENTICATED_USER) + @GET + public javax.ws.rs.core.Response echoToken(@Context HttpServletRequest servletRequest, @Context HttpHeaders httpHeaders) + { + Identity identity = sessionContextFactory.extractAuthorizedIdentity(servletRequest, httpHeaders, Optional.empty()); + return javax.ws.rs.core.Response.ok() + .header("user", identity.getUser()) + .header("principal", identity.getPrincipal().map(Principal::getName).orElse(null)) + .build(); + } + } + private void assertInsecureAuthentication(URI baseUri) throws IOException { From 1287cba51e9e10023d32d6508c641664a804938e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Thu, 9 Dec 2021 11:20:16 +0100 Subject: [PATCH 04/11] Extract token server from OAuth2 test --- .../server/security/TestResourceSecurity.java | 230 ++++++++++++------ 1 file changed, 155 insertions(+), 75 deletions(-) diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index bd46cf95f717..e9251ca800fd 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.io.Resources; import com.google.inject.Key; +import com.google.inject.Module; import io.airlift.http.server.HttpServerConfig; import io.airlift.http.server.HttpServerInfo; import io.airlift.http.server.testing.TestingHttpServer; @@ -27,7 +28,6 @@ import io.jsonwebtoken.JwsHeader; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; import io.trino.plugin.base.security.AllowAllSystemAccessControl; import io.trino.security.AccessControl; import io.trino.security.AccessControlManager; @@ -71,7 +71,9 @@ import java.util.Base64; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,7 +89,6 @@ import static io.trino.metadata.MetadataManager.createTestMetadataManager; import static io.trino.server.security.ResourceSecurity.AccessType.AUTHENTICATED_USER; import static io.trino.server.security.oauth2.OAuth2Service.NONCE; -import static io.trino.server.security.oauth2.OAuth2Service.hashNonce; import static io.trino.spi.security.AccessDeniedException.denyImpersonateUser; import static io.trino.spi.security.AccessDeniedException.denyReadSystemInformationAccess; import static io.trino.testing.assertions.Assert.assertEquals; @@ -126,6 +127,7 @@ public class TestResourceSecurity private static final String MANAGEMENT_USER_LOGIN = MANAGEMENT_USER + "@allowed"; private static final String MANAGEMENT_PASSWORD = "management-password"; private static final String HMAC_KEY = Resources.getResource("hmac_key.txt").getPath(); + private static final String JWK_KEY_ID = "test-rsa"; private static final PrivateKey JWK_PRIVATE_KEY; private static final ObjectMapper json = new ObjectMapper(); @@ -495,7 +497,7 @@ public void testJwtWithJwkAuthenticator() String token = Jwts.builder() .signWith(JWK_PRIVATE_KEY) - .setHeaderParam(JwsHeader.KEY_ID, "test-rsa") + .setHeaderParam(JwsHeader.KEY_ID, JWK_KEY_ID) .setSubject("test-user") .setExpiration(Date.from(ZonedDateTime.now().plusMinutes(5).toInstant())) .compact(); @@ -530,67 +532,16 @@ private void verifyOAuth2Authenticator(boolean webUiEnabled, Optional pr .cookieJar(new JavaNetCookieJar(cookieManager)) .build(); - String clientId = "client"; - Date tokenExpiration = Date.from(ZonedDateTime.now().plusMinutes(5).toInstant()); - String issuer = "http://example.com/"; - JwtBuilder accessTokenBuilder = Jwts.builder() - .signWith(JWK_PRIVATE_KEY) - .setHeaderParam(JwsHeader.KEY_ID, "test-rsa") - .setIssuer(issuer) - .setAudience(clientId) - .setExpiration(tokenExpiration); - JwtBuilder idTokenBuilder = Jwts.builder() - .signWith(SignatureAlgorithm.RS256, JWK_PRIVATE_KEY) - .setHeaderParam(JwsHeader.KEY_ID, "test-rsa") - .setIssuer(issuer) - .setAudience(clientId) - .setExpiration(tokenExpiration); - if (principalField.isPresent()) { - accessTokenBuilder.claim(principalField.get(), "test-user"); - idTokenBuilder.claim(principalField.get(), "test-user"); - } - else { - accessTokenBuilder.setSubject("test-user"); - idTokenBuilder.setSubject("test-user"); - } - String accessToken = accessTokenBuilder.compact(); - - TestingHttpServer jwkServer = createTestingJwkServer(); - jwkServer.start(); - try (TestingTrinoServer server = TestingTrinoServer.builder() - .setProperties(ImmutableMap.builder() - .putAll(SECURE_PROPERTIES) - .put("http-server.authentication.type", "oauth2") - .put("web-ui.enabled", String.valueOf(webUiEnabled)) - .put("http-server.authentication.oauth2.issuer", issuer) - .put("http-server.authentication.oauth2.jwks-url", jwkServer.getBaseUrl().toString()) - .put("http-server.authentication.oauth2.state-key", "test-state-key") - .put("http-server.authentication.oauth2.auth-url", issuer) - .put("http-server.authentication.oauth2.token-url", issuer) - .put("http-server.authentication.oauth2.client-id", clientId) - .put("http-server.authentication.oauth2.client-secret", "client-secret") - .put("http-server.authentication.oauth2.principal-field", principalField.orElse("sub")) - .buildOrThrow()) - .setAdditionalModule(binder -> newOptionalBinder(binder, OAuth2Client.class) - .setBinding() - .toInstance(new OAuth2Client() - { - @Override - public URI getAuthorizationUri(String state, URI callbackUri, Optional nonceHash) - { - return URI.create("http://example.com/authorize?" + state); - } - - @Override - public OAuth2Response getOAuth2Response(String code, URI callbackUri) - { - if (!"TEST_CODE".equals(code)) { - throw new IllegalArgumentException("Expected TEST_CODE"); - } - return new OAuth2Response(accessToken, Optional.of(now().plus(5, ChronoUnit.MINUTES)), Optional.of(idTokenBuilder.compact())); - } - })) - .build()) { + try (TokenServer tokenServer = new TokenServer(principalField); + TestingTrinoServer server = TestingTrinoServer.builder() + .setProperties(ImmutableMap.builder() + .putAll(SECURE_PROPERTIES) + .put("web-ui.enabled", String.valueOf(webUiEnabled)) + .putAll(getOAuth2Properties(tokenServer)) + .put("http-server.authentication.oauth2.principal-field", principalField.orElse("sub")) + .buildOrThrow()) + .setAdditionalModule(oauth2Module(tokenServer)) + .build()) { server.getInstance(Key.get(AccessControlManager.class)).addSystemAccessControl(TestSystemAccessControl.NO_IMPERSONATION); HttpServerInfo httpServerInfo = server.getInstance(Key.get(HttpServerInfo.class)); @@ -599,14 +550,10 @@ public OAuth2Response getOAuth2Response(String code, URI callbackUri) // not logged in URI baseUri = httpServerInfo.getHttpsUri(); assertOk(client, getPublicLocation(baseUri)); - OAuthBearer bearer = assertAuthenticateOAuth2Bearer(client, getAuthorizedUserLocation(baseUri), "http://example.com/authorize"); assertAuthenticateOAuth2Bearer(client, getManagementLocation(baseUri), "http://example.com/authorize"); + OAuthBearer bearer = assertAuthenticateOAuth2Bearer(client, getAuthorizedUserLocation(baseUri), "http://example.com/authorize"); assertResponseCode(client, getInternalLocation(baseUri), SC_FORBIDDEN); - // We must add the nonce to the ID token we will soon generate. - idTokenBuilder.claim(NONCE, hashNonce(bearer.getNonceCookie().getValue())); - // The second call to `assertAuthenticateOAuth2Bearer` above overwrites the nonce cookie we need. - cookieManager.getCookieStore().add(cookieManager.getCookieStore().getURIs().get(0), bearer.getNonceCookie()); // login with the callback endpoint assertOk( client, @@ -615,12 +562,12 @@ public OAuth2Response getOAuth2Response(String code, URI callbackUri) .addParameter("code", "TEST_CODE") .addParameter("state", bearer.getState()) .toString()); - assertEquals(getOauthToken(client, bearer.getTokenServer()), accessToken); + assertEquals(getOauthToken(client, bearer.getTokenServer()), tokenServer.getAccessToken()); // if Web UI is using oauth so we should get a cookie if (webUiEnabled) { HttpCookie cookie = getOnlyElement(cookieManager.getCookieStore().getCookies()); - assertEquals(cookie.getValue(), accessToken); + assertEquals(cookie.getValue(), tokenServer.getAccessToken()); assertEquals(cookie.getPath(), "/ui/"); assertEquals(cookie.getDomain(), baseUri.getHost()); assertTrue(cookie.getMaxAge() > 0 && cookie.getMaxAge() < MINUTES.toSeconds(5)); @@ -634,14 +581,11 @@ public OAuth2Response getOAuth2Response(String code, URI callbackUri) OkHttpClient clientWithOAuthToken = client.newBuilder() .authenticator((route, response) -> response.request().newBuilder() - .header(AUTHORIZATION, "Bearer " + accessToken) + .header(AUTHORIZATION, "Bearer " + tokenServer.getAccessToken()) .build()) .build(); assertAuthenticationAutomatic(httpServerInfo.getHttpsUri(), clientWithOAuthToken); } - finally { - jwkServer.stop(); - } } private static OAuthBearer assertAuthenticateOAuth2Bearer(OkHttpClient client, String url, String expectedRedirect) @@ -709,6 +653,30 @@ public HttpCookie getNonceCookie() } } + private static Module oauth2Module(TokenServer tokenServer) + { + return binder -> { + jaxrsBinder(binder).bind(TestResource.class); + newOptionalBinder(binder, OAuth2Client.class) + .setBinding() + .toInstance(tokenServer.getOAuth2Client()); + }; + } + + private static Map getOAuth2Properties(TokenServer tokenServer) + { + return ImmutableMap.builder() + .put("http-server.authentication.type", "oauth2") + .put("http-server.authentication.oauth2.issuer", tokenServer.getIssuer()) + .put("http-server.authentication.oauth2.jwks-url", tokenServer.getJwksUrl()) + .put("http-server.authentication.oauth2.state-key", "test-state-key") + .put("http-server.authentication.oauth2.auth-url", tokenServer.getIssuer()) + .put("http-server.authentication.oauth2.token-url", tokenServer.getIssuer()) + .put("http-server.authentication.oauth2.client-id", tokenServer.getClientId()) + .put("http-server.authentication.oauth2.client-secret", tokenServer.getClientSecret()) + .build(); + } + private static String getOauthToken(OkHttpClient client, String url) throws IOException { @@ -721,6 +689,118 @@ private static String getOauthToken(OkHttpClient client, String url) } } + private static class TokenServer + implements AutoCloseable + { + private final String issuer = "http://example.com/"; + private final String clientId = "clientID"; + private final Date tokenExpiration = Date.from(ZonedDateTime.now().plusMinutes(5).toInstant()); + private final Optional principalField; + private final TestingHttpServer jwkServer; + private final String accessToken; + + public TokenServer(Optional principalField) + throws Exception + { + this.principalField = requireNonNull(principalField, "principalField is null"); + jwkServer = createTestingJwkServer(); + jwkServer.start(); + accessToken = issueAccessToken(); + } + + @Override + public void close() + throws Exception + { + jwkServer.stop(); + } + + public OAuth2Client getOAuth2Client() + { + return new OAuth2Client() + { + private final AtomicReference> nonceHash = new AtomicReference<>(); + + @Override + public URI getAuthorizationUri(String state, URI callbackUri, Optional nonceHash) + { + // Save the last nonce in order to add it to the next issued ID token + this.nonceHash.set(nonceHash); + return URI.create("http://example.com/authorize?" + state); + } + + @Override + public OAuth2Response getOAuth2Response(String code, URI callbackUri) + { + if (!"TEST_CODE".equals(code)) { + throw new IllegalArgumentException("Expected TEST_CODE"); + } + return new OAuth2Response(accessToken, Optional.of(now().plus(5, ChronoUnit.MINUTES)), Optional.of(issueIdToken(nonceHash.get()))); + } + }; + } + + public String getIssuer() + { + return issuer; + } + + public String getJwksUrl() + { + return jwkServer.getBaseUrl().toString(); + } + + public String getClientId() + { + return clientId; + } + + public String getClientSecret() + { + return "clientSecret"; + } + + public String getAccessToken() + { + return accessToken; + } + + private String issueAccessToken() + { + JwtBuilder accessToken = Jwts.builder() + .signWith(JWK_PRIVATE_KEY) + .setHeaderParam(JwsHeader.KEY_ID, JWK_KEY_ID) + .setIssuer(issuer) + .setAudience(clientId) + .setExpiration(tokenExpiration); + if (principalField.isPresent()) { + accessToken.claim(principalField.get(), TEST_USER); + } + else { + accessToken.setSubject(TEST_USER); + } + return accessToken.compact(); + } + + private String issueIdToken(Optional nonceHash) + { + JwtBuilder idToken = Jwts.builder() + .signWith(JWK_PRIVATE_KEY) + .setHeaderParam(JwsHeader.KEY_ID, JWK_KEY_ID) + .setIssuer(issuer) + .setAudience(clientId) + .setExpiration(tokenExpiration); + if (principalField.isPresent()) { + idToken.claim(principalField.get(), TEST_USER); + } + else { + idToken.setSubject(TEST_USER); + } + nonceHash.ifPresent(nonce -> idToken.claim(NONCE, nonce)); + return idToken.compact(); + } + } + @javax.ws.rs.Path("/identity") public static class TestResource { From 663260190cc73768c996d680ac7821b490f6c2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Thu, 9 Dec 2021 11:22:01 +0100 Subject: [PATCH 05/11] Return groups in indentity response --- .../io/trino/server/security/TestResourceSecurity.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index e9251ca800fd..f17cabac1993 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -73,9 +73,11 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.collect.Iterables.getOnlyElement; @@ -820,8 +822,14 @@ public javax.ws.rs.core.Response echoToken(@Context HttpServletRequest servletRe return javax.ws.rs.core.Response.ok() .header("user", identity.getUser()) .header("principal", identity.getPrincipal().map(Principal::getName).orElse(null)) + .header("groups", toHeader(identity.getGroups())) .build(); } + + public static String toHeader(Set groups) + { + return groups.stream().sorted().collect(Collectors.joining(",")); + } } private void assertInsecureAuthentication(URI baseUri) From b0c9db1d94959b094fbac7366cb319cb2ff3ae18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Thu, 9 Dec 2021 11:23:52 +0100 Subject: [PATCH 06/11] Do not return groups=[username] from group provider --- .../java/io/trino/server/security/TestResourceSecurity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index f17cabac1993..712c2ff174a7 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -811,7 +811,7 @@ public static class TestResource @Inject public TestResource(AccessControl accessControl) { - this.sessionContextFactory = new HttpRequestSessionContextFactory(createTestMetadataManager(), ImmutableSet::of, accessControl); + this.sessionContextFactory = new HttpRequestSessionContextFactory(createTestMetadataManager(), user -> ImmutableSet.of(), accessControl); } @ResourceSecurity(AUTHENTICATED_USER) From c1b94b5bb58322f7a8473b27a81ca04d4fea9c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Fri, 10 Dec 2021 08:54:00 +0100 Subject: [PATCH 07/11] Add WebUI identity endpoint to TestResource --- .../server/security/TestResourceSecurity.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index 712c2ff174a7..fea21f3f92f9 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -297,7 +297,7 @@ public void testPasswordAuthenticatorUserMapping() // Normally this would result in an impersonation check to the X-Trino-User, but the password // authenticator has a hack to clear X-Trino-User in this case. Request request = new Request.Builder() - .url(getLocation(httpServerInfo.getHttpsUri(), "/identity")) + .url(getLocation(httpServerInfo.getHttpsUri(), "/protocol/identity")) .addHeader("Authorization", Credentials.basic(TEST_USER_LOGIN, TEST_PASSWORD)) .addHeader("X-Trino-User", TEST_USER_LOGIN) .build(); @@ -803,7 +803,7 @@ private String issueIdToken(Optional nonceHash) } } - @javax.ws.rs.Path("/identity") + @javax.ws.rs.Path("/") public static class TestResource { private final HttpRequestSessionContextFactory sessionContextFactory; @@ -816,7 +816,21 @@ public TestResource(AccessControl accessControl) @ResourceSecurity(AUTHENTICATED_USER) @GET - public javax.ws.rs.core.Response echoToken(@Context HttpServletRequest servletRequest, @Context HttpHeaders httpHeaders) + @javax.ws.rs.Path("/protocol/identity") + public javax.ws.rs.core.Response protocolIdentity(@Context HttpServletRequest servletRequest, @Context HttpHeaders httpHeaders) + { + return echoIdentity(servletRequest, httpHeaders); + } + + @ResourceSecurity(WEB_UI) + @GET + @javax.ws.rs.Path("/ui/api/identity") + public javax.ws.rs.core.Response webUiIdentity(@Context HttpServletRequest servletRequest, @Context HttpHeaders httpHeaders) + { + return echoIdentity(servletRequest, httpHeaders); + } + + public javax.ws.rs.core.Response echoIdentity(HttpServletRequest servletRequest, HttpHeaders httpHeaders) { Identity identity = sessionContextFactory.extractAuthorizedIdentity(servletRequest, httpHeaders, Optional.empty()); return javax.ws.rs.core.Response.ok() From 791afaa2089c4e82fefd72109f4ad8f39d763f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Wed, 19 Jan 2022 13:25:07 +0100 Subject: [PATCH 08/11] Use one shot startup strategy for hydra migrations --- .../product/launcher/env/common/HydraIdentityProvider.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java index b3adcd84b59c..9173bcc2f162 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java @@ -19,6 +19,7 @@ import io.trino.tests.product.launcher.env.Environment; import io.trino.tests.product.launcher.testcontainers.PortBinder; import io.trino.tests.product.launcher.testcontainers.SelectedPortWaitStrategy; +import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; @@ -59,6 +60,7 @@ public void extendEnvironment(Environment.Builder builder) DockerContainer migrationContainer = new DockerContainer(HYDRA_IMAGE, "hydra-db-migration") .withCommand("migrate", "sql", "--yes", DSN) .dependsOn(databaseContainer) + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .setTemporary(true); DockerContainer hydraConsent = new DockerContainer("oryd/hydra-login-consent-node:v1.4.2", "hydra-consent") From b1474b1e12815a24d671053004351aa60b991ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Sun, 23 Jan 2022 11:27:58 +0100 Subject: [PATCH 09/11] Do not remove temporal containers automatically Temporal containers can finish faster than the startup probe can check. The check interval comes from the docker client with rate limiting which queries the docker service at most once per second. This can create a race condition if the container can complete it's job in less or around 1 second. --- .../io/trino/tests/product/launcher/env/Environment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/Environment.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/Environment.java index bc24259432a2..17f10ac18b10 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/Environment.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/Environment.java @@ -380,8 +380,9 @@ public Builder addContainer(DockerContainer container) container.withCreateContainerCmdModifier(Builder::updateContainerHostConfig); - if (!container.getLogicalName().equals(TESTS)) { - // Tests container cannot be auto removed as we need to inspect it's exit code + if (!container.getLogicalName().equals(TESTS) && !container.isTemporary()) { + // Tests container cannot be auto removed as we need to inspect it's exit code. + // Temporal containers might exit earlier than the startup check polling interval. container.withCreateContainerCmdModifier(Builder::setContainerAutoRemove); } From 0e004f5a54053d9803538337369824ab045a5e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Wed, 22 Dec 2021 13:05:54 +0100 Subject: [PATCH 10/11] Use login & consent server accepting all requests Instead of using selenium driver to log in and accept the consent request use a simple python implementation which accepts all requests thus eliminating the need of web driver entirely. Fixes #6991 --- pom.xml | 55 +----- .../launcher/env/EnvironmentModule.java | 2 - .../env/common/HydraIdentityProvider.java | 33 ++-- .../launcher/env/common/SeleniumChrome.java | 67 ------- .../env/environment/EnvSinglenodeOauth2.java | 5 +- .../EnvSinglenodeOauth2HttpProxy.java | 5 +- .../EnvSinglenodeOauth2HttpsProxy.java | 14 +- .../hydra-identity-provider/cert/generate.sh | 11 +- .../hydra-identity-provider/cert/hydra.conf | 15 ++ .../hydra-identity-provider/cert/hydra.pem | 80 ++++++++ .../cert/localhost.conf | 19 -- .../cert/localhost.pem | 83 -------- .../hydra-identity-provider/cert/trino.conf | 15 ++ .../hydra-identity-provider/cert/trino.pem | 80 ++++++++ .../cert/truststore.jks | Bin 0 -> 2903 bytes .../login_and_consent_server.py | 75 ++++++++ ...empto-configuration-for-docker-oauth2.yaml | 2 +- .../config.properties | 5 +- .../cert/create-certs.sh | 16 +- .../cert/hydra.conf | 19 -- .../cert/hydra.pem | 83 -------- .../cert/proxy.pem | 156 +++++++-------- .../cert/truststore.jks | Bin 3191 -> 4375 bytes .../config.properties | 5 +- .../singlenode-oauth2/config.properties | 5 +- .../local/TestManuallyJdbcOauth2.java | 2 +- testing/trino-product-tests/pom.xml | 41 ++-- .../jdbc/TestExternalAuthorizerOAuth2.java | 178 +++++++----------- 28 files changed, 484 insertions(+), 587 deletions(-) delete mode 100644 testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/SeleniumChrome.java create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.conf create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.pem delete mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.conf delete mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.pem create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.conf create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.pem create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/truststore.jks create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/login_and_consent_server.py mode change 100644 => 100755 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/create-certs.sh delete mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.conf delete mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.pem diff --git a/pom.xml b/pom.xml index b6eec55a3014..ba06e3edca2a 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,6 @@ 19.3.0.0 1.14 6.9.0 - 3.141.59 187 2.0.0 2.10.0 @@ -1128,6 +1127,12 @@ ${dep.okhttp.version} + + com.squareup.okhttp3 + okhttp-tls + ${dep.okhttp.version} + + com.squareup.okhttp3 okhttp-urlconnection @@ -1530,54 +1535,6 @@ 42.3.1 - - org.seleniumhq.selenium - selenium-api - ${dep.selenium.version} - - - - org.seleniumhq.selenium - selenium-chrome-driver - ${dep.selenium.version} - - - - org.seleniumhq.selenium - selenium-java - ${dep.selenium.version} - - - commons-logging - commons-logging - - - - - - org.seleniumhq.selenium - selenium-remote-driver - ${dep.selenium.version} - - - commons-logging - commons-logging - - - - - - org.seleniumhq.selenium - selenium-support - ${dep.selenium.version} - - - commons-logging - commons-logging - - - - org.sonatype.aether aether-api diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/EnvironmentModule.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/EnvironmentModule.java index b37d9df21f18..0fa323fb168b 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/EnvironmentModule.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/EnvironmentModule.java @@ -25,7 +25,6 @@ import io.trino.tests.product.launcher.env.common.Kafka; import io.trino.tests.product.launcher.env.common.KafkaSsl; import io.trino.tests.product.launcher.env.common.Phoenix; -import io.trino.tests.product.launcher.env.common.SeleniumChrome; import io.trino.tests.product.launcher.env.common.Standard; import io.trino.tests.product.launcher.env.common.StandardMultinode; import io.trino.tests.product.launcher.testcontainers.PortBinder; @@ -69,7 +68,6 @@ public void configure(Binder binder) binder.bind(HydraIdentityProvider.class).in(SINGLETON); binder.bind(Kafka.class).in(SINGLETON); binder.bind(KafkaSsl.class).in(SINGLETON); - binder.bind(SeleniumChrome.class).in(SINGLETON); binder.bind(Standard.class).in(SINGLETON); binder.bind(StandardMultinode.class).in(SINGLETON); binder.bind(Phoenix.class).in(SINGLETON); diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java index 9173bcc2f162..c25abb287026 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java @@ -63,10 +63,11 @@ public void extendEnvironment(Environment.Builder builder) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .setTemporary(true); - DockerContainer hydraConsent = new DockerContainer("oryd/hydra-login-consent-node:v1.4.2", "hydra-consent") - .withEnv("HYDRA_ADMIN_URL", "https://hydra:4445") - .withEnv("NODE_TLS_REJECT_UNAUTHORIZED", "0") - .waitingFor(Wait.forHttp("/").forPort(3000).forStatusCode(200)); + DockerContainer hydraConsent = new DockerContainer("python:3.10.1-alpine", "hydra-consent") + .withCopyFileToContainer(forHostPath(configDir.getPath("login_and_consent_server.py")), "/") + .withCommand("python", "/login_and_consent_server.py") + .withExposedPorts(3000) + .waitingFor(Wait.forHttp("/healthz").forPort(3000).forStatusCode(200)); binder.exposePort(hydraConsent, 3000); @@ -76,12 +77,12 @@ public void extendEnvironment(Environment.Builder builder) .withEnv("URLS_SELF_ISSUER", "https://hydra:4444/") .withEnv("URLS_CONSENT", "http://hydra-consent:3000/consent") .withEnv("URLS_LOGIN", "http://hydra-consent:3000/login") - .withEnv("SERVE_TLS_KEY_PATH", "/tmp/certs/localhost.pem") - .withEnv("SERVE_TLS_CERT_PATH", "/tmp/certs/localhost.pem") + .withEnv("SERVE_TLS_KEY_PATH", "/tmp/certs/hydra.pem") + .withEnv("SERVE_TLS_CERT_PATH", "/tmp/certs/hydra.pem") .withEnv("STRATEGIES_ACCESS_TOKEN", "jwt") .withEnv("TTL_ACCESS_TOKEN", TTL_ACCESS_TOKEN_IN_SECONDS + "s") .withCommand("serve", "all") - .withCopyFileToContainer(forHostPath(configDir.getPath("cert")), "/tmp/certs") + .withCopyFileToContainer(forHostPath(configDir.getPath("cert/hydra.pem")), "/tmp/certs/hydra.pem") .waitingFor(new WaitAllStrategy() .withStrategy(Wait.forLogMessage(".*Setting up http server on :4444.*", 1)) .withStrategy(Wait.forLogMessage(".*Setting up http server on :4445.*", 1))); @@ -99,14 +100,22 @@ public void extendEnvironment(Environment.Builder builder) if (isPrestoContainer(dockerContainer.getLogicalName())) { dockerContainer .withCopyFileToContainer( - forHostPath(configDir.getPath("cert")), - CONTAINER_PRESTO_ETC + "/hydra/cert"); + forHostPath(configDir.getPath("cert/trino.pem")), + CONTAINER_PRESTO_ETC + "/trino.pem") + .withCopyFileToContainer( + forHostPath(configDir.getPath("cert/hydra.pem")), + CONTAINER_PRESTO_ETC + "/hydra.pem"); } }); - builder.configureContainer(TESTS, dockerContainer -> dockerContainer.withCopyFileToContainer( - forHostPath(configDir.getPath("tempto-configuration-for-docker-oauth2.yaml")), - CONTAINER_TEMPTO_PROFILE_CONFIG)); + builder.configureContainer(TESTS, dockerContainer -> + dockerContainer + .withCopyFileToContainer( + forHostPath(configDir.getPath("tempto-configuration-for-docker-oauth2.yaml")), + CONTAINER_TEMPTO_PROFILE_CONFIG) + .withCopyFileToContainer( + forHostPath(configDir.getPath("cert/truststore.jks")), + "/docker/presto-product-tests/truststore.jks")); } public DockerContainer createClient( diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/SeleniumChrome.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/SeleniumChrome.java deleted file mode 100644 index f0e4268622ca..000000000000 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/SeleniumChrome.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.tests.product.launcher.env.common; - -import com.google.inject.Inject; -import io.trino.tests.product.launcher.env.DockerContainer; -import io.trino.tests.product.launcher.env.Environment; -import io.trino.tests.product.launcher.testcontainers.PortBinder; -import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; -import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; -import org.testcontainers.utility.DockerImageName; - -import java.time.Duration; - -import static java.util.Objects.requireNonNull; - -public class SeleniumChrome - implements EnvironmentExtender -{ - private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome-debug").withTag("3.141.59-20210804"); - private static final int SELENIUM_PORT = 7777; - private static final Duration STARTUP_TIMEOUT = Duration.ofSeconds(15); - - private final PortBinder portBinder; - - @Inject - public SeleniumChrome(PortBinder portBinder) - { - this.portBinder = requireNonNull(portBinder, "portBinder is null"); - } - - @Override - public void extendEnvironment(Environment.Builder builder) - { - DockerContainer seleniumChrome = new DockerContainer(CHROME_IMAGE.asCanonicalNameString(), "selenium-chrome"); - seleniumChrome.addEnv("SE_OPTS", "-port " + SELENIUM_PORT); - seleniumChrome.addEnv("TZ", "Etc/UTC"); - seleniumChrome.addEnv("no_proxy", "localhost"); - seleniumChrome.setCommand("/opt/bin/entry_point.sh"); - - seleniumChrome.waitingForAll( - new LogMessageWaitStrategy() - .withRegEx(".*(RemoteWebDriver instances should connect to|Selenium Server is up and running).*\n") - .withStartupTimeout(STARTUP_TIMEOUT), - new HostPortWaitStrategy() - .withStartupTimeout(STARTUP_TIMEOUT)); - - // Taken from BrowserWebDriverContainer were it has been said that: - // "Some unreliability of the selenium browser containers has been observed, so allow multiple attempts to start." - seleniumChrome.setStartupAttempts(3); - - portBinder.exposePort(seleniumChrome, SELENIUM_PORT); - - builder.addContainer(seleniumChrome); - } -} diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2.java index 1a27c20a9695..d8bcffbe010d 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2.java @@ -20,7 +20,6 @@ import io.trino.tests.product.launcher.env.Environment; import io.trino.tests.product.launcher.env.EnvironmentProvider; import io.trino.tests.product.launcher.env.common.HydraIdentityProvider; -import io.trino.tests.product.launcher.env.common.SeleniumChrome; import io.trino.tests.product.launcher.env.common.Standard; import io.trino.tests.product.launcher.env.common.TestsEnvironment; import io.trino.tests.product.launcher.testcontainers.PortBinder; @@ -41,9 +40,9 @@ public class EnvSinglenodeOauth2 private final ResourceProvider configDir; @Inject - public EnvSinglenodeOauth2(DockerFiles dockerFiles, PortBinder binder, Standard standard, HydraIdentityProvider hydraIdentityProvider, SeleniumChrome seleniumChrome) + public EnvSinglenodeOauth2(DockerFiles dockerFiles, PortBinder binder, Standard standard, HydraIdentityProvider hydraIdentityProvider) { - super(ImmutableList.of(standard, hydraIdentityProvider, seleniumChrome)); + super(ImmutableList.of(standard, hydraIdentityProvider)); this.binder = requireNonNull(binder, "binder is null"); this.hydraIdentityProvider = requireNonNull(hydraIdentityProvider, "hydraIdentityProvider is null"); diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpProxy.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpProxy.java index 6bdfe49df606..679f7b9a567f 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpProxy.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpProxy.java @@ -20,7 +20,6 @@ import io.trino.tests.product.launcher.env.Environment; import io.trino.tests.product.launcher.env.EnvironmentProvider; import io.trino.tests.product.launcher.env.common.HydraIdentityProvider; -import io.trino.tests.product.launcher.env.common.SeleniumChrome; import io.trino.tests.product.launcher.env.common.Standard; import io.trino.tests.product.launcher.env.common.TestsEnvironment; import io.trino.tests.product.launcher.testcontainers.PortBinder; @@ -41,9 +40,9 @@ public class EnvSinglenodeOauth2HttpProxy private final ResourceProvider configDir; @Inject - public EnvSinglenodeOauth2HttpProxy(DockerFiles dockerFiles, PortBinder binder, Standard standard, HydraIdentityProvider hydraIdentityProvider, SeleniumChrome seleniumChrome) + public EnvSinglenodeOauth2HttpProxy(DockerFiles dockerFiles, PortBinder binder, Standard standard, HydraIdentityProvider hydraIdentityProvider) { - super(ImmutableList.of(standard, hydraIdentityProvider, seleniumChrome)); + super(ImmutableList.of(standard, hydraIdentityProvider)); this.binder = requireNonNull(binder, "binder is null"); this.hydraIdentityProvider = requireNonNull(hydraIdentityProvider, "hydraIdentityProvider is null"); diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpsProxy.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpsProxy.java index 4cd3e9747de6..4df9422f29ec 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpsProxy.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeOauth2HttpsProxy.java @@ -20,7 +20,6 @@ import io.trino.tests.product.launcher.env.Environment; import io.trino.tests.product.launcher.env.EnvironmentProvider; import io.trino.tests.product.launcher.env.common.HydraIdentityProvider; -import io.trino.tests.product.launcher.env.common.SeleniumChrome; import io.trino.tests.product.launcher.env.common.Standard; import io.trino.tests.product.launcher.env.common.TestsEnvironment; import io.trino.tests.product.launcher.testcontainers.PortBinder; @@ -42,9 +41,9 @@ public class EnvSinglenodeOauth2HttpsProxy private final ResourceProvider configDir; @Inject - public EnvSinglenodeOauth2HttpsProxy(DockerFiles dockerFiles, PortBinder binder, Standard standard, HydraIdentityProvider hydraIdentityProvider, SeleniumChrome seleniumChrome) + public EnvSinglenodeOauth2HttpsProxy(DockerFiles dockerFiles, PortBinder binder, Standard standard, HydraIdentityProvider hydraIdentityProvider) { - super(ImmutableList.of(standard, hydraIdentityProvider, seleniumChrome)); + super(ImmutableList.of(standard, hydraIdentityProvider)); this.binder = requireNonNull(binder, "binder is null"); this.hydraIdentityProvider = requireNonNull(hydraIdentityProvider, "hydraIdentityProvider is null"); @@ -61,8 +60,8 @@ public void extendEnvironment(Environment.Builder builder) forHostPath(configDir.getPath("config.properties")), CONTAINER_PRESTO_CONFIG_PROPERTIES) .withCopyFileToContainer( - forHostPath(configDir.getPath("cert")), - CONTAINER_PRESTO_ETC + "/cert"); + forHostPath(configDir.getPath("cert/truststore.jks")), + CONTAINER_PRESTO_ETC + "/cert/truststore.jks"); binder.exposePort(dockerContainer, 7778); }); @@ -77,11 +76,6 @@ public void extendEnvironment(Environment.Builder builder) builder.containerDependsOn(COORDINATOR, hydraClientConfig.getLogicalName()); - builder.configureContainer("hydra", dockerContainer -> dockerContainer - .withCopyFileToContainer(forHostPath(configDir.getPath("cert")), "/tmp/certs") - .withEnv("SERVE_TLS_KEY_PATH", "/tmp/certs/hydra.pem") - .withEnv("SERVE_TLS_CERT_PATH", "/tmp/certs/hydra.pem")); - DockerContainer proxy = new DockerContainer("httpd:2.4.51", "proxy"); proxy .withCopyFileToContainer( diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/generate.sh b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/generate.sh index cf662f5e120c..af7b93e2eaa2 100755 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/generate.sh +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/generate.sh @@ -2,5 +2,12 @@ set -eux -openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes -keyout localhost.key -days 3560 -out localhost.crt -config localhost.conf -cat localhost.crt localhost.key > localhost.pem +rm -f truststore.jks + +for name in "hydra" "trino" +do + openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes -keyout "${name}.key" -days 35600 -out "${name}.crt" -config "${name}.conf" + cat "${name}.crt" "${name}.key" > "${name}.pem" + keytool -import -noprompt -alias "${name}" -keystore truststore.jks -storepass 123456 -file "${name}.crt" + rm "${name}.crt" "${name}.key" +done diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.conf b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.conf new file mode 100644 index 000000000000..fe9fdf4682eb --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.conf @@ -0,0 +1,15 @@ +[ req ] +default_bits = 4096 +prompt = no +default_md = sha256 +x509_extensions = v3_req +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +CN = hydra + +[ v3_req ] +subjectAltName = @alt_names + +[alt_names] +DNS = hydra diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.pem b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.pem new file mode 100644 index 000000000000..ba15db1fb133 --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/hydra.pem @@ -0,0 +1,80 @@ +-----BEGIN CERTIFICATE----- +MIIEuTCCAqGgAwIBAgIJAOa8Xr8cVD9oMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNV +BAMMBWh5ZHJhMCAXDTIxMTIyMjA3NDM1MVoYDzIxMTkwNjEyMDc0MzUxWjAQMQ4w +DAYDVQQDDAVoeWRyYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANFy +KpNoQW3N83gGavUNjvqsJSeVnNpI/76kTesqIQzC7Q/HvK6UbFeZeqc3fD7RcoFo +NvsOl5QORsR3qhFADA2IrPCthF4sqEq0y30/YDxZHDtojY+LdNEE2kcMH15CjoEa +BESu/Y6rmwQ2V653M4IcpOuvQHX7+B7otjQmnht8gv5LgeN0l+BMgGq7DaKXMS/a +jCFG00E+5ilco8a/PakzP/XNfpJiWC/C7eRI8ovmjUgFjY6ixyTABP3rzWM0zgDd +Q9FBUm7lRtTcWwwB7psJ6B1Ibmf4NyvC2YTSFcK3c0KZbLsgb4xcEEcpEiGD6KmH +o8QXO1UYGy3eAZ7/y38Ofo0aNykiLSMHeGZ9n6hR0oTPl3LCJNlHxh3OyRfVgRkW +VntXQRPhRB3L9x7k7Ip9Pjh49orZfjj4GdrJX3/scJcUZCc4KzHPmDjlsgtcPyQY +pSrNfggIxLZERKeT3O5/jIuQAXG7drMb20atAUpQlvAQqBgIRLj9F/W56zg1J+Sr +O0YHnz9/QDqBrhqiF/hP7skzeXcfUyVpSuLRYUFTM46OT8vJzAIbvh9c4grpqd2m +z14JbzTDGPV+tlRPMXP18+1zJ4efFgl46VXZaPiMgVkzbzONNOTyB+cSUfVobBID +ian7Hs62gR4hTu1upcSFwLlnYBqOBQbH5l1mATrtAgMBAAGjFDASMBAGA1UdEQQJ +MAeCBWh5ZHJhMA0GCSqGSIb3DQEBCwUAA4ICAQCD5GmzbLlYqfpv5uxSJQqvLHDT +1m6RWx0Ym/h/wNJR3nh68K/GKDPUh0EV5TUWQUg9rr0aB1ozV2lJTK2e3OQN+qDp +CyHSgt+tw/ir/DfAqeCmadvXoXwOs52UQMm9YDq4KU7bcIGVTT+LG/JgFTurS94n +PTdXbmC16PJyOR8KC7WlxmU4VYyv4MvsWUuzndoWigu8IjrlclbAPN04hBx68YII +tcS/X5fjTDrtLeyCqoa5alsmReiY7uIxI+aZPY8AZw3mhM2ZqnFE4ThY+Rsulp4X +kWBJSrLU+ahU3YvddQCMoAbfrJo/PBb2S7MO6dAerlTe12RRtA914wghueuA1zEj +Y6Rauu0pDWj2f5Ga7O0nisuFI8XaaMKlVAKfnSadpK8iU1jbU+GIDJ5ZM/fIF7mE +gKPxWL6NoFgy2psFlSjwgk7X3wo1MPxy9vtGGzZHGqKhNy7FNjrRLStwzaA8t3Py +vSltFEAjOzT0kyLCunWd8KKloUTVkQ3aCsy2YCzYlrpXcMyszqTP/PllWyaPMGLB +/zi9Vdu2fY+881SaeePO6Shazv5mY8Q2Ed6in79OTGp4ioLbvYmiyuJ/fRzBYJit +NeoWNt2mrZgY2nn7+L9zA3W32+YNILB7/MjBmwokhxbHF6dbtn1MsnUF7qd0aCkD +aQ3dA9Anu/PASQCddw== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +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 +4N+nzawlz9SrYXr6fQUPqdRex41H +-----END PRIVATE KEY----- diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.conf b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.conf deleted file mode 100644 index 11be13d10710..000000000000 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.conf +++ /dev/null @@ -1,19 +0,0 @@ -[req] -default_bits = 4096 -prompt = no -default_md = sha256 -x509_extensions = v3_req -distinguished_name = dn - -[dn] -C = US -ST = California -L = Palo Alto -O = PrestoTest -CN = PrestoTest - -[v3_req] -subjectAltName = @alt_names - -[alt_names] -DNS.1 = hydra diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.pem b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.pem deleted file mode 100644 index cafb06346dee..000000000000 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/localhost.pem +++ /dev/null @@ -1,83 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgIJANciS7odijt6MA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8x -EzARBgNVBAoMClByZXN0b1Rlc3QxEzARBgNVBAMMClByZXN0b1Rlc3QwHhcNMjEw -NTI2MTIwNDA5WhcNMzEwMjIzMTIwNDA5WjBgMQswCQYDVQQGEwJVUzETMBEGA1UE -CAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJUGFsbyBBbHRvMRMwEQYDVQQKDApQcmVz -dG9UZXN0MRMwEQYDVQQDDApQcmVzdG9UZXN0MIICIjANBgkqhkiG9w0BAQEFAAOC -Ag8AMIICCgKCAgEAxSzRwKshIyVwtRkOQCg2VjaD2woUyqxljbOPYOLNt2NdBa5/ -LMJ+LaHwsmVyW8l8EGLdp7EGRNjZfG4ZezZbMTRf4RkrVcDAgFdMONjNmM3iyLi+ -ryPDzEQFnI4Z2dJ3ZpsdDATbcWPPv1qyvI0vOyYrVHHByYCaKOTrzfzV9sssXMR8 -osy4aVjP5SOOLMKg99bAeWMCTDTYJlXc7ROba+N6OYEDR6a1vefXI4hc4dQy18SZ -/rFqvgcf+rqlz+PL+kNjPJ2uBAvcDF3e0fEMOn8yhPDvrp3Lzso1wwgAFZCE7Cv2 -hz0pCqYy6hMUSl4HqZLj0WlPDTOobKSADoQkHfjEGhCtThj9CWwGly7aeQdk+roI -VRDXcYLeJXA/xSzTPtWO4wkjX9VMcwWrFYDuycqxyfXvKxGPHsY3oRqbgW5RgvOh -sIPa7Yu3oc998h6QyMDO6YPseKfRULuOse7ITUTRNPV0A4eztOne5/ZemEiRYzwH -N8+r8zsdz5m47B0+8ZNpiiBgy9sTCNs2DKy50HZNJ/D5CQOwW56CfV5NHAXhocAE -aSmbSPOs0Wz+wDR+5cs9B6pKZd6BqyOJz+/+2tPQ30OpGbjyWgRoK9cHld82CiWY -+FgTFQaBK5OrL4puaGY+mus8C31i6HD5r+ECmkK+iG9z1K23ifDYI1opAG8CAwEA -AaMUMBIwEAYDVR0RBAkwB4IFaHlkcmEwDQYJKoZIhvcNAQELBQADggIBALW9IvOs -DNCrJrx2ZJN0N+EMY5kOXFtrfQPgz5OWYz0TNBIbEjNWGRYyrYNyijdzgnIeEn3P -BQ+0jl6O2sbSF9vkKgwCH9iH6oDtU4bApqGz8W5uFyM3kgS31C7ZJSCu/+KtsKwv -q7o3g5jSLW6Wgn+abJIoljn+/Z5vHn+81tWjxUfY8gwhtw8mk9vrS6mVuMhYfuoi -4eZ7pew/8mYdfHhwRdBAEZN4+ovNgb1GZDk4s2NWwOGS0WpUDfAuXVeZ2GzOPVbR -YEbaSwrGh+M2K+Vg1MEgkPmRCY3drZOJd6wcCkJVE6sUsp6UIKzFdDrSFU2mvyhS -MJU/JC+0rPFpjsDe+VvAEbHTJ0nx37hh6igpZuSJH39O9oKjox3HKItf6OtGj9K1 -1XPyWsBQgZdyqh8nFFrf8n1qnfeJR6wJpYd1cW3oJuNgbVtmyvTOMdNHdII1tKv5 -lfgB4TCoKJpEiYYZlTtHIiB8NyUy4PpVCfmfe7tfIKcUV29oa1ZJRH0Fq3l/ywlQ -WuRCYHw6vEOCR17TiLRN02NMU6QYQKFlK8zFgempKf6b943MYQ9EBYC4Z3Xuw7R3 -qozE9UDK/7cGTH0Vy1Cpt3T857G0FjivG/KQFqtM6V4om9PsX052w2kabrtYw7th -vRDDiUuChbW5L/Bn+N+HMDq9phsfcI5/zBry ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -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 -bVAoDxTHIF++oefZSmn2rZBOBCtW ------END PRIVATE KEY----- diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.conf b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.conf new file mode 100644 index 000000000000..a70f27181b85 --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.conf @@ -0,0 +1,15 @@ +[ req ] +default_bits = 4096 +prompt = no +default_md = sha256 +x509_extensions = v3_req +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +CN = presto-master + +[ v3_req ] +subjectAltName = @alt_names + +[alt_names] +DNS = presto-master diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.pem b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.pem new file mode 100644 index 000000000000..42904fb19baf --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/trino.pem @@ -0,0 +1,80 @@ +-----BEGIN CERTIFICATE----- +MIIE0TCCArmgAwIBAgIJAO4k4YwG5hr8MA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV +BAMMDXByZXN0by1tYXN0ZXIwIBcNMjExMjIyMDc0MzUyWhgPMjExOTA2MTIwNzQz +NTJaMBgxFjAUBgNVBAMMDXByZXN0by1tYXN0ZXIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC1ioarBcMyp88h4Cp8Dw6me9KFcvnhuadIkEfwwh/QRzk6 +Zb4lwUlJduUo72nUVkklAWpuLWFwoeDDWrrttJSTtXfs0YtQzbLLY+N+NJcrSO9K +Q9KMxOSevsVvqokvq7cKOcwOuHMxLZ+p48g+XQvjTuhOTXRbJSlXLpGi/z2EC+RM +QRrdbbwy6ubgtIJWK9GGS/FtHXIglhNPZCA5dPg9ljM+LSZkxgr1X5DqLuPamF6V +G7eZDAPJ59aEljIFS0NC0hSDydaWtVuQ+cuee/Nbk/Tk0jnK+VFPnhWhPHisOE3y +3cF5wXXSd8ScNcYsj6LjJ8KwNkT+BUEWjRTaYOjahggHUW4ZTDeOC9w6lFpGf5ag +gstRj4d1TjTAxAq8ZSvWe1wgJiBxkRotM+R1eDcAISxh2+Dj9ZqLiL6wTkiZOGAx +9lxwlielnwsuxpVAko+4R+GqXw2sbREppSZwVKtkIAsaa9soWG2YBf+7G7zr9F/f +i24tBDvTNruTXN0X7hk9lujj2sVb2zv4lo/gy1FOQv4LfIr6/8jmmsRWAOuyril8 +DyItRCarcd0FwbHyQgVijsNjdSkpUZ+PCmPjKRfUFIvbyCTltedb7xXLyBD9tvzC +oYeqMgDPglNFS2YzMzymghegQm7ZzKSeTmvGQGOe4gph0r18IQ/IckzheAnYswID +AQABoxwwGjAYBgNVHREEETAPgg1wcmVzdG8tbWFzdGVyMA0GCSqGSIb3DQEBCwUA +A4ICAQB/Mtfa+32FT7rrxLYdzoW2mCXH7I0lXnjXM7EXo6oeO8rrNWQboYn2KGUy +7nPlnwt9zR8p7f4ERpgwYITHZruv3NnBnnRm2Exrg+gjH5WTPAqPoBlZtDtw1fQz +eyn3SXe1J2xBiec4HUadkf/nqOsx3BWl59mvL8DaRlT/CCQmWG89G6TRIcIAev3W +qZUOd/NuXY32iuRMv5j2CdwFKRIAhvldLrqzvD3U6imb/YOnoDz1omsXe4L6xcgS +OJH1hhxMjBdYSkrcGiy5N5Oe7JL45kIvxi518O3c8CvdZdWc9dudzpl/Q9clRabd +Q0v3jSdeXiZNl6UgxK+9IYx6r1cOM4eKjqYSsmzOhrcREU3LUY/HfDatjqCdKjPz +pvM1zCzr3Wf4/R7Ene1zdq7SNlnuWy2p1FoDLtDmYPwV1jSMduemMZPAp5rYIA6r +Wn65GVOy3DAjK073ICH+0BA0kftXXIm/3scj4Y5iFFFkGq9UvA+gdScIeBuSNYrm +Q40IaEDDCH/ROMo+ieBPtFbFZoDcqT8t5Ba52cjDtmmTR8AbBSAQOee4cef/eijI +0gEm97Fu17kHIF6uZvOLI/zMY91lhikTviuSp8OSpsFrphWB4JNtZhdYu2lKkqMs +00rnB0zHg4sXqvonEzrmvdTI2pD3lFLJTaD4XtOiEtaMkhpeoQ== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +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 +ag1idl6/CvSJuJ2XJErJzXTcFTnuFNo= +-----END PRIVATE KEY----- diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/truststore.jks b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/cert/truststore.jks new file mode 100644 index 0000000000000000000000000000000000000000..f9ab80eac63d30db829ea2a39943c193e6b945f4 GIT binary patch literal 2903 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 BYdin| literal 0 HcmV?d00001 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/login_and_consent_server.py b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/login_and_consent_server.py new file mode 100644 index 000000000000..d1a08f456170 --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/login_and_consent_server.py @@ -0,0 +1,75 @@ +import json +import os +import ssl +from http.server import BaseHTTPRequestHandler, HTTPServer +from typing import Dict, Any +from urllib.parse import urlparse, parse_qs +from urllib.request import Request, urlopen + +HYDRA_ADMIN_URL = os.getenv("HYDRA_ADMIN_URL", "https://hydra:4445") +PORT = os.getenv("PORT", 3000) +SSL_CONTEXT = ssl.create_default_context() +SSL_CONTEXT.check_hostname = False +SSL_CONTEXT.verify_mode = ssl.CERT_NONE + + +class LoginAndConsentServer(BaseHTTPRequestHandler): + def do_GET(self): + params = parse_qs(urlparse(self.path).query) + if self.path == "/healthz": + self.send_response(200) + if self.path.startswith("/login"): + self.accept_login(params) + return + if self.path.startswith("/consent"): + self.accept_consent(params) + return + self.send_error(404, "Not found") + + def accept_login(self, params: Dict[str, list[str]]) -> None: + login_challenge = params["login_challenge"][0] + with urlopen(Request( + method="PUT", + url=HYDRA_ADMIN_URL + "/oauth2/auth/requests/login/accept?login_challenge=" + login_challenge, + headers={"Content-Type": "application/json; charset=UTF-8"}, + data=json.dumps({"subject": "foo@bar.com"}).encode()), + context=SSL_CONTEXT) as response: + self.send_redirect(response) + + def accept_consent(self, params: Dict[str, list[str]]) -> None: + consent_challenge = params["consent_challenge"][0] + consent_request = self.get_consent_request(consent_challenge) + with urlopen(Request( + method="PUT", + url=HYDRA_ADMIN_URL + "/oauth2/auth/requests/consent/accept?consent_challenge=" + consent_challenge, + headers={"Content-Type": "application/json; charset=UTF-8"}, + data=json.dumps({ + "grant_scope": consent_request["requested_scope"], + "grant_access_token_audience": consent_request["requested_access_token_audience"], + "session": { + "access_token": { + "groups": ["admin", "public"] + } + }}).encode()), + context=SSL_CONTEXT) as response: + self.send_redirect(response) + + @staticmethod + def get_consent_request(consent_challenge: str) -> Dict[str, Any]: + with urlopen(Request( + method="GET", + url=HYDRA_ADMIN_URL + "/oauth2/auth/requests/consent?consent_challenge=" + consent_challenge), + context=SSL_CONTEXT) as response: + return json.load(response) + + def send_redirect(self, response): + body = json.load(response) + self.send_response(302) + self.send_header("Location", body["redirect_to"]) + self.end_headers() + + +if __name__ == "__main__": + server_address = ("", PORT) + httpd = HTTPServer(server_address, LoginAndConsentServer) + httpd.serve_forever() diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/tempto-configuration-for-docker-oauth2.yaml b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/tempto-configuration-for-docker-oauth2.yaml index 046df1fed050..a44081af00ba 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/tempto-configuration-for-docker-oauth2.yaml +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/common/hydra-identity-provider/tempto-configuration-for-docker-oauth2.yaml @@ -10,5 +10,5 @@ databases: SSLTrustStorePath=${databases.presto.https_keystore_path}&\ SSLTrustStorePassword=${databases.presto.https_keystore_password}&\ externalAuthentication=true" - https_keystore_path: /docker/presto-product-tests/conf/presto/etc/presto-master.jks + https_keystore_path: /docker/presto-product-tests/truststore.jks https_keystore_password: '123456' diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties index 977ad331c115..0f2310114f28 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties @@ -12,8 +12,7 @@ web-ui.enabled=true http-server.authentication.type=oauth2 http-server.https.port=7778 http-server.https.enabled=true -http-server.https.keystore.path=/docker/presto-product-tests/conf/presto/etc/presto-master.jks -http-server.https.keystore.key=123456 +http-server.https.keystore.path=/docker/presto-product-tests/conf/presto/etc/trino.pem http-server.authentication.oauth2.issuer=https://hydra:4444/ http-server.authentication.oauth2.auth-url=https://hydra:4444/oauth2/auth http-server.authentication.oauth2.token-url=https://hydra:4444/oauth2/token @@ -21,5 +20,5 @@ http-server.authentication.oauth2.jwks-url=https://hydra:4444/.well-known/jwks.j http-server.authentication.oauth2.client-id=trinodb_client_id http-server.authentication.oauth2.client-secret=trinodb_client_secret http-server.authentication.oauth2.user-mapping.pattern=(.*)(@.*)? -oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/hydra/cert/localhost.pem +oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/hydra.pem oauth2-jwk.http-client.http-proxy=proxy:8888 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/create-certs.sh b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/create-certs.sh old mode 100644 new mode 100755 index 4e910b8fa644..d83865149be6 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/create-certs.sh +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/create-certs.sh @@ -2,14 +2,12 @@ set -eux -for i in hydra proxy; do - echo $i +cp "$(dirname "$0")/../../../../common/hydra-identity-provider/cert/truststore.jks" truststore.jks - # Generate private key and certificate - openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes -keyout $i.key -days 3650 -out $i.crt -config $i.conf - cat $i.crt $i.key > $i.pem +# Generate private key and certificate +openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes -keyout proxy.key -days 36500 -out proxy.crt -config proxy.conf +cat proxy.crt proxy.key > proxy.pem - # Create truststore and import the cert. - keytool -keystore truststore.jks -alias $i -import -file $i.crt -storepass changeit -noprompt - rm $i.crt $i.key -done +# Create truststore and import the cert. +keytool -keystore truststore.jks -alias proxy -import -file proxy.crt -storepass 123456 -noprompt +rm proxy.crt proxy.key diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.conf b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.conf deleted file mode 100644 index 11be13d10710..000000000000 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.conf +++ /dev/null @@ -1,19 +0,0 @@ -[req] -default_bits = 4096 -prompt = no -default_md = sha256 -x509_extensions = v3_req -distinguished_name = dn - -[dn] -C = US -ST = California -L = Palo Alto -O = PrestoTest -CN = PrestoTest - -[v3_req] -subjectAltName = @alt_names - -[alt_names] -DNS.1 = hydra diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.pem b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.pem deleted file mode 100644 index 13d1b030a66c..000000000000 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/hydra.pem +++ /dev/null @@ -1,83 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgIJAMB9iM7Mrn+jMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8x -EzARBgNVBAoMClByZXN0b1Rlc3QxEzARBgNVBAMMClByZXN0b1Rlc3QwHhcNMjEx -MTI1MTQwMjQzWhcNMzExMTIzMTQwMjQzWjBgMQswCQYDVQQGEwJVUzETMBEGA1UE -CAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJUGFsbyBBbHRvMRMwEQYDVQQKDApQcmVz -dG9UZXN0MRMwEQYDVQQDDApQcmVzdG9UZXN0MIICIjANBgkqhkiG9w0BAQEFAAOC -Ag8AMIICCgKCAgEArE9uGiDuoN8aQeEBzLk+AXi9VdTsBSwXxZqXET3Kojm706q8 -+mIrYIWgTbw5ZmRoE1wvJ15iOdOsPm9m1knhS02ygUs4s8H7wAa5o4ciUvCJFdDB -FXHgZ7wxkeTCmZiGAORDRiaZAs4YIO898xpQ11L6c+X/lcyhCOqQEZaNvpEioPxo -DYZvBLcUUFYHYB2bSFmjLiVYUnzsopTJwzw50ll4PgQJSHrT5vNrIWRGzZeqi+lr -IFYKpgAOeUxGbimDhs524M+r5GRlZIvnhPL4/iaOKVrTLbhF7spBMoFR/fsChvMf -WKDZTU8jbeZWb/42p33eR51A50U+xfSqthmvH4Z4xXpxcgYfNi3/9yXK5Mo+rv1U -ReP64pzczGUzyDkVuEn9arT/kdZHcNPtJdmmGQq1W+p36K+e9jbM7y0ZaJ9L8K+2 -xoJ5WPvi6ar6ahsVOLMR5VWkF0QcMaEOLGe86bB0/UagrdQK08hL7N0B5pT93c0V -EpnEWncFmBd7nozm7IisH/iOuG3/C30IRUxC8rngrJD3wrypdCwg3cZ+0HiXEGhz -Q+TVehVRtbNlWM3EV3mB7LItRmYtgQhK8t3dARy9X3j+gXMuQpVXZHlbML+xHiEM -Yx4YfliYcYBNc9LKG58iTsRJxYSXPrOaqDwjnhm5KelBCZPoAcJCq7J3J0cCAwEA -AaMUMBIwEAYDVR0RBAkwB4IFaHlkcmEwDQYJKoZIhvcNAQELBQADggIBAEkQjFAN -g3UYaO/iMJwqeMsasetklHdMe86TD0MsJ3Tp7NpGPlUJ9zqW3jQhvmU5EYaY0cVl -2x04R1C0ByBMlucVB+fdEMvvMVHsBtaeDra2oNBAZILj4rNWEdjcT2f6pFl3xuB/ -wrbEmiiYrT+n2pedvfy84ov8Wo2ipP+Pdl2epRVOGjqeiN2Xxept+5uArGo0icp9 -gPaBZ+1TzjVQ8R1bhJTq8tlCD+nGISG9PQtkBwFLSX6q7Cso9AnUe5KEszNFngjY -JAML2gD6+K2Nd7VZEm78j7sxIGVB50WD619dJ8vvWpnJsDv/MpsJRj1b4gaKfLpd -622VkFeFZfmASbOK9+tP0ZcYwOiJuhbGbA2tg/RCFJo+UJZi34J8Pg2tmI7JvpGH -LVUqEAqNkcVuF2RitZ/h4KjuLOAgPfRe4uYavGJYXy84AyCxpwIXxchZ+P2RHIrU -dAD2VbTj+zjlO4fcKSfjzOi+RHOREMlQBFPDOIssZvbAQbW2wD9g66P4Yu3jl7wO -fDcJg6Ux0dRoBCeUPCWPqndYOgJ0DSv2cYCv/HcI07hA1xH38nxZrxPfKYAAFhXQ -vQy/T9Bb96KlpBwEQZN2ge6GH3k0Twyf1XhCiftHu5OHjW0fudOgPxqHJMPJ2VyS -QXvNn3LrsEyKBTNttmhjKnFahHKMfL332odr ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -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 -7ZAmQq6tNRH2Nd/K9JtkFHsG5v8tpz8= ------END PRIVATE KEY----- diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/proxy.pem b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/proxy.pem index 5a6c9b68fee9..b795e7dd6868 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/proxy.pem +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/proxy.pem @@ -1,83 +1,83 @@ -----BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgIJAPKFfaGVNxY0MA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV +MIIFWTCCA0GgAwIBAgIJAJGKeIrKYuZIMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8x -EzARBgNVBAoMClByZXN0b1Rlc3QxEzARBgNVBAMMClByZXN0b1Rlc3QwHhcNMjEx -MTI1MTQwMjQ0WhcNMzExMTIzMTQwMjQ0WjBgMQswCQYDVQQGEwJVUzETMBEGA1UE -CAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJUGFsbyBBbHRvMRMwEQYDVQQKDApQcmVz -dG9UZXN0MRMwEQYDVQQDDApQcmVzdG9UZXN0MIICIjANBgkqhkiG9w0BAQEFAAOC -Ag8AMIICCgKCAgEAz0lMy27eEa1cTuxE0PG4oc2eZOiijEHk+eP7aRf3DAfUnYAd -WCwu69qxV4Nb5mQQKRz/Gr1mrHjaYTIJirFYY4zNUUfxd6gPzyX6CSe3srL5QQIZ -HxT+AJcVOaIwARVhiu2hBRWdX50jS7ONPA8+ccSAeY40Xh+UtWm35TUOxfZc320d -03CjVcWwM5ygzaRmVtwQAjWZ9MfJ8U5NohdVspS7SN8gssI4KYd15MSceJeabvzq -b142aIMnmhVLvx27X6pub2IwmT5rmhDsxxXciRBUF5mGNhcS25lYycqJ0U7fZzbt -qA7sJidup5e3mPXdjmQgloeekDovHWxqp1qLVyNR2+pKN0pfVsbFR6oXrafU63G7 -ZMOkiyk+sii5WAmygyuRBGSsc/gPz9Ke6UVPAY428RNzGAKiMp2tES3byue5p8IK -bop1imo2xBIekIVjxmUP4s/QJ7VQAYmHIhEvRhNDKEg+18ZHcDTBYKGNx0aYtwrX -4nYtdLQ5mMmunOe2X2X41LWCB0vxP8cMnSmuhlWp4m57tSmDsjx3hozCOhDaV6Fa -ykzwzcnE3Dki6zW2d29r1pAd627UhWyE6Aqxk3vO6qorG8QTzU7UmGMGcRfALs+u -IHPOXXqt/U+6MhYdrJi/BcP8UQXjE0YbW3NBro0q/QwtRSoe3tqX8+DhR5cCAwEA -AaMUMBIwEAYDVR0RBAkwB4IFcHJveHkwDQYJKoZIhvcNAQELBQADggIBAG6jWgW8 -2MGNy8HEuKgY7LQTD3CqyaRrG3qpzz7YfXd0wJL6BA/TNOu7AMHMsoAFQn9Ua5t6 -H1lh0eFO7r3zovJRlaJPqwEw54EbgcimF1vOJNklWovPfuFopC1p8Q0pnA/2Qrpe -kEBrX9LUhDRT143UQ0e43EhT0MBXBtrUQhw7zgE88eh37nLz/HyS9UFFkFn1YmTY -czXfXcRVR1TB6EY10x2NQb889iHRzT3Pt23WwNcm6iKMkDNTn6HgmNUcE9db4fPV -bshvtb1HGLmZ/T8Se23XK0Wt5nLZ4n++sWyfMHQRsPALNZjCpxjT7sgITA4R4ikh -5WqTKjO+QCO8w+mQlVjBKbu7s4PVvj6VrsJzcE2TnmQedkqs29sEcpBW64R5B6gP -7ujoJwzYVQoAtK1RhwQglWxPcx7PbMvEQpiutnZ/DFo785EkfB3ha+NdDthoNod+ -4wtnE3IRdh/4lJN1bZtkVEEKyaToQe0veRXGtsmzUr4e2kW3ii/1usknkkSq+bC/ -JTDpRbVD1OIDx8q6TfVkU4r5egYzfYogGOXtZrr8gYzjbhBFZwGNS8ro1KNmpwxo -26RqbWOjmkRLO5tJPhUDBg9IxG5RSasAA8Zqn5IHh2G85sIyJ1rXkpe0aprC7uRY -YAdfq/7sPdurnpu8PXvw0/DVxd5np2x6qYp6 +EzARBgNVBAoMClByZXN0b1Rlc3QxEzARBgNVBAMMClByZXN0b1Rlc3QwIBcNMjEx +MjIzMDc0ODUwWhgPMjEyMTExMjkwNzQ4NTBaMGAxCzAJBgNVBAYTAlVTMRMwEQYD +VQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xEzARBgNVBAoMClBy +ZXN0b1Rlc3QxEzARBgNVBAMMClByZXN0b1Rlc3QwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC+j+uWvhNcqkEOfFu4ALDsy1r1osYEfWwD91jqaZy50wCP +YpOwMWbvAWvky+LB6ibJuEqjVfdqFicQvOWAJs1kWq86igKVybjQT/J8bv8cYtKJ +B5KwrfUNyU5g2nDz4v6O9xKO3+UE4WgWNoROGM54+jCNJixRWQDrVJp6ZcIKYcK1 +mdXATiZ1Df/P2YTXJJUdeUvDAwuR7YNX6GrYMsRH/et3vy1t7ySjni5otvdwd93v +H9OeUD9nr1qxHgaNcfH7sQU5pAERlXsFg8/w4nRufPK0iAOTV1P6YASXDAlRj9AW +TCySqvYCvGswRrLYb9YSWqXn//UvCk1UuAoFTZ16Mm0IxonWbMr74duOb0JUH1ZB +4S/TO4hc7cDQQI3Z+/B3q3uHsw5BiCAoZ04PW88x5UQfjTu+SGCG+zHXIINkdu++ +/F28AlAXzAskEDQjw2e4CoeF0LGCWZS1XSTMXNOdCG/6YeJfBu29iPa2nOA2+xDV +NcURdZb/nFY4LPv41z1EXLdTzo9g6sMZ/oQSU/z72Q12H2x2NHTTbXWExJTZuyL0 +YkL78/RV64Fox6ABm5U0sNVNaINW9iL+p6suuP3VtrxZpNmEjt0Ep16j+04BQ/P1 +tkEI7D9n6g3XImaPWjpS674ESRFN/1lPUseilPzhJuGlJ2ahtsYgGTk/tqjbxwID +AQABoxQwEjAQBgNVHREECTAHggVwcm94eTANBgkqhkiG9w0BAQsFAAOCAgEAQ1eY +T+GTohsYLD3OQPEw9qMPIs+WOhdG2z9jO0y82LfykVnXsv8MhlYZ26uinu2QLLmc +Ufdz63CAU1d5jIRyLJ160dpALWuF2v9Dh7dKLarIlFVs9k6fkN2c1Xw3do1d1OqU +d4lNU5Rc1+lFbROi06OBavAVqRVzl00JR2krRqX+PZaHD6EGUC00n120R+Vse3E+ +Ed+cAb3lfy8TOE6psahEHX+kDW3rwR/amY4Hh8ZIlSlEShnoi4ruvrxClT7OfPxQ +2DM7MM62TFwjVRq8rsc2HfuAYTvwOE5wXeIVW+TwflpWjivTeQuBDqAzA4v1Ady0 +2oj/x1TmMgLs6htn5fwUKQ8YGy2IzbgVkugYO7/1hVfXGHS4cEtkDQFAOLnlTjVv +QbxwYS8xaRINI8jXIMAQR2TqEDIGCC2W5ZlPemSGwENaAc71S8GHWtf25TEpuepK +B6HwoF687Vd5utDW/ICqHjjzYey1DkXgQJ/5sCT+NhSS5C6xTeL5wbSLfDB/YhPV +EaChOG5pedvp+22Gz9BMzyEDQh58Qce7EiCAh76lsz0QBXE+OhVwTV2ZIS+w9fY7 +EOUeObHyYrT3Yqdl7ETuPxIxNB6MpxXi7w0qGgtpu57Cz/+04vLDM9reij2hEBwW +e0Mw1IhmXOkVga8UlCzctkUrFp+2Da6z/KX3gk0= -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- -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 -H5XnZiQqrccTT4vob9YGhsTMx4239gY= +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 +WeqKrlt4TvvXTkV/ic8cWtqnkgkD -----END PRIVATE KEY----- diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/truststore.jks b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/cert/truststore.jks index 46fce42b7d9d5ea7de2b99e6d281eca3e9ba6736..1c626c72be4f8f0c44e7b582fd5a9f8bec608a6e 100644 GIT binary patch delta 4342 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 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties index c637bd72bb92..81beb0871bdb 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties @@ -12,8 +12,7 @@ web-ui.enabled=true http-server.authentication.type=oauth2 http-server.https.port=7778 http-server.https.enabled=true -http-server.https.keystore.path=/docker/presto-product-tests/conf/presto/etc/presto-master.jks -http-server.https.keystore.key=123456 +http-server.https.keystore.path=/docker/presto-product-tests/conf/presto/etc/trino.pem http-server.authentication.oauth2.issuer=https://hydra:4444/ http-server.authentication.oauth2.auth-url=https://hydra:4444/oauth2/auth http-server.authentication.oauth2.token-url=https://hydra:4444/oauth2/token @@ -22,6 +21,6 @@ http-server.authentication.oauth2.client-id=trinodb_client_id http-server.authentication.oauth2.client-secret=trinodb_client_secret http-server.authentication.oauth2.user-mapping.pattern=(.*)(@.*)? oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/cert/truststore.jks -oauth2-jwk.http-client.trust-store-password=changeit +oauth2-jwk.http-client.trust-store-password=123456 oauth2-jwk.http-client.http-proxy=proxy:8888 oauth2-jwk.http-client.http-proxy.secure=true diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties index 120c6068b157..bfed2a42b4fb 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties @@ -12,8 +12,7 @@ web-ui.enabled=true http-server.authentication.type=oauth2 http-server.https.port=7778 http-server.https.enabled=true -http-server.https.keystore.path=/docker/presto-product-tests/conf/presto/etc/presto-master.jks -http-server.https.keystore.key=123456 +http-server.https.keystore.path=/docker/presto-product-tests/conf/presto/etc/trino.pem http-server.authentication.oauth2.issuer=https://hydra:4444/ http-server.authentication.oauth2.auth-url=https://hydra:4444/oauth2/auth http-server.authentication.oauth2.token-url=https://hydra:4444/oauth2/token @@ -21,4 +20,4 @@ http-server.authentication.oauth2.jwks-url=https://hydra:4444/.well-known/jwks.j http-server.authentication.oauth2.client-id=trinodb_client_id http-server.authentication.oauth2.client-secret=trinodb_client_secret http-server.authentication.oauth2.user-mapping.pattern=(.*)(@.*)? -oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/hydra/cert/localhost.pem +oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/hydra.pem diff --git a/testing/trino-product-tests-launcher/src/test/java/io/trino/tests/product/launcher/local/TestManuallyJdbcOauth2.java b/testing/trino-product-tests-launcher/src/test/java/io/trino/tests/product/launcher/local/TestManuallyJdbcOauth2.java index 397ea606189e..8c474d9f9239 100644 --- a/testing/trino-product-tests-launcher/src/test/java/io/trino/tests/product/launcher/local/TestManuallyJdbcOauth2.java +++ b/testing/trino-product-tests-launcher/src/test/java/io/trino/tests/product/launcher/local/TestManuallyJdbcOauth2.java @@ -48,7 +48,7 @@ public void verifyEtcHostsEntries() /** * This test is here to allow manually tests OAuth2 implementation through jdbc. * It's configured in a way that allows it to connect to SinglenodeOauth2 environment. In order for it to work, - * one must add to /etc/hosts following entries. They need to be removed before running Selenium tests against SinglenodeHydraSelenium environment. + * one must add to /etc/hosts following entries. They need to be removed before running automated tests against SinglenodeOAuth2* environments. * 127.0.0.1 presto-master * 127.0.0.1 hydra * 127.0.0.1 hydra-consent diff --git a/testing/trino-product-tests/pom.xml b/testing/trino-product-tests/pom.xml index a1edd7aaa2e0..4134d146e55c 100644 --- a/testing/trino-product-tests/pom.xml +++ b/testing/trino-product-tests/pom.xml @@ -111,6 +111,21 @@ guice + + com.squareup.okhttp3 + okhttp + + + + com.squareup.okhttp3 + okhttp-tls + + + + com.squareup.okhttp3 + okhttp-urlconnection + + io.confluent kafka-schema-registry-client @@ -141,32 +156,6 @@ annotations - - org.seleniumhq.selenium - selenium-api - - - - org.seleniumhq.selenium - selenium-chrome-driver - - - com.squareup.okio - okio - - - - - - org.seleniumhq.selenium - selenium-remote-driver - - - - org.seleniumhq.selenium - selenium-support - - org.testng testng diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java index 7e6d4c8b5212..0e64d3dc6161 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java @@ -15,179 +15,135 @@ import com.google.inject.Inject; import com.google.inject.name.Named; -import io.airlift.log.Logger; import io.trino.jdbc.TestingRedirectHandlerInjector; +import io.trino.tempto.BeforeTestWithContext; import io.trino.tempto.ProductTest; -import io.trino.testng.services.Flaky; import io.trino.tests.product.TpchTableResults; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.support.ui.WebDriverWait; -import org.testng.annotations.AfterClass; +import okhttp3.JavaNetCookieJar; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.tls.HandshakeCertificates; import org.testng.annotations.Test; -import java.net.MalformedURLException; -import java.net.URL; +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.CookieManager; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Properties; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import static com.google.common.util.concurrent.Futures.immediateFailedFuture; +import static com.google.common.base.Preconditions.checkState; import static io.trino.tempto.assertions.QueryAssert.assertThat; import static io.trino.tempto.query.QueryResult.forResultSet; import static io.trino.tests.product.TestGroups.OAUTH2; import static io.trino.tests.product.TestGroups.PROFILE_SPECIFIC_TESTS; -import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable; public class TestExternalAuthorizerOAuth2 extends ProductTest { - private static final Logger log = Logger.get(TestExternalAuthorizerOAuth2.class); - @Inject @Named("databases.presto.jdbc_url") String jdbcUrl; - private final ExecutorService executor = newSingleThreadExecutor(); - private Future lastLoginAction; + @Inject + @Named("databases.presto.https_keystore_path") + String truststorePath; + + @Inject + @Named("databases.presto.https_keystore_password") + String truststorePassword; + + private OkHttpClient httpClient; - @AfterClass(alwaysRun = true) - public void clean() - throws InterruptedException + @BeforeTestWithContext + public void setUp() + throws Exception { - executor.shutdown(); - executor.awaitTermination(10, SECONDS); + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); + KeyStore keyStore = KeyStore.getInstance(new File(truststorePath), truststorePassword.toCharArray()); + HandshakeCertificates.Builder certificatesBuilder = new HandshakeCertificates.Builder(); + keyStore.aliases().asIterator().forEachRemaining(alias -> { + try { + Certificate certificate = keyStore.getCertificate(alias); + if (certificate instanceof X509Certificate) { + certificatesBuilder.addTrustedCertificate((X509Certificate) certificate); + } + } + catch (KeyStoreException e) { + throw new RuntimeException(e); + } + }); + HandshakeCertificates certificates = certificatesBuilder.build(); + httpClientBuilder.sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager()); + httpClientBuilder.followRedirects(true); + httpClientBuilder.cookieJar(new JavaNetCookieJar(new CookieManager())); + httpClient = httpClientBuilder.build(); } @Test(groups = {OAUTH2, PROFILE_SPECIFIC_TESTS}) - @Flaky(issue = "https://github.com/trinodb/trino/issues/6991", match = "Last login action has failed with exception") public void shouldAuthenticateAndExecuteQuery() throws Exception { - prepareSeleniumHandler(); + prepareHandler(); Properties properties = new Properties(); properties.setProperty("user", "test"); try (Connection connection = DriverManager.getConnection(jdbcUrl, properties); PreparedStatement statement = connection.prepareStatement("SELECT * FROM tpch.tiny.nation"); ResultSet results = statement.executeQuery()) { - assertSuccessfulLogin(); assertThat(forResultSet(results)).matches(TpchTableResults.PRESTO_NATION_RESULT); } } @Test(groups = {OAUTH2, PROFILE_SPECIFIC_TESTS}) - @Flaky(issue = "https://github.com/trinodb/trino/issues/6991", match = "Last login action has failed with exception") public void shouldAuthenticateAfterTokenExpires() throws Exception { - prepareSeleniumHandler(); + prepareHandler(); Properties properties = new Properties(); properties.setProperty("user", "test"); try (Connection connection = DriverManager.getConnection(jdbcUrl, properties); PreparedStatement statement = connection.prepareStatement("SELECT * FROM tpch.tiny.nation"); ResultSet results = statement.executeQuery()) { - assertSuccessfulLogin(); + assertThat(forResultSet(results)).matches(TpchTableResults.PRESTO_NATION_RESULT); //Wait until the token expires. See: HydraIdentityProvider.TTL_ACCESS_TOKEN_IN_SECONDS SECONDS.sleep(10); try (PreparedStatement repeatedStatement = connection.prepareStatement("SELECT * FROM tpch.tiny.nation"); ResultSet repeatedResults = repeatedStatement.executeQuery()) { - assertSuccessfulLogin(); assertThat(forResultSet(repeatedResults)).matches(TpchTableResults.PRESTO_NATION_RESULT); } } } - private void prepareSeleniumHandler() + private void prepareHandler() { - lastLoginAction = immediateFailedFuture(new AssertionError("Login action has not been triggered")); TestingRedirectHandlerInjector.setRedirectHandler(uri -> { - lastLoginAction = executor.submit(() -> { - WebDriver driver = getWebDriver(); - driver.get(uri.toString()); - WebDriverWait wait = new WebDriverWait(driver, 10); - submitCredentials(driver, "foo@bar.com", "foobar", wait); - giveConsent(driver, wait); - }); - }); - } - - private WebDriver getWebDriver() - { - ChromeOptions options = new ChromeOptions(); - options.setAcceptInsecureCerts(true); - return new RemoteWebDriver(getWebDriverUrl(), options); - } - - private URL getWebDriverUrl() - { - try { - return new URL("http", "selenium-chrome", 7777, "/wd/hub"); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - - private void submitCredentials(WebDriver driver, String email, String password, WebDriverWait wait) - { - log.info("trying to submit credentials"); - By emailElementLocator = By.id("email"); - log.info("waiting for email field"); - wait.until(elementToBeClickable(emailElementLocator)); - log.info("email field found"); - WebElement usernameElement = driver.findElement(emailElementLocator); - usernameElement.sendKeys(email); - log.info("email field set to %s", email); - log.info("waiting for password field"); - By passwordElementLocator = By.id("password"); - wait.until(elementToBeClickable(passwordElementLocator)); - log.info("password field found"); - WebElement passwordElement = driver.findElement(passwordElementLocator); - passwordElement.sendKeys(password + "\n"); - log.info("password field set to %s", password); - } - - private void giveConsent(WebDriver driver, WebDriverWait wait) - { - log.info("trying to give consent"); - log.info("waiting for openId checkbox"); - By openIdCheckboxLocator = By.id("openid"); - wait.until(elementToBeClickable(openIdCheckboxLocator)); - log.info("openId checkbox found"); - WebElement openIdCheckbox = driver.findElement(openIdCheckboxLocator); - openIdCheckbox.click(); - log.info("openId checkbox clicked"); - log.info("waiting for accept button"); - By acceptButtonLocator = By.id("accept"); - wait.until(elementToBeClickable(acceptButtonLocator)); - log.info("accept button found"); - WebElement acceptButton = driver.findElement(acceptButtonLocator); - acceptButton.click(); - log.info("accept button clicked"); - } - - private void assertSuccessfulLogin() - throws Exception - { - try { - lastLoginAction.get(); - } - catch (ExecutionException e) { - if (e.getCause() != null) { - throw new AssertionError("Last login action has failed with exception", e.getCause()); + try (Response response = httpClient.newCall( + new Request.Builder() + .get() + .url(uri.toString()) + .build()) + .execute()) { + int statusCode = response.code(); + checkState(statusCode == 200, "Invalid status %s", statusCode); + requireNonNull(response.body(), "body is null"); + String body = response.body().string(); + checkState(body.contains("OAuth2 authentication succeeded"), "Invalid response %s", body); } - throw e; - } + catch (IOException e) { + throw new UncheckedIOException(e); + } + }); } } From d842185deacb49fb28be82716206eac952378ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Walkiewicz?= Date: Fri, 10 Dec 2021 08:56:21 +0100 Subject: [PATCH 11/11] Support passing groups in OAuth access token claim --- .../security/oauth2/OAuth2Authenticator.java | 12 ++- .../server/security/oauth2/OAuth2Config.java | 14 +++ .../ui/OAuth2WebUiAuthenticationFilter.java | 11 ++- .../server/security/TestResourceSecurity.java | 94 ++++++++++++++++++- .../security/oauth2/TestOAuth2Config.java | 3 + docs/src/main/sphinx/security/oauth2.rst | 2 + .../env/common/HydraIdentityProvider.java | 1 + .../config.properties | 1 + .../config.properties | 1 + .../singlenode-oauth2/config.properties | 1 + .../jdbc/TestExternalAuthorizerOAuth2.java | 16 ++++ 11 files changed, 148 insertions(+), 8 deletions(-) diff --git a/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java b/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java index 2d076912b729..23f391e7542a 100644 --- a/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java +++ b/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Authenticator.java @@ -13,6 +13,7 @@ */ package io.trino.server.security.oauth2; +import com.google.common.collect.ImmutableSet; import io.trino.server.security.AbstractBearerAuthenticator; import io.trino.server.security.AuthenticationException; import io.trino.server.security.UserMapping; @@ -24,6 +25,7 @@ import javax.ws.rs.container.ContainerRequestContext; import java.net.URI; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -39,6 +41,7 @@ public class OAuth2Authenticator { private final OAuth2Service service; private final String principalField; + private final Optional groupsField; private final UserMapping userMapping; @Inject @@ -46,6 +49,7 @@ public OAuth2Authenticator(OAuth2Service service, OAuth2Config config) { this.service = requireNonNull(service, "service is null"); this.principalField = config.getPrincipalField(); + groupsField = requireNonNull(config.getGroupsField(), "groupsField is null"); userMapping = createUserMapping(config.getUserMappingPattern(), config.getUserMappingFile()); } @@ -59,9 +63,11 @@ protected Optional createIdentity(String token) return Optional.empty(); } String principal = (String) claims.get().get(principalField); - return Optional.of(Identity.forUser(userMapping.mapUser(principal)) - .withPrincipal(new BasicPrincipal(principal)) - .build()); + Identity.Builder builder = Identity.forUser(userMapping.mapUser(principal)); + builder.withPrincipal(new BasicPrincipal(principal)); + groupsField.flatMap(field -> Optional.ofNullable((List) claims.get().get(field))) + .ifPresent(groups -> builder.withGroups(ImmutableSet.copyOf(groups))); + return Optional.of(builder.build()); } catch (ChallengeFailedException e) { return Optional.empty(); diff --git a/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Config.java b/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Config.java index 5f978467907f..fb8bc874f012 100644 --- a/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Config.java +++ b/core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Config.java @@ -49,6 +49,7 @@ public class OAuth2Config private String clientSecret; private Set scopes = ImmutableSet.of(OPENID_SCOPE); private String principalField = "sub"; + private Optional groupsField = Optional.empty(); private List additionalAudiences = Collections.emptyList(); private Duration challengeTimeout = new Duration(15, TimeUnit.MINUTES); private Optional userMappingPattern = Optional.empty(); @@ -222,6 +223,19 @@ public OAuth2Config setPrincipalField(String principalField) return this; } + public Optional getGroupsField() + { + return groupsField; + } + + @Config("http-server.authentication.oauth2.groups-field") + @ConfigDescription("Groups field in the claim") + public OAuth2Config setGroupsField(String groupsField) + { + this.groupsField = Optional.ofNullable(groupsField); + return this; + } + @MinDuration("1ms") @NotNull public Duration getChallengeTimeout() diff --git a/core/trino-main/src/main/java/io/trino/server/ui/OAuth2WebUiAuthenticationFilter.java b/core/trino-main/src/main/java/io/trino/server/ui/OAuth2WebUiAuthenticationFilter.java index e259e4db9642..a4a9ddf6fab8 100644 --- a/core/trino-main/src/main/java/io/trino/server/ui/OAuth2WebUiAuthenticationFilter.java +++ b/core/trino-main/src/main/java/io/trino/server/ui/OAuth2WebUiAuthenticationFilter.java @@ -28,6 +28,7 @@ import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.core.Response; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -50,6 +51,7 @@ public class OAuth2WebUiAuthenticationFilter private final String principalField; private final OAuth2Service service; private final UserMapping userMapping; + private final Optional groupsField; @Inject public OAuth2WebUiAuthenticationFilter(OAuth2Service service, OAuth2Config oauth2Config) @@ -58,6 +60,7 @@ public OAuth2WebUiAuthenticationFilter(OAuth2Service service, OAuth2Config oauth requireNonNull(oauth2Config, "oauth2Config is null"); this.userMapping = UserMapping.createUserMapping(oauth2Config.getUserMappingPattern(), oauth2Config.getUserMappingFile()); this.principalField = oauth2Config.getPrincipalField(); + groupsField = requireNonNull(oauth2Config.getGroupsField(), "groupsField is null"); } @Override @@ -101,9 +104,11 @@ public void filter(ContainerRequestContext request) return; } String principalName = (String) principal; - setAuthenticatedIdentity(request, Identity.forUser(userMapping.mapUser(principalName)) - .withPrincipal(new BasicPrincipal(principalName)) - .build()); + Identity.Builder builder = Identity.forUser(userMapping.mapUser(principalName)); + builder.withPrincipal(new BasicPrincipal(principalName)); + groupsField.flatMap(field -> Optional.ofNullable((List) claims.get().get(field))) + .ifPresent(groups -> builder.withGroups(ImmutableSet.copyOf(groups))); + setAuthenticatedIdentity(request, builder.build()); } catch (UserMappingException e) { sendErrorMessage(request, UNAUTHORIZED, firstNonNull(e.getMessage(), "Unauthorized")); diff --git a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java index fea21f3f92f9..8923f9f6887a 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java +++ b/core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java @@ -15,6 +15,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.io.Resources; @@ -38,13 +39,17 @@ import io.trino.spi.security.BasicPrincipal; import io.trino.spi.security.Identity; import io.trino.spi.security.SystemSecurityContext; +import okhttp3.Cookie; +import okhttp3.CookieJar; import okhttp3.Credentials; import okhttp3.Headers; +import okhttp3.HttpUrl; import okhttp3.JavaNetCookieJar; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import javax.crypto.SecretKey; @@ -90,7 +95,10 @@ import static io.trino.client.ProtocolHeaders.TRINO_HEADERS; import static io.trino.metadata.MetadataManager.createTestMetadataManager; import static io.trino.server.security.ResourceSecurity.AccessType.AUTHENTICATED_USER; +import static io.trino.server.security.ResourceSecurity.AccessType.WEB_UI; import static io.trino.server.security.oauth2.OAuth2Service.NONCE; +import static io.trino.server.ui.FormWebUiAuthenticationFilter.UI_LOCATION; +import static io.trino.server.ui.OAuthWebUiCookie.OAUTH2_COOKIE; import static io.trino.spi.security.AccessDeniedException.denyImpersonateUser; import static io.trino.spi.security.AccessDeniedException.denyReadSystemInformationAccess; import static io.trino.testing.assertions.Assert.assertEquals; @@ -130,6 +138,7 @@ public class TestResourceSecurity private static final String MANAGEMENT_PASSWORD = "management-password"; private static final String HMAC_KEY = Resources.getResource("hmac_key.txt").getPath(); private static final String JWK_KEY_ID = "test-rsa"; + private static final String GROUPS_CLAIM = "groups"; private static final PrivateKey JWK_PRIVATE_KEY; private static final ObjectMapper json = new ObjectMapper(); @@ -655,6 +664,86 @@ public HttpCookie getNonceCookie() } } + @Test(dataProvider = "groups") + public void testOAuth2Groups(Optional> groups) + throws Exception + { + try (TokenServer tokenServer = new TokenServer(Optional.empty()); + TestingTrinoServer server = TestingTrinoServer.builder() + .setProperties(ImmutableMap.builder() + .putAll(SECURE_PROPERTIES) + .put("web-ui.enabled", "true") + .putAll(getOAuth2Properties(tokenServer)) + .put("http-server.authentication.oauth2.groups-field", GROUPS_CLAIM) + .build()) + .setAdditionalModule(oauth2Module(tokenServer)) + .build()) { + server.getInstance(Key.get(AccessControlManager.class)).addSystemAccessControl(TestSystemAccessControl.NO_IMPERSONATION); + HttpServerInfo httpServerInfo = server.getInstance(Key.get(HttpServerInfo.class)); + + String accessToken = tokenServer.issueAccessToken(groups); + OkHttpClient clientWithOAuthToken = client.newBuilder() + .authenticator((route, response) -> response.request().newBuilder() + .header(AUTHORIZATION, "Bearer " + accessToken) + .build()) + .build(); + + assertAuthenticationAutomatic(httpServerInfo.getHttpsUri(), clientWithOAuthToken); + + try (Response response = clientWithOAuthToken.newCall(new Request.Builder() + .url(getLocation(httpServerInfo.getHttpsUri(), "/protocol/identity")) + .build()) + .execute()) { + assertEquals(response.code(), SC_OK); + assertEquals(response.header("user"), TEST_USER); + assertEquals(response.header("principal"), TEST_USER); + assertEquals(response.header("groups"), groups.map(TestResource::toHeader).orElse("")); + } + + OkHttpClient clientWithOAuthCookie = client.newBuilder() + .cookieJar(new CookieJar() + { + @Override + public void saveFromResponse(HttpUrl url, List cookies) + { + } + + @Override + public List loadForRequest(HttpUrl url) + { + return ImmutableList.of(new Cookie.Builder() + .domain(httpServerInfo.getHttpsUri().getHost()) + .path(UI_LOCATION) + .name(OAUTH2_COOKIE) + .value(accessToken) + .httpOnly() + .secure() + .build()); + } + }) + .build(); + try (Response response = clientWithOAuthCookie.newCall(new Request.Builder() + .url(getLocation(httpServerInfo.getHttpsUri(), "/ui/api/identity")) + .build()) + .execute()) { + assertEquals(response.code(), SC_OK); + assertEquals(response.header("user"), TEST_USER); + assertEquals(response.header("principal"), TEST_USER); + assertEquals(response.header("groups"), groups.map(TestResource::toHeader).orElse("")); + } + } + } + + @DataProvider(name = "groups") + public static Object[][] groups() + { + return new Object[][] { + {Optional.empty()}, + {Optional.of(ImmutableSet.of())}, + {Optional.of(ImmutableSet.of("admin", "public"))} + }; + } + private static Module oauth2Module(TokenServer tokenServer) { return binder -> { @@ -707,7 +796,7 @@ public TokenServer(Optional principalField) this.principalField = requireNonNull(principalField, "principalField is null"); jwkServer = createTestingJwkServer(); jwkServer.start(); - accessToken = issueAccessToken(); + accessToken = issueAccessToken(Optional.empty()); } @Override @@ -767,7 +856,7 @@ public String getAccessToken() return accessToken; } - private String issueAccessToken() + public String issueAccessToken(Optional> groups) { JwtBuilder accessToken = Jwts.builder() .signWith(JWK_PRIVATE_KEY) @@ -781,6 +870,7 @@ private String issueAccessToken() else { accessToken.setSubject(TEST_USER); } + groups.ifPresent(groupsClaim -> accessToken.claim(GROUPS_CLAIM, groupsClaim)); return accessToken.compact(); } diff --git a/core/trino-main/src/test/java/io/trino/server/security/oauth2/TestOAuth2Config.java b/core/trino-main/src/test/java/io/trino/server/security/oauth2/TestOAuth2Config.java index 5f230415ccd3..e7b480df2d95 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/oauth2/TestOAuth2Config.java +++ b/core/trino-main/src/test/java/io/trino/server/security/oauth2/TestOAuth2Config.java @@ -48,6 +48,7 @@ public void testDefaults() .setScopes("openid") .setChallengeTimeout(new Duration(15, MINUTES)) .setPrincipalField("sub") + .setGroupsField(null) .setAdditionalAudiences(Collections.emptyList()) .setUserMappingPattern(null) .setUserMappingFile(null)); @@ -70,6 +71,7 @@ public void testExplicitPropertyMappings() .put("http-server.authentication.oauth2.client-secret", "consumer-secret") .put("http-server.authentication.oauth2.scopes", "email,offline") .put("http-server.authentication.oauth2.principal-field", "some-field") + .put("http-server.authentication.oauth2.groups-field", "groups") .put("http-server.authentication.oauth2.additional-audiences", "test-aud1,test-aud2") .put("http-server.authentication.oauth2.challenge-timeout", "90s") .put("http-server.authentication.oauth2.user-mapping.pattern", "(.*)@something") @@ -88,6 +90,7 @@ public void testExplicitPropertyMappings() .setClientSecret("consumer-secret") .setScopes("email, offline") .setPrincipalField("some-field") + .setGroupsField("groups") .setAdditionalAudiences(List.of("test-aud1", "test-aud2")) .setChallengeTimeout(new Duration(90, SECONDS)) .setUserMappingPattern("(.*)@something") diff --git a/docs/src/main/sphinx/security/oauth2.rst b/docs/src/main/sphinx/security/oauth2.rst index 40f9795ea038..d1eb7936a0d7 100644 --- a/docs/src/main/sphinx/security/oauth2.rst +++ b/docs/src/main/sphinx/security/oauth2.rst @@ -108,6 +108,8 @@ The following configuration properties are available: for more information. * - ``http-server.authentication.oauth2.principal-field`` - The field of the access token used for the Trino user principal. Defaults to ``sub``. Other commonly used fields include ``sAMAccountName``, ``name``, ``upn``, and ``email``. + * - ``http-server.authentication.oauth2.groups-field`` + - The field of the access token used for Trino groups. The corresponding claim value must be an array. Troubleshooting diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java index c25abb287026..4903411dcb75 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/common/HydraIdentityProvider.java @@ -81,6 +81,7 @@ public void extendEnvironment(Environment.Builder builder) .withEnv("SERVE_TLS_CERT_PATH", "/tmp/certs/hydra.pem") .withEnv("STRATEGIES_ACCESS_TOKEN", "jwt") .withEnv("TTL_ACCESS_TOKEN", TTL_ACCESS_TOKEN_IN_SECONDS + "s") + .withEnv("OAUTH2_ALLOWED_TOP_LEVEL_CLAIMS", "groups") .withCommand("serve", "all") .withCopyFileToContainer(forHostPath(configDir.getPath("cert/hydra.pem")), "/tmp/certs/hydra.pem") .waitingFor(new WaitAllStrategy() diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties index 0f2310114f28..eb688dd78ad9 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-http-proxy/config.properties @@ -20,5 +20,6 @@ http-server.authentication.oauth2.jwks-url=https://hydra:4444/.well-known/jwks.j http-server.authentication.oauth2.client-id=trinodb_client_id http-server.authentication.oauth2.client-secret=trinodb_client_secret http-server.authentication.oauth2.user-mapping.pattern=(.*)(@.*)? +http-server.authentication.oauth2.groups-field=groups oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/hydra.pem oauth2-jwk.http-client.http-proxy=proxy:8888 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties index 81beb0871bdb..d6162c783551 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2-https-proxy/config.properties @@ -20,6 +20,7 @@ http-server.authentication.oauth2.jwks-url=https://hydra:4444/.well-known/jwks.j http-server.authentication.oauth2.client-id=trinodb_client_id http-server.authentication.oauth2.client-secret=trinodb_client_secret http-server.authentication.oauth2.user-mapping.pattern=(.*)(@.*)? +http-server.authentication.oauth2.groups-field=groups oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/cert/truststore.jks oauth2-jwk.http-client.trust-store-password=123456 oauth2-jwk.http-client.http-proxy=proxy:8888 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties index bfed2a42b4fb..67d9be99b3f4 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-oauth2/config.properties @@ -20,4 +20,5 @@ http-server.authentication.oauth2.jwks-url=https://hydra:4444/.well-known/jwks.j http-server.authentication.oauth2.client-id=trinodb_client_id http-server.authentication.oauth2.client-secret=trinodb_client_secret http-server.authentication.oauth2.user-mapping.pattern=(.*)(@.*)? +http-server.authentication.oauth2.groups-field=groups oauth2-jwk.http-client.trust-store-path=/docker/presto-product-tests/conf/presto/etc/hydra.pem diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java index 0e64d3dc6161..1eb9a80c4f40 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/jdbc/TestExternalAuthorizerOAuth2.java @@ -13,6 +13,7 @@ */ package io.trino.tests.product.jdbc; +import com.google.common.collect.ImmutableList; import com.google.inject.Inject; import com.google.inject.name.Named; import io.trino.jdbc.TestingRedirectHandlerInjector; @@ -42,6 +43,7 @@ import java.util.Properties; import static com.google.common.base.Preconditions.checkState; +import static io.trino.tempto.assertions.QueryAssert.Row.row; import static io.trino.tempto.assertions.QueryAssert.assertThat; import static io.trino.tempto.query.QueryResult.forResultSet; import static io.trino.tests.product.TestGroups.OAUTH2; @@ -126,6 +128,20 @@ public void shouldAuthenticateAfterTokenExpires() } } + @Test(groups = {OAUTH2, PROFILE_SPECIFIC_TESTS}) + public void shouldReturnGroups() + throws SQLException + { + prepareHandler(); + Properties properties = new Properties(); + properties.setProperty("user", "test"); + try (Connection connection = DriverManager.getConnection(jdbcUrl, properties); + PreparedStatement statement = connection.prepareStatement("SELECT array_sort(current_groups())"); + ResultSet rs = statement.executeQuery()) { + assertThat(forResultSet(rs)).containsOnly(row(ImmutableList.of("admin", "public"))); + } + } + private void prepareHandler() { TestingRedirectHandlerInjector.setRedirectHandler(uri -> {