-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a flag to control whether credentials are printed during bootstrapping #461
base: main
Are you sure you want to change the base?
Changes from 4 commits
65c3012
d9a1698
7b1e258
312453b
6e14558
4a3b1fd
ffcdf49
910bb2a
208b8cd
3b32662
a7a4e67
f922055
d0aeeee
fd49022
6ee09b4
fbd11a1
96885d0
df1d642
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
import java.util.Map; | ||
import java.util.function.Supplier; | ||
import org.apache.polaris.core.PolarisCallContext; | ||
import org.apache.polaris.core.PolarisConfiguration; | ||
import org.apache.polaris.core.PolarisDefaultDiagServiceImpl; | ||
import org.apache.polaris.core.PolarisDiagnostics; | ||
import org.apache.polaris.core.auth.PolarisSecretsManager.PrincipalSecretsResult; | ||
|
@@ -86,7 +87,8 @@ private void initializeForRealm(RealmContext realmContext) { | |
} | ||
|
||
@Override | ||
public synchronized Map<String, PrincipalSecretsResult> bootstrapRealms(List<String> realms) { | ||
public final synchronized Map<String, PrincipalSecretsResult> bootstrapRealms( | ||
List<String> realms) { | ||
Map<String, PrincipalSecretsResult> results = new HashMap<>(); | ||
|
||
bootstrap = true; | ||
|
@@ -95,10 +97,26 @@ public synchronized Map<String, PrincipalSecretsResult> bootstrapRealms(List<Str | |
RealmContext realmContext = () -> realm; | ||
if (!metaStoreManagerMap.containsKey(realmContext.getRealmIdentifier())) { | ||
initializeForRealm(realmContext); | ||
// While bootstrapping we need to act as a fake privileged context since the real | ||
// CallContext hasn't even been resolved yet. | ||
PolarisCallContext polarisContext = | ||
new PolarisCallContext( | ||
sessionSupplierMap.get(realmContext.getRealmIdentifier()).get(), diagServices); | ||
PrincipalSecretsResult secretsResult = | ||
bootstrapServiceAndCreatePolarisPrincipalForRealm( | ||
realmContext, metaStoreManagerMap.get(realmContext.getRealmIdentifier())); | ||
realmContext, | ||
metaStoreManagerMap.get(realmContext.getRealmIdentifier()), | ||
polarisContext); | ||
results.put(realmContext.getRealmIdentifier(), secretsResult); | ||
if (this.printCredentials(polarisContext)) { | ||
String msg = | ||
String.format( | ||
"realm: %1s root principal credentials: %2s:%3s", | ||
realmContext.getRealmIdentifier(), | ||
secretsResult.getPrincipalSecrets().getPrincipalClientId(), | ||
secretsResult.getPrincipalSecrets().getMainSecret()); | ||
System.out.println(msg); | ||
} | ||
} | ||
} | ||
} finally { | ||
|
@@ -173,12 +191,9 @@ public void setStorageIntegrationProvider(PolarisStorageIntegrationProvider stor | |
* credentials and print them to stdout | ||
*/ | ||
private PrincipalSecretsResult bootstrapServiceAndCreatePolarisPrincipalForRealm( | ||
RealmContext realmContext, PolarisMetaStoreManager metaStoreManager) { | ||
// While bootstrapping we need to act as a fake privileged context since the real | ||
// CallContext hasn't even been resolved yet. | ||
PolarisCallContext polarisContext = | ||
new PolarisCallContext( | ||
sessionSupplierMap.get(realmContext.getRealmIdentifier()).get(), diagServices); | ||
RealmContext realmContext, | ||
PolarisMetaStoreManager metaStoreManager, | ||
PolarisCallContext polarisContext) { | ||
CallContext.setCurrentContext(CallContext.of(realmContext, polarisContext)); | ||
|
||
PolarisMetaStoreManager.EntityResult preliminaryRootPrincipalLookup = | ||
|
@@ -196,6 +211,20 @@ private PrincipalSecretsResult bootstrapServiceAndCreatePolarisPrincipalForRealm | |
throw new IllegalArgumentException(overrideMessage); | ||
} | ||
|
||
boolean environmentVariableCredentials = | ||
PrincipalSecretsGenerator.hasCredentialVariables( | ||
realmContext.getRealmIdentifier(), PolarisEntityConstants.getRootPrincipalName()); | ||
if (!this.printCredentials(polarisContext) && !environmentVariableCredentials) { | ||
String failureMessage = | ||
String.format( | ||
"It appears that environment variables were not provided for root credentials, and that printing " | ||
+ "the root credentials is disabled via %s. If bootstrapping were to proceed, there would be no way " | ||
+ "to recover the root credentials", | ||
PolarisConfiguration.BOOTSTRAP_PRINT_CREDENTIALS.key); | ||
LOGGER.error("\n\n {} \n\n", failureMessage); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar here - why is the metastore aware of whether the secrets were provided by environment variables? What if there are other impls of secrets generators that don't rely on env variables? E.g., we could have one that calls AWS SecretsManager to dynamically generate and store the secrets without any env variables. Should this code throw an exception? |
||
throw new IllegalArgumentException(failureMessage); | ||
eric-maynard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
metaStoreManager.bootstrapPolarisService(polarisContext); | ||
|
||
PolarisMetaStoreManager.EntityResult rootPrincipalLookup = | ||
|
@@ -253,4 +282,11 @@ private void checkPolarisServiceBootstrappedForRealm( | |
"Realm is not bootstrapped, please run server in bootstrap mode."); | ||
} | ||
} | ||
|
||
/** Whether or not to print credentials after bootstrapping */ | ||
protected boolean printCredentials(PolarisCallContext polarisCallContext) { | ||
return polarisCallContext | ||
.getConfigurationStore() | ||
.getConfiguration(polarisCallContext, PolarisConfiguration.BOOTSTRAP_PRINT_CREDENTIALS); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this logic belongs to the secrets generator. The MetaStoreManager doesn't need to know anything about whether the secrets generated are provided by the user or if they've been generated randomly. So why would it be concerned with printing the credentials? The secrets generator knows if the secrets were provided explicitly or if they were randomly generated.
I think the
bootstrap
command should take aprint-credentials
config flag and the constructed secrets generator can react accordingly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the
PrincipalSecretsGenerator
is doing exactly what the name suggests: generating secrets.Whatever is done with those secrets -- persisting them, using them, printing them -- is outside the purview of the generator itself.
You are right that the
MetaStoreManager
doesn't need to know anything about printing either (it doesn't in this PR) and clearly this should be outside the purview of the metastore itself.And so we landed on the factory. I would be happy to take this bootstrapping logic and excise it to somewhere more idiomatic if that is a concern. But right now the bootstrapping logic lives here (e.g. the
purge
check) and this seems like the most appropriate place that doesn't change the responsibility of either the metastore or generator classes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking again, is your objection specifically to the protected method
printCredentials
?That only exists to support the legacy behavior of the in-memory metastore always printing credentials, and if possible I would very much be in favor of removing that.
However it feels like pushing that logic down into an existing method (whether
secretsGenerator
,createMetaStoreSession
, or elsewhere) could be a bit hacky if it winds up somewhere it doesn't belong.