use super::{command_mechanism, ActionSpec};
use sysknife_types::RiskLevel;
pub fn specs() -> Vec<ActionSpec> {
vec![
apparmor_status(),
apparmor_enforce("/etc/apparmor.d/usr.bin.firefox"),
apparmor_complain("/etc/apparmor.d/usr.bin.firefox"),
]
}
pub fn apparmor_status() -> ActionSpec {
ActionSpec {
action_name: "AppArmorStatus",
mechanism: command_mechanism("sudo", ["aa-status"]),
risk_level: RiskLevel::Low,
reboot_required: false,
rollback_available: false,
}
}
pub fn apparmor_enforce(profile_path: &str) -> ActionSpec {
ActionSpec {
action_name: "AppArmorEnforce",
mechanism: command_mechanism("sudo", ["aa-enforce", "--", profile_path]),
risk_level: RiskLevel::High,
reboot_required: false,
rollback_available: false,
}
}
pub fn apparmor_complain(profile_path: &str) -> ActionSpec {
ActionSpec {
action_name: "AppArmorComplain",
mechanism: command_mechanism("sudo", ["aa-complain", "--", profile_path]),
risk_level: RiskLevel::High,
reboot_required: false,
rollback_available: false,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::actions::ActionMechanism;
fn extract_args(spec: &ActionSpec) -> (&'static str, Vec<String>) {
match &spec.mechanism {
ActionMechanism::Command { program, args } => (*program, args.clone()),
_ => panic!("expected Command mechanism"),
}
}
#[test]
fn apparmor_status_action_name() {
assert_eq!(apparmor_status().action_name, "AppArmorStatus");
}
#[test]
fn apparmor_status_risk_is_low() {
assert_eq!(apparmor_status().risk_level, RiskLevel::Low);
}
#[test]
fn apparmor_status_argv() {
let spec = apparmor_status();
let (prog, args) = extract_args(&spec);
assert_eq!(prog, "sudo");
let a: Vec<&str> = args.iter().map(String::as_str).collect();
assert_eq!(a, vec!["aa-status"]);
}
#[test]
fn apparmor_enforce_action_name() {
assert_eq!(
apparmor_enforce("/etc/apparmor.d/usr.bin.firefox").action_name,
"AppArmorEnforce"
);
}
#[test]
fn apparmor_enforce_risk_is_high() {
assert_eq!(
apparmor_enforce("/etc/apparmor.d/usr.bin.firefox").risk_level,
RiskLevel::High
);
}
#[test]
fn apparmor_enforce_argv() {
let profile = "/etc/apparmor.d/usr.bin.firefox";
let spec = apparmor_enforce(profile);
let (prog, args) = extract_args(&spec);
assert_eq!(prog, "sudo");
let a: Vec<&str> = args.iter().map(String::as_str).collect();
assert_eq!(a, vec!["aa-enforce", "--", profile]);
}
#[test]
fn apparmor_complain_action_name() {
assert_eq!(
apparmor_complain("/etc/apparmor.d/usr.bin.firefox").action_name,
"AppArmorComplain"
);
}
#[test]
fn apparmor_complain_risk_is_high() {
assert_eq!(
apparmor_complain("/etc/apparmor.d/usr.bin.firefox").risk_level,
RiskLevel::High
);
}
#[test]
fn apparmor_complain_argv() {
let profile = "/etc/apparmor.d/usr.bin.nginx";
let spec = apparmor_complain(profile);
let (prog, args) = extract_args(&spec);
assert_eq!(prog, "sudo");
let a: Vec<&str> = args.iter().map(String::as_str).collect();
assert_eq!(a, vec!["aa-complain", "--", profile]);
}
#[test]
fn enforce_uses_aa_enforce_not_aa_complain() {
let spec = apparmor_enforce("/etc/apparmor.d/test");
let (_, args) = extract_args(&spec);
let a: Vec<&str> = args.iter().map(String::as_str).collect();
assert!(a.contains(&"aa-enforce"));
assert!(!a.contains(&"aa-complain"));
}
#[test]
fn complain_uses_aa_complain_not_aa_enforce() {
let spec = apparmor_complain("/etc/apparmor.d/test");
let (_, args) = extract_args(&spec);
let a: Vec<&str> = args.iter().map(String::as_str).collect();
assert!(a.contains(&"aa-complain"));
assert!(!a.contains(&"aa-enforce"));
}
#[test]
fn specs_covers_all_action_names() {
let expected = ["AppArmorStatus", "AppArmorEnforce", "AppArmorComplain"];
let spec_names: Vec<&str> = specs().iter().map(|s| s.action_name).collect();
for name in &expected {
assert!(spec_names.contains(name), "specs() missing {name}");
}
}
}