This is an automated email from the ASF dual-hosted git repository.
dimas pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new d95bd6b1e Extract root Principal setup code into a common util class
(#3446)
d95bd6b1e is described below
commit d95bd6b1e3d77b5db7769e866c0474f08accad2c
Author: Dmitri Bourlatchkov <[email protected]>
AuthorDate: Fri Jan 23 10:12:45 2026 -0500
Extract root Principal setup code into a common util class (#3446)
* Add `AuthBootstrapUtil` to contain the canonical setup code
for the "root" Polaris Principal and default roles.
* This class is not meant for reuse outside the Polaris codebase.
---
.../maintenance/TestCatalogMaintenance.java | 4 +-
.../nosql/metastore/NoSqlMetaStoreManager.java | 83 ---------------
.../metastore/NoSqlMetaStoreManagerFactory.java | 79 +-------------
.../jdbc/JdbcMetaStoreManagerFactory.java | 40 ++-----
.../polaris/core/auth/AuthBootstrapUtil.java | 115 +++++++++++++++++++++
.../AtomicOperationMetaStoreManager.java | 64 ------------
.../core/persistence/PolarisMetaStoreManager.java | 6 +-
.../TransactionalMetaStoreManagerImpl.java | 73 -------------
8 files changed, 135 insertions(+), 329 deletions(-)
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 d5f311054..84ffa51a8 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 class TestCatalogMaintenance {
// 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 9338f2a5a..e35e34dde 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 @@ record NoSqlMetaStoreManager(
// Realms
- @Nonnull
- @Override
- public BaseResult bootstrapPolarisService(@Nonnull PolarisCallContext
callCtx) {
- bootstrapPolarisServiceInternal(ms(callCtx));
- return new BaseResult(BaseResult.ReturnStatus.SUCCESS);
- }
-
- Optional<CreatePrincipalResult>
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.<CreatePrincipalResult>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 6fffd8faa..04ed314f9 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 @@ package org.apache.polaris.persistence.nosql.metastore;
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.HashMap;
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 @@ class NoSqlMetaStoreManagerFactory implements
MetaStoreManagerFactory {
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 @@ class NoSqlMetaStoreManagerFactory implements
MetaStoreManagerFactory {
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 690eb5ae3..26f38fc31 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;
@@ -176,8 +178,14 @@ public class JdbcMetaStoreManagerFactory implements
MetaStoreManagerFactory {
}
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);
}
}
@@ -239,36 +247,6 @@ public class JdbcMetaStoreManagerFactory implements
MetaStoreManagerFactory {
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<PrincipalEntity> 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 000000000..fe730fbd6
--- /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.
+ *
+ * <p>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<PrincipalEntity> 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 60085193c..84341f793 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.PolarisPrincipalSecrets;
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 @@ public class AtomicOperationMetaStoreManager extends
BaseMetaStoreManager {
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 efa73a60b..423295d3a 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.List;
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 458963541..eab383593 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.PolarisPrincipalSecrets;
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 @@ public class TransactionalMetaStoreManagerImpl extends
BaseMetaStoreManager {
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