bascule-workspace/bascule-agent/src/bin/sb.rs
Tyler King b1865a0627 initial: bascule v0.1.0
Bascule shell runtime workspace — governed shell access layer
for Substrate/Guildhouse FFC deployments.

Crates:
- bascule-agent: node agent with SSH server + command filtering
- bascule-core: audit, grant engine, ceremony types, session
- bascule-filter-core: log line filtering (stdio protocol)
- bascule-gateway: OIDC auth, session management, SAT validation
- bascule-node-agent: k8s DaemonSet agent (pod watcher, BPF manager)
- bascule-proto: protobuf definitions
- bascule-shell: governed SSH shell (commands, elevation, REPL)
- bascule-tail: chronicle log tail + fanout
- ceremony-engine: ceremony lifecycle (6 types + request/resolution)

172 tests passing.
Implements SBS-SPEC-0001 shell model.
Reference impl for SPEC-SHELLOPS-0001 Layer 1 (root shell).
2026-03-18 16:40:48 -04:00

93 lines
2.3 KiB
Rust

//! sb — Substrate CLI
//!
//! Currently supports:
//! sb shell [--host HOST] [--port PORT] [--user USER]
//!
//! Connects to the bascule-agent's governed SSH shell.
use std::process::Command;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "sb", about = "Substrate CLI", version)]
struct Cli {
#[command(subcommand)]
command: SubCmd,
}
#[derive(Subcommand)]
enum SubCmd {
/// Connect to the bascule-agent governed shell via SSH.
Shell {
/// SSH host to connect to.
#[arg(long, default_value = "localhost")]
host: String,
/// SSH port.
#[arg(short, long, default_value = "2222")]
port: u16,
/// SSH username.
#[arg(short, long, default_value_t = whoami())]
user: String,
/// SSH identity file (private key).
#[arg(short, long)]
identity: Option<String>,
},
/// Show agent status via IPC socket.
Status {
/// Path to the agent Unix socket.
#[arg(long, default_value = "/var/run/substrate/agent.sock")]
socket: String,
},
}
fn whoami() -> String {
std::env::var("USER").unwrap_or_else(|_| "substrate".to_string())
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
SubCmd::Shell {
host,
port,
user,
identity,
} => {
let mut cmd = Command::new("ssh");
cmd.arg("-p").arg(port.to_string());
cmd.arg("-o").arg("StrictHostKeyChecking=no");
cmd.arg("-o").arg("UserKnownHostsFile=/dev/null");
cmd.arg("-o").arg("LogLevel=ERROR");
if let Some(ref key) = identity {
cmd.arg("-i").arg(key);
}
cmd.arg(format!("{user}@{host}"));
eprintln!("Connecting to bascule-agent shell at {host}:{port}...");
let status = cmd.status()?;
if !status.success() {
std::process::exit(status.code().unwrap_or(1));
}
}
SubCmd::Status { socket } => {
if std::path::Path::new(&socket).exists() {
println!("Agent socket: {} (active)", socket);
} else {
println!("Agent socket: {} (not found)", socket);
std::process::exit(1);
}
}
}
Ok(())
}