feat: configurable corpus base dir + Bascule dev config
- corpus_check_with_base(): accepts explicit base directory - corpus_check(): still defaults to /opt/substrate/corpus - Improved corpus test with actual Allowed/Denied assertions - Updated bascule-dev.toml with [gsap] section and shell_command Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fcc7758249
commit
5f7f9c0ff7
3 changed files with 27 additions and 7 deletions
|
|
@ -6,8 +6,15 @@ ca_key_path = "/dev/null"
|
|||
host_key_path = "/dev/null"
|
||||
dispatch_mode = "direct"
|
||||
auth_mode = "permissive"
|
||||
shell_command = "/home/tking/.local/bin/gsh"
|
||||
|
||||
[elevation]
|
||||
operator_ttl_secs = 3600
|
||||
admin_ttl_secs = 1800
|
||||
emergency_ttl_secs = 900
|
||||
|
||||
[gsap]
|
||||
# broker_url = "http://localhost:8091"
|
||||
# token = ""
|
||||
default_corpus_cid = "sha256:dev-jumphost"
|
||||
default_accord_template = "shell-exec"
|
||||
|
|
|
|||
|
|
@ -15,15 +15,24 @@ pub enum CorpusCheckResult {
|
|||
Denied { command: String, corpus_cid: String },
|
||||
}
|
||||
|
||||
/// Default corpus base directory.
|
||||
pub const DEFAULT_CORPUS_BASE: &str = "/opt/substrate/corpus";
|
||||
|
||||
/// Check if a command is authorized in the corpus directory.
|
||||
///
|
||||
/// `base_dir` overrides the default /opt/substrate/corpus (set via GSH_CORPUS_DIR env).
|
||||
/// Returns Ok(result) always. Caller decides whether to block on Denied.
|
||||
pub fn corpus_check(corpus_cid: &str, command: &str) -> CorpusCheckResult {
|
||||
corpus_check_with_base(corpus_cid, command, DEFAULT_CORPUS_BASE)
|
||||
}
|
||||
|
||||
/// corpus_check with an explicit base directory.
|
||||
pub fn corpus_check_with_base(corpus_cid: &str, command: &str, base_dir: &str) -> CorpusCheckResult {
|
||||
if corpus_cid == "sha256:ungoverned" {
|
||||
return CorpusCheckResult::Ungoverned;
|
||||
}
|
||||
|
||||
let corpus_dir = Path::new("/opt/substrate/corpus").join(corpus_cid);
|
||||
let corpus_dir = Path::new(base_dir).join(corpus_cid);
|
||||
if !corpus_dir.exists() {
|
||||
return CorpusCheckResult::NotMounted;
|
||||
}
|
||||
|
|
@ -73,10 +82,14 @@ mod tests {
|
|||
std::fs::create_dir_all(&corpus_dir).unwrap();
|
||||
std::fs::write(corpus_dir.join("kubectl"), "").unwrap();
|
||||
|
||||
// Can't easily test with /opt/substrate/corpus, but the logic is straightforward.
|
||||
// The unit test validates the command name extraction:
|
||||
let cmd = "kubectl get pods -n test";
|
||||
let name = cmd.split_whitespace().next().unwrap();
|
||||
assert_eq!(name, "kubectl");
|
||||
let base = dir.path().to_str().unwrap();
|
||||
assert!(matches!(
|
||||
corpus_check_with_base(cid, "kubectl get pods -n test", base),
|
||||
CorpusCheckResult::Allowed
|
||||
));
|
||||
assert!(matches!(
|
||||
corpus_check_with_base(cid, "helm install", base),
|
||||
CorpusCheckResult::Denied { .. }
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ pub mod session;
|
|||
pub use ac::{AcValidationError, AuthorizationContext};
|
||||
pub use classifier::{classify_command, CommandClass, FREE_COMMANDS};
|
||||
pub use config::GshConfig;
|
||||
pub use corpus::{corpus_check, CorpusCheckResult};
|
||||
pub use corpus::{corpus_check, corpus_check_with_base, CorpusCheckResult, DEFAULT_CORPUS_BASE};
|
||||
pub use cr::{post_cr, CrResult};
|
||||
pub use registry::ConsumedRegistry;
|
||||
pub use session::SessionState;
|
||||
|
|
|
|||
Loading…
Reference in a new issue