swarmctl: add bao init and bao grant-bootstrap
init prints the store's keys and root token once and keeps none; with --and-grant it goes on to the granter bootstrap in the same process. grant-bootstrap does that step alone, reading the root token from a hidden prompt or stdin. The token reaches bao only as BAO_TOKEN in the child's environment.
This commit is contained in:
parent
e9321297c0
commit
a20596fa59
1 changed files with 909 additions and 26 deletions
|
|
@ -19,7 +19,8 @@
|
|||
//! work they ask for is only the controller's to do (see [`agent`]). They
|
||||
//! reach it over its unix socket on its host, or, with `--swarm`, through
|
||||
//! the swarm domain's gateway as the operator's own SSO account
|
||||
//! ([`remote`]). The `user` verbs act on the local users file only.
|
||||
//! ([`remote`]). The `user` verbs act on the local users file only; the `bao`
|
||||
//! verbs run the `bao` CLI against the secret store.
|
||||
//!
|
||||
//! Distinct from `hivectl`, which drives one hive's `hive-c0re` over its
|
||||
//! admin socket. This crate deliberately does not link `swarm-controller`,
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
|
||||
mod agent;
|
||||
mod agents_md;
|
||||
mod bao;
|
||||
mod forge;
|
||||
mod inference;
|
||||
mod login;
|
||||
|
|
@ -220,6 +222,15 @@ enum Verb {
|
|||
#[command(subcommand)]
|
||||
command: SetupVerb,
|
||||
},
|
||||
/// Initialise the swarm's secret store and bootstrap its granter.
|
||||
///
|
||||
/// Runs the `bao` CLI against the store over HTTPS, so the store need
|
||||
/// not run on this host. The root token never reaches a file, an
|
||||
/// argument list or an environment variable of this process.
|
||||
Bao {
|
||||
#[command(subcommand)]
|
||||
command: BaoVerb,
|
||||
},
|
||||
/// Log in to the swarm named by `--swarm` as your own SSO account.
|
||||
///
|
||||
/// With no `--swarm` or `SWARMCTL_SWARM`, logs in to
|
||||
|
|
@ -286,6 +297,25 @@ struct SetupStatusArgs {
|
|||
socket: ControllerSocketArg,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum BaoVerb {
|
||||
/// Initialise the store, printing its keys and the root token once.
|
||||
///
|
||||
/// Prints the unseal or recovery keys and the root token to stdout, once,
|
||||
/// and stores none of them: record them off this host before doing
|
||||
/// anything else. Refuses an initialised store.
|
||||
Init(bao::InitArgs),
|
||||
/// Bootstrap the granter: the one-time step that lets `swarm-bao-granter-role`
|
||||
/// write every `swarm-*` policy and role.
|
||||
///
|
||||
/// Reads the root token from a hidden prompt, or from stdin when stdin isn't
|
||||
/// a terminal; never from an argument or an environment variable. Writes
|
||||
/// the `bao-bootstrap` policy, places a 24h grant token for the granter unit
|
||||
/// and restarts it, so run it as root on the host running that unit. Says so
|
||||
/// and does nothing when the granter exists already.
|
||||
GrantBootstrap(bao::GrantBootstrapArgs),
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum AgentVerb {
|
||||
/// Queue creation of a new agent on a hive in this swarm.
|
||||
|
|
@ -798,6 +828,13 @@ fn main() -> Result<()> {
|
|||
let target = remote.target(args.controller_socket)?;
|
||||
forge::make_admin(&target, &args.name)
|
||||
}
|
||||
// Acts through the `bao` CLI only: none of the `SWARMCTL_AUTHELIA_*` values apply.
|
||||
Verb::Bao {
|
||||
command: BaoVerb::Init(args),
|
||||
} => bao::init(args),
|
||||
Verb::Bao {
|
||||
command: BaoVerb::GrantBootstrap(args),
|
||||
} => bao::grant_bootstrap(args),
|
||||
// Same socket-resolution reasoning as `Create` above.
|
||||
Verb::Schedule { command } => schedule(&remote, command),
|
||||
// Neither the controller socket nor the users file is required: a
|
||||
|
|
@ -1718,7 +1755,7 @@ mod tests {
|
|||
/// rather than from this one: a write fd on it held here could be inherited
|
||||
/// by a child another test thread forks, and exec'ing a file some process
|
||||
/// still holds open for writing fails with `ETXTBSY`.
|
||||
fn write_executable(path: &std::path::Path, body: &str) {
|
||||
pub(crate) fn write_executable(path: &std::path::Path, body: &str) {
|
||||
let status = std::process::Command::new("/bin/sh")
|
||||
.args([
|
||||
"-c",
|
||||
|
|
|
|||
Loading…
Reference in a new issue