mod operator_cli;
mod operator_tooling;
mod s3_listener;
use operator_cli::{parse_operator_command, OperatorCommand, S3ServeStorage, HELP};
#[derive(Debug)]
pub enum CliError {
Usage(String),
Runtime(anyhow::Error),
}
impl std::fmt::Display for CliError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Usage(message) => write!(f, "{message}"),
Self::Runtime(error) => write!(f, "{error}"),
}
}
}
impl std::error::Error for CliError {}
impl From<anyhow::Error> for CliError {
fn from(error: anyhow::Error) -> Self {
Self::Runtime(error)
}
}
pub fn run_env() -> Result<(), CliError> {
run(std::env::args().collect())
}
pub fn run(args: Vec<String>) -> Result<(), CliError> {
let mut command = parse_operator_command(&args).map_err(CliError::Usage)?;
let mut quiet = false;
let mut verbosity = 0;
if let OperatorCommand::Global {
options,
command: inner,
} = command
{
quiet = options.quiet;
verbosity = options.verbose;
command = *inner;
}
if quiet
&& matches!(
command,
OperatorCommand::Help | OperatorCommand::DefaultStatus | OperatorCommand::Version
)
{
return Ok(());
}
match command {
OperatorCommand::Help => {
print!("{HELP}");
return Ok(());
}
OperatorCommand::Version => {
print!("{}", operator_cli::version_text());
return Ok(());
}
OperatorCommand::Global { .. } => {
unreachable!("global command wrappers are unwrapped before dispatch")
}
OperatorCommand::Health { config_path } => {
println!("{}", operator_cli::health_json(config_path.as_deref())?);
return Ok(());
}
OperatorCommand::Readiness { config_path } => {
println!("{}", operator_cli::readiness_json(config_path.as_deref())?);
return Ok(());
}
OperatorCommand::Diagnostics { config_path } => {
let diagnostics = if verbosity > 0 {
operator_cli::diagnostics_json_with_cli_metadata(config_path.as_deref(), verbosity)?
} else {
operator_cli::diagnostics_json(config_path.as_deref())?
};
println!("{diagnostics}");
return Ok(());
}
OperatorCommand::Metrics { config_path } => {
print!("{}", operator_cli::metrics_text(config_path.as_deref())?);
return Ok(());
}
OperatorCommand::OpsReportHealth {
config_path,
bucket,
} => {
println!(
"{}",
operator_cli::ops_report_health_json(config_path.as_deref(), bucket.as_deref(),)?
);
return Ok(());
}
OperatorCommand::OpsReportConfig {
config_path,
bucket,
} => {
println!(
"{}",
operator_cli::ops_report_config_json(config_path.as_deref(), bucket.as_deref(),)?
);
return Ok(());
}
OperatorCommand::OpsReportAdminSurfaces {
config_path,
bucket,
} => {
println!(
"{}",
operator_cli::ops_report_admin_surfaces_json(
config_path.as_deref(),
bucket.as_deref(),
)?
);
return Ok(());
}
OperatorCommand::OpsReportIncident {
config_path,
bucket,
incident_type,
} => {
println!(
"{}",
operator_cli::ops_report_incident_json(
config_path.as_deref(),
bucket.as_deref(),
&incident_type,
)?
);
return Ok(());
}
OperatorCommand::OpsReportEvidenceExport {
config_path,
bucket,
} => {
println!(
"{}",
operator_cli::ops_report_evidence_export_json(
config_path.as_deref(),
bucket.as_deref(),
)?
);
return Ok(());
}
OperatorCommand::UiBrowserManifest => {
println!("{}", operator_cli::ui_browser_manifest_json());
return Ok(());
}
OperatorCommand::UiBrowserHtml => {
print!("{}", operator_cli::ui_browser_html());
return Ok(());
}
OperatorCommand::UiBrowserCss => {
print!("{}", operator_cli::ui_browser_css());
return Ok(());
}
OperatorCommand::UiBrowserJs => {
print!("{}", operator_cli::ui_browser_js());
return Ok(());
}
OperatorCommand::ConfigValidate { config_path } => {
println!("{}", operator_cli::validate_config_path(&config_path)?);
return Ok(());
}
OperatorCommand::AuditExport { config_path } => {
print!("{}", operator_cli::audit_export(config_path.as_deref())?);
return Ok(());
}
OperatorCommand::ReplicationStatus { config_path } => {
println!(
"{}",
operator_cli::replication_status_json(config_path.as_deref())?
);
return Ok(());
}
OperatorCommand::S3Serve {
bind,
console_bind,
config_path,
principal,
access_key_id,
secret_access_key,
storage,
} => {
let storage = match storage {
S3ServeStorage::Filesystem { data_dir } => s3_listener::S3StorageMode::Filesystem {
data_dir: data_dir.into(),
},
S3ServeStorage::InMemory => s3_listener::S3StorageMode::InMemory,
};
return Ok(s3_listener::serve(s3_listener::S3ServeOptions {
bind,
console_bind,
config: operator_cli::load_runtime_config(config_path.as_deref())?,
principal,
access_key_id,
secret_access_key,
storage,
})?);
}
OperatorCommand::PolicyExplain(args) => {
println!("{}", operator_tooling::policy_explain_json(&args)?);
return Ok(());
}
OperatorCommand::PolicySimulate(args) => {
println!("{}", operator_tooling::policy_simulate_json(&args)?);
return Ok(());
}
OperatorCommand::PolicyAnalyze => {
println!("{}", operator_tooling::policy_analyze_json()?);
return Ok(());
}
OperatorCommand::AuthReportIdentityProviders => {
println!(
"{}",
operator_tooling::auth_report_identity_providers_json()?
);
return Ok(());
}
OperatorCommand::AuthReportCredentials => {
println!("{}", operator_tooling::auth_report_credentials_json()?);
return Ok(());
}
OperatorCommand::AuthReportTemporaryCredentials => {
println!(
"{}",
operator_tooling::auth_report_temporary_credentials_json()?
);
return Ok(());
}
OperatorCommand::AuthRoleAssign {
principal,
role,
scope,
} => {
println!(
"{}",
operator_tooling::auth_role_assign_json(&principal, role, &scope)?
);
return Ok(());
}
OperatorCommand::AuthRoleList { principal } => {
println!("{}", operator_tooling::auth_role_list_json(&principal)?);
return Ok(());
}
OperatorCommand::AuthKeyRotate {
principal,
old_access_key_id,
new_access_key_id,
secret_access_key,
} => {
println!(
"{}",
operator_tooling::auth_key_rotate_json(
&principal,
&old_access_key_id,
&new_access_key_id,
&secret_access_key,
)?
);
return Ok(());
}
OperatorCommand::AuthKeyRevoke {
principal,
access_key_id,
} => {
println!(
"{}",
operator_tooling::auth_key_revoke_json(&principal, &access_key_id)?
);
return Ok(());
}
OperatorCommand::AuthKeyReportLeaked {
principal,
access_key_id,
} => {
println!(
"{}",
operator_tooling::auth_key_report_leaked_json(&principal, &access_key_id)?
);
return Ok(());
}
OperatorCommand::Conformance { target } => {
bucketwarden_demo::print_conformance(target.as_deref())?;
return Ok(());
}
OperatorCommand::Demo(command) => {
let runtime =
bucketwarden_server::BucketWarden::new(operator_cli::load_runtime_config(None)?)
.map_err(anyhow::Error::from)?;
return Ok(bucketwarden_demo::run_demo_command(&command, &runtime)?);
}
OperatorCommand::DefaultStatus => {
print_default_status();
return Ok(());
}
}
unreachable!("all operator commands should be fully handled by match arms");
}
fn print_default_status() {
println!(
"{}",
serde_json::json!({
"name": "bucketwarden",
"status": "ready",
"certified_runtime_slice": "in-memory-0.1.0"
})
);
}