From ce7188a0fe2ef2335a259dbde27d401517ff7b8b Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 18 Apr 2025 17:02:14 +0200 Subject: [PATCH] Remove "test" Authenticator --- .../config/ProductionReadinessChecks.java | 29 ----- ...InlineBearerTokenPolarisAuthenticator.java | 107 ---------------- .../service/auth/TestOAuth2ApiService.java | 118 ------------------ 3 files changed, 254 deletions(-) delete mode 100644 service/common/src/main/java/org/apache/polaris/service/auth/TestInlineBearerTokenPolarisAuthenticator.java delete mode 100644 service/common/src/main/java/org/apache/polaris/service/auth/TestOAuth2ApiService.java diff --git a/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/ProductionReadinessChecks.java b/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/ProductionReadinessChecks.java index b69e5318c9..bac6ba02f7 100644 --- a/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/ProductionReadinessChecks.java +++ b/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/ProductionReadinessChecks.java @@ -26,20 +26,15 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; -import org.apache.polaris.core.auth.AuthenticatedPolarisPrincipal; import org.apache.polaris.core.config.ProductionReadinessCheck; import org.apache.polaris.core.config.ProductionReadinessCheck.Error; import org.apache.polaris.core.persistence.MetaStoreManagerFactory; import org.apache.polaris.service.auth.AuthenticationConfiguration; import org.apache.polaris.service.auth.AuthenticationConfiguration.TokenBrokerConfiguration.RSAKeyPairConfiguration; import org.apache.polaris.service.auth.AuthenticationConfiguration.TokenBrokerConfiguration.SymmetricKeyConfiguration; -import org.apache.polaris.service.auth.Authenticator; import org.apache.polaris.service.auth.JWTRSAKeyPairFactory; import org.apache.polaris.service.auth.JWTSymmetricKeyFactory; -import org.apache.polaris.service.auth.TestInlineBearerTokenPolarisAuthenticator; -import org.apache.polaris.service.auth.TestOAuth2ApiService; import org.apache.polaris.service.auth.TokenBrokerFactory; -import org.apache.polaris.service.catalog.api.IcebergRestOAuth2ApiService; import org.apache.polaris.service.context.DefaultRealmContextResolver; import org.apache.polaris.service.context.RealmContextResolver; import org.apache.polaris.service.context.TestRealmContextResolver; @@ -84,30 +79,6 @@ public void warnOnFailedChecks( } } - @Produces - public ProductionReadinessCheck checkAuthenticator( - Authenticator authenticator) { - if (authenticator instanceof TestInlineBearerTokenPolarisAuthenticator) { - return ProductionReadinessCheck.of( - Error.of( - "The current authenticator is intended for tests only.", - "polaris.authentication.authenticator.type")); - } - - return ProductionReadinessCheck.OK; - } - - @Produces - public ProductionReadinessCheck checkTokenService(IcebergRestOAuth2ApiService service) { - if (service instanceof TestOAuth2ApiService) { - return ProductionReadinessCheck.of( - Error.of( - "The current token service is intended for tests only.", - "polaris.authentication.token-service.type")); - } - return ProductionReadinessCheck.OK; - } - @Produces public ProductionReadinessCheck checkTokenBroker( AuthenticationConfiguration configuration, TokenBrokerFactory factory) { diff --git a/service/common/src/main/java/org/apache/polaris/service/auth/TestInlineBearerTokenPolarisAuthenticator.java b/service/common/src/main/java/org/apache/polaris/service/auth/TestInlineBearerTokenPolarisAuthenticator.java deleted file mode 100644 index cd4b914aab..0000000000 --- a/service/common/src/main/java/org/apache/polaris/service/auth/TestInlineBearerTokenPolarisAuthenticator.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.polaris.service.auth; - -import com.google.common.base.Splitter; -import io.smallrye.common.annotation.Identifier; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import org.apache.polaris.core.auth.AuthenticatedPolarisPrincipal; -import org.apache.polaris.core.context.CallContext; -import org.apache.polaris.core.entity.PolarisPrincipalSecrets; -import org.apache.polaris.core.persistence.MetaStoreManagerFactory; -import org.apache.polaris.core.persistence.PolarisMetaStoreManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * {@link Authenticator} that parses a token as a sequence of key/value pairs. Specifically, we - * expect to find - * - * - * - * This class does not expect a client to be either present or correct. Lookup is delegated to the - * {@link PolarisMetaStoreManager} for the current realm. - */ -@RequestScoped -@Identifier("test") -public class TestInlineBearerTokenPolarisAuthenticator extends BasePolarisAuthenticator { - private static final Logger LOGGER = - LoggerFactory.getLogger(TestInlineBearerTokenPolarisAuthenticator.class); - - public TestInlineBearerTokenPolarisAuthenticator() { - this(null, null); - } - - @Inject - public TestInlineBearerTokenPolarisAuthenticator( - MetaStoreManagerFactory metaStoreManagerFactory, CallContext callContext) { - super(metaStoreManagerFactory, callContext); - } - - @Override - public Optional authenticate(String credentials) { - Map properties = extractPrincipal(credentials); - PolarisMetaStoreManager metaStoreManager = - metaStoreManagerFactory.getOrCreateMetaStoreManager(callContext.getRealmContext()); - String principal = properties.get("principal"); - - LOGGER.info("Checking for existence of principal {} in map {}", principal, properties); - - TokenInfoExchangeResponse tokenInfo = new TokenInfoExchangeResponse(); - tokenInfo.setSub(principal); - if (properties.get("role") != null) { - tokenInfo.setScope( - Arrays.stream(properties.get("role").split(" ")) - .map(r -> PRINCIPAL_ROLE_PREFIX + r) - .collect(Collectors.joining(" "))); - } - - PolarisPrincipalSecrets secrets = - metaStoreManager - .loadPrincipalSecrets(callContext.getPolarisCallContext(), principal) - .getPrincipalSecrets(); - if (secrets == null) { - // For test scenarios, if we're allowing short-circuiting into the bearer flow, there may - // not be a clientId/clientSecret, and instead we'll let the BasePolarisAuthenticator - // resolve the principal by name from the persistence store. - LOGGER.warn("Failed to load secrets for principal {}", principal); - } else { - tokenInfo.setIntegrationId(secrets.getPrincipalId()); - } - - return getPrincipal(tokenInfo); - } - - private static Map extractPrincipal(String credentials) { - if (credentials.contains(";") || credentials.contains(":")) { - return new HashMap<>( - Splitter.on(';').trimResults().withKeyValueSeparator(':').split(credentials)); - } - return Map.of(); - } -} diff --git a/service/common/src/main/java/org/apache/polaris/service/auth/TestOAuth2ApiService.java b/service/common/src/main/java/org/apache/polaris/service/auth/TestOAuth2ApiService.java deleted file mode 100644 index fefa710907..0000000000 --- a/service/common/src/main/java/org/apache/polaris/service/auth/TestOAuth2ApiService.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.polaris.service.auth; - -import io.smallrye.common.annotation.Identifier; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.SecurityContext; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.apache.iceberg.exceptions.NotAuthorizedException; -import org.apache.polaris.core.PolarisCallContext; -import org.apache.polaris.core.context.CallContext; -import org.apache.polaris.core.context.RealmContext; -import org.apache.polaris.core.entity.PolarisEntitySubType; -import org.apache.polaris.core.entity.PolarisEntityType; -import org.apache.polaris.core.persistence.MetaStoreManagerFactory; -import org.apache.polaris.core.persistence.PolarisMetaStoreManager; -import org.apache.polaris.core.persistence.dao.entity.EntityResult; -import org.apache.polaris.core.persistence.dao.entity.PrincipalSecretsResult; -import org.apache.polaris.service.catalog.api.IcebergRestOAuth2ApiService; -import org.apache.polaris.service.types.TokenType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@RequestScoped -@Identifier("test") -public class TestOAuth2ApiService implements IcebergRestOAuth2ApiService { - private static final Logger LOGGER = LoggerFactory.getLogger(TestOAuth2ApiService.class); - - @Inject MetaStoreManagerFactory metaStoreManagerFactory; - @Inject CallContext callContext; - - @Override - public Response getToken( - String authHeader, - String grantType, - String scope, - String clientId, - String clientSecret, - TokenType requestedTokenType, - String subjectToken, - TokenType subjectTokenType, - String actorToken, - TokenType actorTokenType, - RealmContext realmContext, - SecurityContext securityContext) { - Map response = new HashMap<>(); - String principalName = getPrincipalName(clientId, realmContext); - response.put( - "access_token", - "principal:" - + principalName - + ";password:" - + clientSecret - + ";realm:" - + realmContext.getRealmIdentifier() - + ";role:" - + scope.replaceAll(BasePolarisAuthenticator.PRINCIPAL_ROLE_PREFIX, "")); - response.put("token_type", "bearer"); - response.put("expires_in", 3600); - response.put("scope", Objects.requireNonNullElse(scope, "catalog")); - return Response.ok(response).build(); - } - - private String getPrincipalName(String clientId, RealmContext realmContext) { - PolarisMetaStoreManager metaStoreManager = - metaStoreManagerFactory.getOrCreateMetaStoreManager(realmContext); - PolarisCallContext polarisCallContext = callContext.getPolarisCallContext(); - PrincipalSecretsResult secretsResult = - metaStoreManager.loadPrincipalSecrets(polarisCallContext, clientId); - if (secretsResult.isSuccess()) { - LOGGER.debug("Found principal secrets for client id {}", clientId); - EntityResult principalResult = - metaStoreManager.loadEntity( - polarisCallContext, - 0L, - secretsResult.getPrincipalSecrets().getPrincipalId(), - PolarisEntityType.PRINCIPAL); - if (!principalResult.isSuccess()) { - throw new NotAuthorizedException("Failed to load principal entity"); - } - return principalResult.getEntity().getName(); - } else { - LOGGER.debug( - "Unable to find principal secrets for client id {} - trying as principal name", clientId); - EntityResult principalResult = - metaStoreManager.readEntityByName( - polarisCallContext, - null, - PolarisEntityType.PRINCIPAL, - PolarisEntitySubType.NULL_SUBTYPE, - clientId); - if (!principalResult.isSuccess()) { - throw new NotAuthorizedException("Failed to read principal entity"); - } - return principalResult.getEntity().getName(); - } - } -}