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).
149 lines
4.2 KiB
Rust
149 lines
4.2 KiB
Rust
use serde::Deserialize;
|
|
|
|
/// Gateway configuration, loaded from environment variables with BASCULE_ prefix.
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct BasculeConfig {
|
|
/// gRPC listen address (default: 0.0.0.0:50052)
|
|
#[serde(default = "default_listen_addr")]
|
|
pub listen_addr: String,
|
|
|
|
/// OIDC issuer URL for token validation
|
|
#[serde(default = "default_oidc_issuer")]
|
|
pub oidc_issuer: String,
|
|
|
|
/// Expected OIDC audience (client_id)
|
|
#[serde(default = "default_oidc_audience")]
|
|
pub oidc_audience: String,
|
|
|
|
/// Default session lifetime in seconds for self-grant ceremonies
|
|
#[serde(default = "default_session_lifetime")]
|
|
pub session_lifetime_secs: u64,
|
|
|
|
// --- Database (QM-provisioned bascule_svc credentials) ---
|
|
#[serde(default = "default_db_host")]
|
|
pub db_host: String,
|
|
|
|
#[serde(default = "default_db_port")]
|
|
pub db_port: u16,
|
|
|
|
#[serde(default = "default_db_name")]
|
|
pub db_name: String,
|
|
|
|
#[serde(default = "default_db_user")]
|
|
pub db_user: String,
|
|
|
|
#[serde(default)]
|
|
pub db_password: String,
|
|
|
|
// --- OPA sidecar ---
|
|
#[serde(default = "default_opa_url")]
|
|
pub opa_url: String,
|
|
|
|
// --- Quartermaster endpoint ---
|
|
#[serde(default = "default_qm_endpoint")]
|
|
pub qm_endpoint: String,
|
|
|
|
// --- Accord ---
|
|
#[serde(default = "default_accord_path")]
|
|
pub accord_path: String,
|
|
|
|
// --- Audit pipeline ---
|
|
#[serde(default = "default_audit_batch_size")]
|
|
pub audit_batch_size: usize,
|
|
|
|
#[serde(default = "default_audit_flush_interval")]
|
|
pub audit_flush_interval_secs: u64,
|
|
}
|
|
|
|
fn default_listen_addr() -> String {
|
|
"0.0.0.0:50052".to_string()
|
|
}
|
|
|
|
fn default_oidc_issuer() -> String {
|
|
"http://localhost:8080/realms/guildhouse".to_string()
|
|
}
|
|
|
|
fn default_oidc_audience() -> String {
|
|
"bascule-gateway".to_string()
|
|
}
|
|
|
|
fn default_session_lifetime() -> u64 {
|
|
28800 // 8 hours
|
|
}
|
|
|
|
fn default_db_host() -> String {
|
|
"localhost".to_string()
|
|
}
|
|
|
|
fn default_db_port() -> u16 {
|
|
5432
|
|
}
|
|
|
|
fn default_db_name() -> String {
|
|
"telemetry".to_string()
|
|
}
|
|
|
|
fn default_db_user() -> String {
|
|
"bascule_svc".to_string()
|
|
}
|
|
|
|
fn default_opa_url() -> String {
|
|
"http://localhost:8181".to_string()
|
|
}
|
|
|
|
fn default_qm_endpoint() -> String {
|
|
"http://quartermaster.quartermaster.svc.cluster.local:50051".to_string()
|
|
}
|
|
|
|
fn default_accord_path() -> String {
|
|
"/accord/accord.yaml".to_string()
|
|
}
|
|
|
|
fn default_audit_batch_size() -> usize {
|
|
50
|
|
}
|
|
|
|
fn default_audit_flush_interval() -> u64 {
|
|
10
|
|
}
|
|
|
|
impl BasculeConfig {
|
|
pub fn from_env() -> anyhow::Result<Self> {
|
|
let config = config::Config::builder()
|
|
.add_source(
|
|
config::Environment::with_prefix("BASCULE")
|
|
.separator("__")
|
|
.try_parsing(true),
|
|
)
|
|
.set_default("listen_addr", default_listen_addr())?
|
|
.set_default("oidc_issuer", default_oidc_issuer())?
|
|
.set_default("oidc_audience", default_oidc_audience())?
|
|
.set_default("session_lifetime_secs", default_session_lifetime() as i64)?
|
|
.set_default("db_host", default_db_host())?
|
|
.set_default("db_port", default_db_port() as i64)?
|
|
.set_default("db_name", default_db_name())?
|
|
.set_default("db_user", default_db_user())?
|
|
.set_default("db_password", "")?
|
|
.set_default("opa_url", default_opa_url())?
|
|
.set_default("qm_endpoint", default_qm_endpoint())?
|
|
.set_default("accord_path", default_accord_path())?
|
|
.set_default("audit_batch_size", default_audit_batch_size() as i64)?
|
|
.set_default("audit_flush_interval_secs", default_audit_flush_interval() as i64)?
|
|
.build()?;
|
|
|
|
Ok(config.try_deserialize()?)
|
|
}
|
|
|
|
/// HTTP listen address for ceremony approval endpoints.
|
|
pub fn http_listen_addr(&self) -> String {
|
|
std::env::var("BASCULE__HTTP_LISTEN_ADDR").unwrap_or_else(|_| "0.0.0.0:8443".to_string())
|
|
}
|
|
|
|
/// Build a PostgreSQL connection URL from the individual config fields.
|
|
pub fn database_url(&self) -> String {
|
|
format!(
|
|
"postgresql://{}:{}@{}:{}/{}",
|
|
self.db_user, self.db_password, self.db_host, self.db_port, self.db_name
|
|
)
|
|
}
|
|
}
|