use crate::parse::Token;
use crate::registry;
use crate::verdict::Verdict;
pub fn check_tilt(tokens: &[Token]) -> Verdict {
if let Some(verdict) = registry::try_sub_dispatch("tilt", tokens) {
return verdict;
}
registry::try_fallback_grammar("tilt", tokens).unwrap_or(Verdict::Denied)
}
#[cfg(test)]
mod tests {
use crate::is_safe_command;
use crate::verdict::{SafetyLevel, Verdict};
fn check(cmd: &str) -> bool {
is_safe_command(cmd)
}
fn verdict(cmd: &str) -> Verdict {
crate::command_verdict(cmd)
}
safe! {
bare: "tilt",
long_help: "tilt --help",
short_help: "tilt -h",
long_version: "tilt --version",
short_version_lower: "tilt -v",
short_version_upper: "tilt -V",
ruby_long_list: "tilt --list",
ruby_short_list: "tilt -l",
ruby_render_extension: "tilt template.erb",
ruby_render_subdir: "tilt views/index.haml",
ruby_render_absolute: "tilt /tmp/page.md",
ruby_render_stdin: "tilt -",
ruby_render_with_type_long: "tilt --type erb template.erb",
ruby_render_with_type_short: "tilt -t erb template.erb",
ruby_render_with_type_eq: "tilt --type=erb template.erb",
ruby_render_with_layout: "tilt --layout layout.erb page.erb",
ruby_render_with_layout_short: "tilt -y layout.erb page.erb",
ruby_render_flags_after_file: "tilt page.erb -t erb",
k8s_version: "tilt version",
k8s_version_help: "tilt version --help",
k8s_doctor: "tilt doctor",
k8s_verify_install: "tilt verify-install",
k8s_completion: "tilt completion bash",
k8s_help: "tilt help",
k8s_help_topic: "tilt help up",
k8s_get: "tilt get pod",
k8s_get_named: "tilt get pod my-pod",
k8s_get_namespace: "tilt get pod -n default",
k8s_get_namespace_eq: "tilt get pod --namespace=default",
k8s_get_all_namespaces: "tilt get pod -A",
k8s_describe: "tilt describe pod my-pod",
k8s_describe_namespace: "tilt describe pod my-pod -n prod",
}
denied! {
k8s_up: "tilt up",
k8s_down: "tilt down",
k8s_ci: "tilt ci",
k8s_apply: "tilt apply -f manifest",
k8s_delete: "tilt delete resource",
k8s_trigger: "tilt trigger build",
k8s_logs: "tilt logs",
k8s_dump: "tilt dump engine",
bare_word_first: "tilt foo",
bare_word_render: "tilt template",
unknown_flag: "tilt --evil",
unknown_short: "tilt -X",
two_files: "tilt a.erb b.erb",
version_extra: "tilt version foo",
doctor_with_dash_flag: "tilt doctor --evil",
}
#[test]
fn k8s_get_returns_safe_read() {
assert_eq!(
verdict("tilt get pod"),
Verdict::Allowed(SafetyLevel::SafeRead),
);
}
#[test]
fn ruby_render_returns_inert() {
assert_eq!(
verdict("tilt template.erb"),
Verdict::Allowed(SafetyLevel::Inert),
);
}
#[test]
fn k8s_doctor_returns_inert() {
assert_eq!(
verdict("tilt doctor"),
Verdict::Allowed(SafetyLevel::Inert),
);
}
use proptest::prelude::*;
proptest! {
#[test]
fn get_with_random_resource_is_safe_read(
resource in "[a-z][a-z0-9-]{0,15}",
) {
let cmd = format!("tilt get {resource}");
prop_assert_eq!(
crate::command_verdict(&cmd),
Verdict::Allowed(SafetyLevel::SafeRead),
);
}
#[test]
fn describe_with_random_resource_is_safe_read(
resource in "[a-z][a-z0-9-]{0,15}",
name in "[a-z][a-z0-9-]{0,15}",
) {
let cmd = format!("tilt describe {resource} {name}");
prop_assert_eq!(
crate::command_verdict(&cmd),
Verdict::Allowed(SafetyLevel::SafeRead),
);
}
#[test]
fn random_path_shaped_arg_is_inert(
stem in "[a-z][a-z0-9_]{0,15}",
ext in "(erb|haml|md|slim|txt)",
) {
let cmd = format!("tilt {stem}.{ext}");
prop_assert_eq!(
crate::command_verdict(&cmd),
Verdict::Allowed(SafetyLevel::Inert),
);
}
#[test]
fn random_bare_word_is_denied(
word in "[a-z][a-z0-9-]{0,15}",
) {
let known_subs = [
"doctor", "verify-install", "version",
"completion", "help", "describe", "get",
];
prop_assume!(!known_subs.contains(&word.as_str()));
let cmd = format!("tilt {word}");
prop_assert_eq!(crate::command_verdict(&cmd), Verdict::Denied);
}
}
}