swarmctl: forge make-admin
Calls POST /api/forge/users/{name}/admin and prints what it found. It
fails with the controller's message when the user has not logged in via
SSO yet, and when the name is an agent's.
Refs #3782
This commit is contained in:
parent
f1f59ea165
commit
d56d8f2b36
4 changed files with 157 additions and 2 deletions
|
|
@ -28,6 +28,7 @@
|
|||
//! for the same reason `hivectl` does not link `hive-c0re`.
|
||||
|
||||
mod agent;
|
||||
mod forge;
|
||||
mod users;
|
||||
|
||||
use std::fs::{self, File, Permissions};
|
||||
|
|
@ -123,6 +124,11 @@ enum Verb {
|
|||
#[command(subcommand)]
|
||||
command: UserVerb,
|
||||
},
|
||||
/// Manage human accounts on the swarm's forge.
|
||||
Forge {
|
||||
#[command(subcommand)]
|
||||
command: ForgeVerb,
|
||||
},
|
||||
/// Emit the full CLI reference as `CommonMark` to stdout.
|
||||
///
|
||||
/// Hidden tooling command used by the docs build to keep the published
|
||||
|
|
@ -255,6 +261,29 @@ struct AgentMintIdentityArgs {
|
|||
controller_socket: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum ForgeVerb {
|
||||
/// Make an existing forge user a site admin.
|
||||
///
|
||||
/// The forge creates a human's account on their first SSO login, and
|
||||
/// this fails until that login has happened. Running it on a site admin
|
||||
/// changes nothing. Refused for an agent.
|
||||
MakeAdmin(ForgeMakeAdminArgs),
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
struct ForgeMakeAdminArgs {
|
||||
/// Forge username, the same as the user's SSO username.
|
||||
name: String,
|
||||
/// swarm-controller's unix socket.
|
||||
///
|
||||
/// Supplied by the nix module that installs this binary, from the same
|
||||
/// `socketPath` option the daemon binds; falls back to
|
||||
/// `SWARM_CONTROLLER_SOCKET`.
|
||||
#[arg(long, value_name = "PATH")]
|
||||
controller_socket: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum UserVerb {
|
||||
/// Add a user, generating a password for them.
|
||||
|
|
@ -337,6 +366,13 @@ fn main() -> Result<()> {
|
|||
let socket = path_from(args.controller_socket, "SWARM_CONTROLLER_SOCKET")?;
|
||||
agent::mint_forge_token(&socket, &args.name)
|
||||
}
|
||||
// Same socket-resolution reasoning as `Create` above.
|
||||
Verb::Forge {
|
||||
command: ForgeVerb::MakeAdmin(args),
|
||||
} => {
|
||||
let socket = path_from(args.controller_socket, "SWARM_CONTROLLER_SOCKET")?;
|
||||
forge::make_admin(&socket, &args.name)
|
||||
}
|
||||
// Resolved lazily, inside the one arm that actually touches the
|
||||
// deployment env vars — see the `MarkdownDocs` doc comment above
|
||||
// for why an unconditional resolve up front would be wrong.
|
||||
|
|
@ -751,6 +787,24 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_make_admin_verb_takes_a_user_name() {
|
||||
let cli = Cli::try_parse_from(["swarmctl", "forge", "make-admin", "mara"])
|
||||
.expect("the minimal form parses");
|
||||
let Verb::Forge {
|
||||
command: ForgeVerb::MakeAdmin(args),
|
||||
} = cli.command
|
||||
else {
|
||||
panic!("expected `forge make-admin`");
|
||||
};
|
||||
assert_eq!(args.name, "mara");
|
||||
assert!(args.controller_socket.is_none());
|
||||
assert!(
|
||||
Cli::try_parse_from(["swarmctl", "forge", "make-admin"]).is_err(),
|
||||
"the user must be named"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_authelia_hash_output() {
|
||||
let out = "Random Password: hunter2\nDigest: $argon2id$v=19$m=65536$abc\n";
|
||||
|
|
|
|||
Loading…
Reference in a new issue