Skip to content

Commit 1a03108

Browse files
authored
Prevent the bootstrap command from leaving root credentials unrecoverable (#461)
* rebase * autolint
1 parent ec137a2 commit 1a03108

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

quarkus/admin/src/main/java/org/apache/polaris/admintool/BootstrapCommand.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ static class StandardInputOptions {
5757
description =
5858
"Root principal credentials to bootstrap. Must be of the form 'realm,clientId,clientSecret'.")
5959
List<String> credentials;
60+
61+
@CommandLine.Option(
62+
names = {"-p", "--print-credentials"},
63+
description = "Print root credentials to stdout")
64+
boolean printCredentials;
6065
}
6166

6267
static class FileInputOptions {
@@ -85,6 +90,17 @@ public Integer call() {
8590
|| inputOptions.stdinOptions.credentials.isEmpty()
8691
? RootCredentialsSet.EMPTY
8792
: RootCredentialsSet.fromList(inputOptions.stdinOptions.credentials);
93+
if (inputOptions.stdinOptions.credentials == null
94+
|| inputOptions.stdinOptions.credentials.isEmpty()) {
95+
if (!inputOptions.stdinOptions.printCredentials) {
96+
spec.commandLine()
97+
.getErr()
98+
.println(
99+
"Specify either `--credentials` or `--print-credentials` to ensure"
100+
+ " the root user is accessible after bootstrapping.");
101+
return EXIT_CODE_BOOTSTRAP_ERROR;
102+
}
103+
}
88104
}
89105

90106
// Execute the bootstrap
@@ -97,6 +113,15 @@ public Integer call() {
97113
if (result.getValue().isSuccess()) {
98114
String realm = result.getKey();
99115
spec.commandLine().getOut().printf("Realm '%s' successfully bootstrapped.%n", realm);
116+
if (inputOptions.stdinOptions != null && inputOptions.stdinOptions.printCredentials) {
117+
String msg =
118+
String.format(
119+
"realm: %1s root principal credentials: %2s:%3s",
120+
result.getKey(),
121+
result.getValue().getPrincipalSecrets().getPrincipalClientId(),
122+
result.getValue().getPrincipalSecrets().getMainSecret());
123+
spec.commandLine().getOut().println(msg);
124+
}
100125
} else {
101126
String realm = result.getKey();
102127
spec.commandLine()

quarkus/admin/src/test/java/org/apache/polaris/admintool/BootstrapCommandTest.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void testBootstrapInvalidCredentials(LaunchResult result) {
9999
public void testBootstrapInvalidArguments(LaunchResult result) {
100100
assertThat(result.getErrorOutput())
101101
.contains(
102-
"Error: (-r=<realm> [-r=<realm>]... [-c=<realm,clientId,clientSecret>]...) "
102+
"Error: (-r=<realm> [-r=<realm>]... [-c=<realm,clientId,clientSecret>]... [-p]) "
103103
+ "and -f=<file> are mutually exclusive (specify only one)");
104104
}
105105

@@ -132,6 +132,45 @@ public void testBootstrapFromInvalidFile(QuarkusMainLauncher launcher) {
132132
.contains("Bootstrap encountered errors during operation.");
133133
}
134134

135+
@Test
136+
@Launch(
137+
value = {"bootstrap", "-r", "realm1", "-c", "realm1,client1d,s3cr3t", "--print-credentials"})
138+
public void testPrintCredentials(LaunchResult result) {
139+
assertThat(result.getOutput()).contains("Bootstrap completed successfully.");
140+
assertThat(result.getOutput()).contains("realm: realm1 root principal credentials: client1d:");
141+
}
142+
143+
@Test
144+
@Launch(value = {"bootstrap", "-r", "realm1", "--print-credentials"})
145+
public void testPrintCredentialsSystemGenerated(LaunchResult result) {
146+
assertThat(result.getOutput()).contains("Bootstrap completed successfully.");
147+
assertThat(result.getOutput()).contains("realm: realm1 root principal credentials: ");
148+
}
149+
150+
@Test
151+
@Launch(
152+
value = {"bootstrap", "-r", "realm1"},
153+
exitCode = EXIT_CODE_BOOTSTRAP_ERROR)
154+
public void testNoPrintCredentialsSystemGenerated(LaunchResult result) {
155+
assertThat(result.getErrorOutput()).contains("--credentials");
156+
assertThat(result.getErrorOutput()).contains("--print-credentials");
157+
}
158+
159+
@Test
160+
@Launch(
161+
value = {
162+
"bootstrap",
163+
"-r",
164+
"realm1",
165+
"--not-real-arg",
166+
},
167+
exitCode = EXIT_CODE_USAGE)
168+
public void testBootstrapInvalidArg(LaunchResult result) {
169+
assertThat(result.getErrorOutput())
170+
.contains("Unknown option: '--not-real-arg'")
171+
.contains("Usage:");
172+
}
173+
135174
private static Path copyResource(Path temp, String resource) throws IOException {
136175
URL source = Objects.requireNonNull(BootstrapCommandTest.class.getResource(resource));
137176
Path dest = temp.resolve(resource);

0 commit comments

Comments
 (0)