diff --git a/persistence/nosql/persistence/metastore-maintenance/src/test/java/org/apache/polaris/persistence/nosql/metastore/maintenance/TestCatalogMaintenance.java b/persistence/nosql/persistence/metastore-maintenance/src/test/java/org/apache/polaris/persistence/nosql/metastore/maintenance/TestCatalogMaintenance.java index d5f311054a..84ffa51a8c 100644 --- a/persistence/nosql/persistence/metastore-maintenance/src/test/java/org/apache/polaris/persistence/nosql/metastore/maintenance/TestCatalogMaintenance.java +++ b/persistence/nosql/persistence/metastore-maintenance/src/test/java/org/apache/polaris/persistence/nosql/metastore/maintenance/TestCatalogMaintenance.java @@ -248,12 +248,12 @@ public void catalogMaintenance() { // 8 stale objects: // - 1 namespace (catalog state) // - 1 table (catalog state) - // - 1 grants (realm setup) - including 1 ACLs + // - 2 grants (realm setup) - including 2 ACLs // - 1 principal // - 1 principal role // - 1 catalog role // - 1 catalog - Optional.of(8L)); + Optional.of(10L)); checkEntities("real state after grace", entities); } diff --git a/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManager.java b/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManager.java index 9338f2a5a4..e35e34ddeb 100644 --- a/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManager.java +++ b/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManager.java @@ -92,89 +92,6 @@ NoSqlMetaStore ms(PolarisCallContext callContext) { // Realms - @Nonnull - @Override - public BaseResult bootstrapPolarisService(@Nonnull PolarisCallContext callCtx) { - bootstrapPolarisServiceInternal(ms(callCtx)); - return new BaseResult(BaseResult.ReturnStatus.SUCCESS); - } - - Optional bootstrapPolarisServiceInternal(NoSqlMetaStore ms) { - // This function is idempotent, already existing entities will not be created again. - - // Create the root-container, if not already present - var rootContainer = - ms.lookupRoot() - .orElseGet( - () -> { - var newRoot = - new PolarisBaseEntity( - PolarisEntityConstants.getNullId(), - PolarisEntityConstants.getRootEntityId(), - PolarisEntityType.ROOT, - PolarisEntitySubType.NULL_SUBTYPE, - PolarisEntityConstants.getRootEntityId(), - PolarisEntityConstants.getRootContainerName()); - ms.createEntity(newRoot); - return newRoot; - }); - - // Create the root-principal, if not already present - var rootPrincipal = - ms.lookupEntityByName( - 0L, - 0L, - PolarisEntityType.PRINCIPAL.getCode(), - PolarisEntityConstants.getRootPrincipalName()); - var createPrincipalResult = Optional.empty(); - if (rootPrincipal == null) { - var rootPrincipalId = ms.generateNewId(); - rootPrincipal = - new PolarisBaseEntity( - PolarisEntityConstants.getNullId(), - rootPrincipalId, - PolarisEntityType.PRINCIPAL, - PolarisEntitySubType.NULL_SUBTYPE, - PolarisEntityConstants.getRootEntityId(), - PolarisEntityConstants.getRootPrincipalName()); - - createPrincipalResult = Optional.of(ms.createPrincipal(rootPrincipal, rootCredentialsSet)); - } - - // Create the service-admin principal-role, if not already present - var serviceAdminPrincipalRole = - ms.lookupEntityByName( - 0L, - 0L, - PolarisEntityType.PRINCIPAL_ROLE.getCode(), - PolarisEntityConstants.getNameOfPrincipalServiceAdminRole()); - if (serviceAdminPrincipalRole == null) { - // now create the account admin principal role - var serviceAdminPrincipalRoleId = ms.generateNewId(); - serviceAdminPrincipalRole = - new PolarisBaseEntity( - PolarisEntityConstants.getNullId(), - serviceAdminPrincipalRoleId, - PolarisEntityType.PRINCIPAL_ROLE, - PolarisEntitySubType.NULL_SUBTYPE, - PolarisEntityConstants.getRootEntityId(), - PolarisEntityConstants.getNameOfPrincipalServiceAdminRole()); - ms.createEntity(serviceAdminPrincipalRole); - } - - // Persisting already existing grants is an idempotent operation - ms.persistGrantsOrRevokes( - true, - // we also need to grant usage on the account-admin principal to the principal - new SecurableGranteePrivilegeTuple( - serviceAdminPrincipalRole, rootPrincipal, PolarisPrivilege.PRINCIPAL_ROLE_USAGE), - // grant SERVICE_MANAGE_ACCESS on the rootContainer to the serviceAdminPrincipalRole - new SecurableGranteePrivilegeTuple( - rootContainer, serviceAdminPrincipalRole, PolarisPrivilege.SERVICE_MANAGE_ACCESS)); - - return createPrincipalResult; - } - @Nonnull @Override public BaseResult purge(@Nonnull PolarisCallContext callCtx) { diff --git a/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManagerFactory.java b/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManagerFactory.java index 6fffd8faa9..04ed314f95 100644 --- a/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManagerFactory.java +++ b/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStoreManagerFactory.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import static org.apache.polaris.core.auth.AuthBootstrapUtil.createPolarisPrincipalForRealm; import static org.apache.polaris.persistence.nosql.coretypes.refs.References.realmReferenceNames; import static org.apache.polaris.persistence.nosql.realms.api.RealmDefinition.RealmStatus.ACTIVE; import static org.apache.polaris.persistence.nosql.realms.api.RealmDefinition.RealmStatus.CREATED; @@ -37,21 +38,16 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import org.apache.polaris.core.PolarisCallContext; import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.config.RealmConfig; import org.apache.polaris.core.context.RealmContext; -import org.apache.polaris.core.entity.PolarisBaseEntity; -import org.apache.polaris.core.entity.PolarisEntity; -import org.apache.polaris.core.entity.PolarisEntityConstants; -import org.apache.polaris.core.entity.PolarisEntityType; -import org.apache.polaris.core.entity.PolarisPrincipalSecrets; import org.apache.polaris.core.persistence.BasePersistence; import org.apache.polaris.core.persistence.MetaStoreManagerFactory; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.bootstrap.RootCredentialsSet; import org.apache.polaris.core.persistence.cache.EntityCache; import org.apache.polaris.core.persistence.dao.entity.BaseResult; -import org.apache.polaris.core.persistence.dao.entity.CreatePrincipalResult; import org.apache.polaris.core.persistence.dao.entity.PrincipalSecretsResult; import org.apache.polaris.core.storage.PolarisStorageIntegrationProvider; import org.apache.polaris.persistence.nosql.api.Persistence; @@ -275,9 +271,8 @@ private PrincipalSecretsResult bootstrapRealm( rootCredentialsSet, clock); - var secretsResult = - bootstrapServiceAndCreatePolarisPrincipalForRealm( - realmId, metaStoreManager, metaStore, rootCredentialsSet); + PolarisCallContext ctx = new PolarisCallContext(() -> realmId, metaStore); + var secretsResult = createPolarisPrincipalForRealm(metaStoreManager, ctx); realmManagement.update( realmDesc, RealmDefinition.builder().from(realmDesc).status(ACTIVE).build()); @@ -286,70 +281,4 @@ private PrincipalSecretsResult bootstrapRealm( return secretsResult; } - - /** - * This method bootstraps service for a given realm: i.e., creates all the required entities in - * the metastore and creates a root service principal. After that, we rotate the root principal - * credentials and print them to stdout - */ - private PrincipalSecretsResult bootstrapServiceAndCreatePolarisPrincipalForRealm( - String realmId, - NoSqlMetaStoreManager metaStoreManager, - NoSqlMetaStore metaStore, - RootCredentialsSet rootCredentialsSet) { - var createPrincipalResult = metaStoreManager.bootstrapPolarisServiceInternal(metaStore); - - var rootPrincipal = - createPrincipalResult - .map(result -> (PolarisBaseEntity) result.getPrincipal()) - .orElseGet( - () -> - metaStoreManager - .readEntityByName( - metaStore, - null, - PolarisEntityType.PRINCIPAL, - PolarisEntityConstants.getRootPrincipalName()) - .getEntity()); - - var clientId = - PolarisEntity.of(rootPrincipal) - .getInternalPropertiesAsMap() - .get(PolarisEntityConstants.getClientIdPropertyName()); - checkState(clientId != null, "Root principal has no client-ID"); - var secrets = metaStore.loadPrincipalSecrets(clientId); - - var principalSecrets = createPrincipalResult.map(CreatePrincipalResult::getPrincipalSecrets); - if (principalSecrets.isPresent()) { - LOGGER.debug( - "Root principal created for realm '{}', directly returning credentials for client-ID '{}'", - realmId, - principalSecrets.get().getPrincipalClientId()); - return new PrincipalSecretsResult(principalSecrets.get()); - } - - var providedCredentials = rootCredentialsSet.credentials().get(realmId); - if (providedCredentials != null) { - LOGGER.debug( - "Root principal for realm '{}' already exists, credentials provided externally, returning credentials for client-ID '{}'", - realmId, - providedCredentials.clientId()); - return new PrincipalSecretsResult( - new PolarisPrincipalSecrets( - rootPrincipal.getId(), - providedCredentials.clientId(), - providedCredentials.clientSecret(), - providedCredentials.clientSecret())); - } - - // Have to rotate the secrets to retain the idempotency of this function - var result = - metaStoreManager.rotatePrincipalSecrets( - metaStore, secrets.getPrincipalId(), false, secrets.getMainSecretHash()); - LOGGER.debug( - "Rotating credentials for root principal for realm '{}', client-ID is '{}'", - realmId, - result.getPrincipalSecrets().getPrincipalClientId()); - return result; - } } diff --git a/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java b/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java index e46cc7277e..d21d1959a3 100644 --- a/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java +++ b/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java @@ -18,6 +18,8 @@ */ package org.apache.polaris.persistence.relational.jdbc; +import static org.apache.polaris.core.auth.AuthBootstrapUtil.createPolarisPrincipalForRealm; + import io.smallrye.common.annotation.Identifier; import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; @@ -181,8 +183,14 @@ public synchronized Map bootstrapRealms( } initializeForRealm( datasourceOperations, realmContext, bootstrapOptions.rootCredentialsSet()); + + PolarisMetaStoreManager metaStoreManager = + metaStoreManagerMap.get(realmContext.getRealmIdentifier()); + BasePersistence metaStore = sessionSupplierMap.get(realmContext.getRealmIdentifier()).get(); + PolarisCallContext polarisContext = new PolarisCallContext(realmContext, metaStore); + PrincipalSecretsResult secretsResult = - bootstrapServiceAndCreatePolarisPrincipalForRealm(realmContext); + createPolarisPrincipalForRealm(metaStoreManager, polarisContext); results.put(realm, secretsResult); } } @@ -244,36 +252,6 @@ public synchronized EntityCache getOrCreateEntityCache( return entityCacheMap.get(realmContext.getRealmIdentifier()); } - /** - * This method bootstraps service for a given realm: i.e. creates all the needed entities in the - * metastore and creates a root service principal. - */ - private PrincipalSecretsResult bootstrapServiceAndCreatePolarisPrincipalForRealm( - RealmContext realmContext) { - // While bootstrapping we need to act as a fake privileged context since the real - // CallContext may not have been resolved yet. - PolarisMetaStoreManager metaStoreManager = - metaStoreManagerMap.get(realmContext.getRealmIdentifier()); - BasePersistence metaStore = sessionSupplierMap.get(realmContext.getRealmIdentifier()).get(); - PolarisCallContext polarisContext = new PolarisCallContext(realmContext, metaStore); - - Optional preliminaryRootPrincipal = - metaStoreManager.findRootPrincipal(polarisContext); - if (preliminaryRootPrincipal.isPresent()) { - String overrideMessage = - "It appears this metastore manager has already been bootstrapped. " - + "To continue bootstrapping, please first purge the metastore with the `purge` command."; - LOGGER.error("\n\n {} \n\n", overrideMessage); - throw new IllegalArgumentException(overrideMessage); - } - - metaStoreManager.bootstrapPolarisService(polarisContext); - - PrincipalEntity rootPrincipal = - metaStoreManager.findRootPrincipal(polarisContext).orElseThrow(); - return metaStoreManager.loadPrincipalSecrets(polarisContext, rootPrincipal.getClientId()); - } - /** * In this method we check if Service was bootstrapped for a given realm, i.e. that all the * entities were created (root principal, root principal role, etc) If service was not diff --git a/polaris-core/src/main/java/org/apache/polaris/core/auth/AuthBootstrapUtil.java b/polaris-core/src/main/java/org/apache/polaris/core/auth/AuthBootstrapUtil.java new file mode 100644 index 0000000000..fe730fbd6a --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/auth/AuthBootstrapUtil.java @@ -0,0 +1,115 @@ +/* + * 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.core.auth; + +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.base.Preconditions; +import java.util.Optional; +import org.apache.polaris.core.PolarisCallContext; +import org.apache.polaris.core.entity.PolarisBaseEntity; +import org.apache.polaris.core.entity.PolarisEntityConstants; +import org.apache.polaris.core.entity.PolarisEntitySubType; +import org.apache.polaris.core.entity.PolarisEntityType; +import org.apache.polaris.core.entity.PolarisPrivilege; +import org.apache.polaris.core.entity.PrincipalEntity; +import org.apache.polaris.core.entity.PrincipalRoleEntity; +import org.apache.polaris.core.persistence.PolarisMetaStoreManager; +import org.apache.polaris.core.persistence.dao.entity.CreatePrincipalResult; +import org.apache.polaris.core.persistence.dao.entity.GenerateEntityIdResult; +import org.apache.polaris.core.persistence.dao.entity.PrincipalSecretsResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class for sharing root Polaris Principal setup code among all persistence + * implementations. + * + *

Note: this class is not meant to be reused outside of Polaris code. + */ +public class AuthBootstrapUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(AuthBootstrapUtil.class); + + private AuthBootstrapUtil() {} + + public static PrincipalSecretsResult createPolarisPrincipalForRealm( + PolarisMetaStoreManager metaStoreManager, PolarisCallContext ctx) { + + Optional preliminaryRootPrincipal = metaStoreManager.findRootPrincipal(ctx); + if (preliminaryRootPrincipal.isPresent()) { + String overrideMessage = + "It appears this metastore manager has already been bootstrapped. " + + "To continue bootstrapping, please first purge the metastore with the `purge` command."; + LOGGER.error("\n\n {} \n\n", overrideMessage); + throw new IllegalArgumentException(overrideMessage); + } + + // Create a root container entity that can represent the securable for any top-level grants. + PolarisBaseEntity rootContainer = + new PolarisBaseEntity( + PolarisEntityConstants.getNullId(), + PolarisEntityConstants.getRootEntityId(), + PolarisEntityType.ROOT, + PolarisEntitySubType.NULL_SUBTYPE, + PolarisEntityConstants.getRootEntityId(), + PolarisEntityConstants.getRootContainerName()); + metaStoreManager.createEntityIfNotExists(ctx, null, rootContainer); + + CreatePrincipalResult principalResult = + metaStoreManager.createPrincipal( + ctx, + new PrincipalEntity.Builder() + .setId(generateId(metaStoreManager, ctx)) + .setName(PolarisEntityConstants.getRootPrincipalName()) + .setCreateTimestamp(System.currentTimeMillis()) + .build()); + checkState(principalResult.isSuccess(), "Unable to create root principal"); + PrincipalEntity rootPrincipal = principalResult.getPrincipal(); + + // now create the account admin principal role + PrincipalRoleEntity serviceAdminPrincipalRole = + new PrincipalRoleEntity.Builder() + .setId(generateId(metaStoreManager, ctx)) + .setName(PolarisEntityConstants.getNameOfPrincipalServiceAdminRole()) + .setCreateTimestamp(System.currentTimeMillis()) + .build(); + metaStoreManager.createEntityIfNotExists(ctx, null, serviceAdminPrincipalRole); + + // we also need to grant usage on the account-admin principal to the principal + metaStoreManager.grantPrivilegeOnSecurableToRole( + ctx, rootPrincipal, null, serviceAdminPrincipalRole, PolarisPrivilege.PRINCIPAL_ROLE_USAGE); + + // grant SERVICE_MANAGE_ACCESS on the rootContainer to the serviceAdminPrincipalRole + metaStoreManager.grantPrivilegeOnSecurableToRole( + ctx, + serviceAdminPrincipalRole, + null, + rootContainer, + PolarisPrivilege.SERVICE_MANAGE_ACCESS); + + return metaStoreManager.loadPrincipalSecrets(ctx, rootPrincipal.getClientId()); + } + + private static long generateId(PolarisMetaStoreManager metaStoreManager, PolarisCallContext ctx) { + GenerateEntityIdResult res = metaStoreManager.generateNewEntityId(ctx); + Preconditions.checkState(res.isSuccess(), "Unable to generate id for polaris entity"); + return res.getId(); + } +} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java index 60085193ce..84341f7936 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java @@ -54,7 +54,6 @@ import org.apache.polaris.core.entity.PolarisPrivilege; import org.apache.polaris.core.entity.PolarisTaskConstants; import org.apache.polaris.core.entity.PrincipalEntity; -import org.apache.polaris.core.entity.PrincipalRoleEntity; import org.apache.polaris.core.persistence.dao.entity.BaseResult; import org.apache.polaris.core.persistence.dao.entity.ChangeTrackingResult; import org.apache.polaris.core.persistence.dao.entity.CreateCatalogResult; @@ -560,69 +559,6 @@ private void revokeGrantRecord( return new CreateCatalogResult(catalog, adminRole); } - /** {@inheritDoc} */ - @Override - public @Nonnull BaseResult bootstrapPolarisService(@Nonnull PolarisCallContext callCtx) { - // get meta store we should be using - BasePersistence ms = callCtx.getMetaStore(); - - // Create a root container entity that can represent the securable for any top-level grants. - PolarisBaseEntity rootContainer = - new PolarisBaseEntity( - PolarisEntityConstants.getNullId(), - PolarisEntityConstants.getRootEntityId(), - PolarisEntityType.ROOT, - PolarisEntitySubType.NULL_SUBTYPE, - PolarisEntityConstants.getRootEntityId(), - PolarisEntityConstants.getRootContainerName()); - this.persistNewEntity(callCtx, ms, rootContainer); - - // Now bootstrap the service by creating the root principal and the service_admin principal - // role. The principal role will be granted to that root principal and the root catalog admin - // of the root catalog will be granted to that principal role. - long rootPrincipalId = ms.generateNewId(callCtx); - PrincipalEntity rootPrincipal = - new PrincipalEntity.Builder() - .setId(rootPrincipalId) - .setName(PolarisEntityConstants.getRootPrincipalName()) - .setCreateTimestamp(System.currentTimeMillis()) - .build(); - this.createPrincipal(callCtx, rootPrincipal); - - // now create the account admin principal role - long serviceAdminPrincipalRoleId = ms.generateNewId(callCtx); - PrincipalRoleEntity serviceAdminPrincipalRole = - new PrincipalRoleEntity.Builder() - .setId(serviceAdminPrincipalRoleId) - .setName(PolarisEntityConstants.getNameOfPrincipalServiceAdminRole()) - .setCreateTimestamp(System.currentTimeMillis()) - .build(); - this.persistNewEntity(callCtx, ms, serviceAdminPrincipalRole); - - // we also need to grant usage on the account-admin principal to the principal - this.persistNewGrantRecord( - callCtx, - ms, - serviceAdminPrincipalRole, - rootPrincipal, - PolarisPrivilege.PRINCIPAL_ROLE_USAGE); - - // grant SERVICE_MANAGE_ACCESS on the rootContainer to the serviceAdminPrincipalRole - this.persistNewGrantRecord( - callCtx, - ms, - rootContainer, - serviceAdminPrincipalRole, - PolarisPrivilege.SERVICE_MANAGE_ACCESS); - - // TODO: Make idempotent by being able to continue where it left off for the context's realm. - // In the meantime, if a realm was only partially initialized before the server crashed, - // it's fine to purge the realm and retry the bootstrap. - - // all good - return new BaseResult(BaseResult.ReturnStatus.SUCCESS); - } - @Override public @Nonnull BaseResult purge(@Nonnull PolarisCallContext callCtx) { // get meta store we should be using diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisMetaStoreManager.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisMetaStoreManager.java index efa73a60b7..423295d3a7 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisMetaStoreManager.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisMetaStoreManager.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Optional; import org.apache.polaris.core.PolarisCallContext; +import org.apache.polaris.core.auth.AuthBootstrapUtil; import org.apache.polaris.core.auth.PolarisGrantManager; import org.apache.polaris.core.auth.PolarisSecretsManager; import org.apache.polaris.core.entity.LocationBasedEntity; @@ -73,7 +74,10 @@ public interface PolarisMetaStoreManager * @return the result of the bootstrap attempt */ @Nonnull - BaseResult bootstrapPolarisService(@Nonnull PolarisCallContext callCtx); + default BaseResult bootstrapPolarisService(@Nonnull PolarisCallContext callCtx) { + AuthBootstrapUtil.createPolarisPrincipalForRealm(this, callCtx); + return new BaseResult(BaseResult.ReturnStatus.SUCCESS); + } /** * Purge all metadata associated with the Polaris service, resetting the metastore to the state it diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java index 4589635410..eab3835930 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java @@ -53,7 +53,6 @@ import org.apache.polaris.core.entity.PolarisPrivilege; import org.apache.polaris.core.entity.PolarisTaskConstants; import org.apache.polaris.core.entity.PrincipalEntity; -import org.apache.polaris.core.entity.PrincipalRoleEntity; import org.apache.polaris.core.persistence.BaseMetaStoreManager; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.PolarisObjectMapperUtil; @@ -534,78 +533,6 @@ private void revokeGrantRecord( return new CreateCatalogResult(catalog, adminRole); } - /** - * Bootstrap Polaris catalog service - * - * @param callCtx call context - * @param ms meta store in read/write mode - */ - private void bootstrapPolarisService( - @Nonnull PolarisCallContext callCtx, @Nonnull TransactionalPersistence ms) { - - // Create a root container entity that can represent the securable for any top-level grants. - PolarisBaseEntity rootContainer = - new PolarisBaseEntity( - PolarisEntityConstants.getNullId(), - PolarisEntityConstants.getRootEntityId(), - PolarisEntityType.ROOT, - PolarisEntitySubType.NULL_SUBTYPE, - PolarisEntityConstants.getRootEntityId(), - PolarisEntityConstants.getRootContainerName()); - this.persistNewEntity(callCtx, ms, rootContainer); - - // Now bootstrap the service by creating the root principal and the service_admin principal - // role. The principal role will be granted to that root principal and the root catalog admin - // of the root catalog will be granted to that principal role. - long rootPrincipalId = ms.generateNewIdInCurrentTxn(callCtx); - PrincipalEntity rootPrincipal = - new PrincipalEntity.Builder() - .setId(rootPrincipalId) - .setName(PolarisEntityConstants.getRootPrincipalName()) - .setCreateTimestamp(System.currentTimeMillis()) - .build(); - this.createPrincipal(callCtx, ms, rootPrincipal); - - // now create the account admin principal role - long serviceAdminPrincipalRoleId = ms.generateNewIdInCurrentTxn(callCtx); - PrincipalRoleEntity serviceAdminPrincipalRole = - new PrincipalRoleEntity.Builder() - .setId(serviceAdminPrincipalRoleId) - .setName(PolarisEntityConstants.getNameOfPrincipalServiceAdminRole()) - .setCreateTimestamp(System.currentTimeMillis()) - .build(); - this.persistNewEntity(callCtx, ms, serviceAdminPrincipalRole); - - // we also need to grant usage on the account-admin principal to the principal - this.persistNewGrantRecord( - callCtx, - ms, - serviceAdminPrincipalRole, - rootPrincipal, - PolarisPrivilege.PRINCIPAL_ROLE_USAGE); - - // grant SERVICE_MANAGE_ACCESS on the rootContainer to the serviceAdminPrincipalRole - this.persistNewGrantRecord( - callCtx, - ms, - rootContainer, - serviceAdminPrincipalRole, - PolarisPrivilege.SERVICE_MANAGE_ACCESS); - } - - /** {@inheritDoc} */ - @Override - public @Nonnull BaseResult bootstrapPolarisService(@Nonnull PolarisCallContext callCtx) { - // get meta store we should be using - TransactionalPersistence ms = ((TransactionalPersistence) callCtx.getMetaStore()); - - // run operation in a read/write transaction - ms.runActionInTransaction(callCtx, () -> this.bootstrapPolarisService(callCtx, ms)); - - // all good - return new BaseResult(BaseResult.ReturnStatus.SUCCESS); - } - @Override public @Nonnull BaseResult purge(@Nonnull PolarisCallContext callCtx) { // get meta store we should be using