Merge pull request #1130 from DeterminateSystems/prompt-password

hydra-create-user: support prompting for password
This commit is contained in:
Graham Christensen
2022-01-21 15:38:39 -05:00
committed by GitHub
9 changed files with 112 additions and 21 deletions

View File

@ -16,20 +16,32 @@ use IPC::Run;
our @ISA = qw(Exporter);
our @EXPORT = qw(
getHydraHome getHydraConfig getBaseUrl
getSCMCacheDir getStatsdConfig
registerRoot getGCRootsDir gcRootFor
jobsetOverview jobsetOverview_
getDrvLogPath findLog
getMainOutput
cancelBuilds
captureStdoutStderr
captureStdoutStderrWithStdin
findLog
gcRootFor
getBaseUrl
getDrvLogPath
getEvals getMachines
pathIsInsidePrefix
captureStdoutStderr run grab
getTotalShares
getGCRootsDir
getHydraConfig
getHydraHome
getMainOutput
getSCMCacheDir
getStatsdConfig
getStoreUri
readNixFile
getTotalShares
grab
isLocalStore
cancelBuilds restartBuilds);
jobsetOverview
jobsetOverview_
pathIsInsidePrefix
readNixFile
registerRoot
restartBuilds
run
);
sub getHydraHome {
@ -417,14 +429,19 @@ sub pathIsInsidePrefix {
sub captureStdoutStderr {
my ($timeout, @cmd) = @_;
my $stdin = "";
return captureStdoutStderrWithStdin($timeout, \@cmd, "");
}
sub captureStdoutStderrWithStdin {
my ($timeout, $cmd, $stdin) = @_;
my $stdout;
my $stderr;
eval {
local $SIG{ALRM} = sub { die "timeout\n" }; # NB: \n required
alarm $timeout;
IPC::Run::run(\@cmd, \$stdin, \$stdout, \$stderr);
IPC::Run::run($cmd, \$stdin, \$stdout, \$stderr);
alarm 0;
1;
} or do {

View File

@ -5,6 +5,7 @@ use warnings;
use Hydra::Schema;
use Hydra::Helper::Nix;
use Hydra::Model::DB;
use Term::ReadKey;
use Getopt::Long qw(:config gnu_getopt);
sub showHelp {
@ -14,6 +15,7 @@ Usage: hydra-create-user NAME
[--type hydra|google|github]
[--full-name FULLNAME]
[--email-address EMAIL-ADDRESS]
[--password-prompt]
[--password-hash HASH]
[--password PASSWORD (dangerous)]
[--wipe-roles]
@ -27,6 +29,16 @@ renamed.
* Specifying Passwords
** Interactively
Pass `--password-prompt` to collect the password on stdin.
The password will be hashed with Argon2id when stored.
Example:
$ hydra-create-user alice --password-prompt --role admin
** Specifying a Hash
You can generate a password hash and provide the hash as well. This
@ -63,7 +75,7 @@ Example:
exit 0;
}
my ($renameFrom, $type, $fullName, $emailAddress, $password, $passwordHash);
my ($renameFrom, $type, $fullName, $emailAddress, $password, $passwordHash, $passwordPrompt);
my $wipeRoles = 0;
my @roles;
@ -72,6 +84,7 @@ GetOptions("rename-from=s" => \$renameFrom,
"full-name=s" => \$fullName,
"email-address=s" => \$emailAddress,
"password=s" => \$password,
"password-prompt" => \$passwordPrompt,
"password-hash=s" => \$passwordHash,
"wipe-roles" => \$wipeRoles,
"role=s" => \@roles,
@ -81,9 +94,9 @@ GetOptions("rename-from=s" => \$renameFrom,
die "$0: one user name required\n" if scalar @ARGV != 1;
my $userName = $ARGV[0];
my $chosenPasswordOptions = grep { defined($_) } ($passwordHash, $password);
my $chosenPasswordOptions = grep { defined($_) } ($passwordPrompt, $passwordHash, $password);
if ($chosenPasswordOptions > 1) {
die "$0: please specify only one --password* option. See --help for more information.\n";
die "$0: please specify only one of --password-prompt or --password-hash. See --help for more information.\n";
}
die "$0: type must be `hydra', `google' or `github'\n"
@ -118,17 +131,43 @@ $db->txn_do(sub {
if defined $password;
die "$0: Google and GitHub accounts do not have a password.\n"
if defined $passwordHash;
die "$0: Google and GitHub accounts do not have a password.\n"
if defined $passwordPrompt;
$user->update({ emailaddress => $userName, password => "!" });
} else {
$user->update({ emailaddress => $emailAddress }) if defined $emailAddress;
if (defined $password && !(defined $passwordHash)) {
if (defined $password) {
# !!! TODO: Remove support for plaintext passwords in 2023.
print STDERR "Submitting plaintext passwords as arguments is deprecated and will be removed. See --help for alternatives.\n";
$user->setPassword($password);
}
if (defined $passwordHash) {
$user->setPasswordHash($passwordHash);
}
if (defined $passwordPrompt) {
ReadMode 2;
print STDERR "Password: ";
my $password = <STDIN> // "";
chomp $password;
print STDERR "\nPassword Confirmation: ";
my $passwordConfirm = <STDIN> // "";
chomp $passwordConfirm;
ReadMode 0;
print STDERR "\n";
if ($password ne $passwordConfirm) {
die "Passwords don't match."
} elsif ($password eq "") {
die "Password cannot be empty."
}
$user->setPassword($password);
}
}
$user->userroles->delete if $wipeRoles;