Add --generate-http-password to ssh set-account

To bring the ssh command more in-line with the REST API for a user, it
is now possible to generate a new http-password which does not require
global admin (unlike direct set).

This allows ordinary users to set a new http password via ssh when they
cannot log in to the web ui (e.g. due to being a service account.)

The next commit will change the access restriction so that setting
your own account details does not require MODIFY_ACCOUNT. The REST API
does not need this, and granting it to someone allows them to set *any*
account details, e.g. even deactivating admin accounts.

Change-Id: Ic6102da9e483d07175cdc772930f25608dce12d4
This commit is contained in:
Richard Christie 2018-06-28 12:33:51 +01:00
parent 24d04f4a14
commit efa38be397
2 changed files with 28 additions and 4 deletions

View File

@ -12,6 +12,7 @@ _ssh_ -p <port> <host> _gerrit set-account_
[--preferred-email <EMAIL>] [--preferred-email <EMAIL>]
[--add-ssh-key - | <KEY>] [--add-ssh-key - | <KEY>]
[--delete-ssh-key - | <KEY> | ALL] [--delete-ssh-key - | <KEY> | ALL]
[--generate-http-password]
[--http-password <PASSWORD>] [--http-password <PASSWORD>]
[--clear-http-password] <USER> [--clear-http-password] <USER>
-- --
@ -93,6 +94,11 @@ This most likely requires double quoting the value, for example
May be supplied more than once to delete multiple SSH May be supplied more than once to delete multiple SSH
keys in a single command execution. keys in a single command execution.
--generate-http-password::
Generate a new random HTTP password for the user account
similar to the web ui. The password will be output to the
user on success with a line: `New password: <PASSWORD>`.
--http-password:: --http-password::
Set the HTTP password for the user account. Set the HTTP password for the user account.

View File

@ -26,6 +26,7 @@ import com.google.gerrit.extensions.common.EmailInfo;
import com.google.gerrit.extensions.common.SshKeyInfo; import com.google.gerrit.extensions.common.SshKeyInfo;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountSshKey; import com.google.gerrit.reviewdb.client.AccountSshKey;
@ -113,6 +114,9 @@ final class SetAccountCommand extends SshCommand {
@Option(name = "--clear-http-password", usage = "clear HTTP password for the account") @Option(name = "--clear-http-password", usage = "clear HTTP password for the account")
private boolean clearHttpPassword; private boolean clearHttpPassword;
@Option(name = "--generate-http-password", usage = "generate a new HTTP password for the account")
private boolean generateHttpPassword;
@Inject private IdentifiedUser.GenericFactory genericUserFactory; @Inject private IdentifiedUser.GenericFactory genericUserFactory;
@Inject private CreateEmail.Factory createEmailFactory; @Inject private CreateEmail.Factory createEmailFactory;
@ -150,8 +154,16 @@ final class SetAccountCommand extends SshCommand {
if (active && inactive) { if (active && inactive) {
throw die("--active and --inactive options are mutually exclusive."); throw die("--active and --inactive options are mutually exclusive.");
} }
if (clearHttpPassword && !Strings.isNullOrEmpty(httpPassword)) { if (generateHttpPassword && clearHttpPassword) {
throw die("--http-password and --clear-http-password options are mutually exclusive."); throw die("--generate-http-password and --clear-http-password are mutually exclusive.");
}
if (!Strings.isNullOrEmpty(httpPassword)) { // gave --http-password
if (generateHttpPassword) {
throw die("--http-password and --generate-http-password options are mutually exclusive.");
}
if (clearHttpPassword) {
throw die("--http-password and --clear-http-password options are mutually exclusive.");
}
} }
if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) { if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) {
throw die("Only one option may use the stdin"); throw die("Only one option may use the stdin");
@ -193,10 +205,16 @@ final class SetAccountCommand extends SshCommand {
putName.apply(rsrc, in); putName.apply(rsrc, in);
} }
if (httpPassword != null || clearHttpPassword) { if (httpPassword != null || clearHttpPassword || generateHttpPassword) {
PutHttpPassword.Input in = new PutHttpPassword.Input(); PutHttpPassword.Input in = new PutHttpPassword.Input();
in.httpPassword = httpPassword; in.httpPassword = httpPassword;
putHttpPassword.apply(rsrc, in); if (generateHttpPassword) {
in.generate = true;
}
Response<String> resp = putHttpPassword.apply(rsrc, in);
if (generateHttpPassword) {
stdout.print("New password: " + resp.value() + "\n");
}
} }
if (active) { if (active) {