hyperion-vault-core 0.3.0

Pure-Rust security core for hyperion-vault: envelope encryption, IP allowlist, token auth, rotation policy
Documentation
pub const ACTIONS: [&str; 4] = ["create", "update", "delete", "rotate"];

pub fn is_valid_action(action: &str) -> bool {
    action == "*" || ACTIONS.contains(&action)
}

pub fn path_matches(pattern: &str, name: &str) -> bool {
    match pattern.strip_suffix('*') {
        Some(prefix) => name.starts_with(prefix),
        None => pattern == name,
    }
}

pub fn action_matches(rule_action: &str, action: &str) -> bool {
    rule_action == "*" || rule_action == action
}

pub fn authorize(is_admin: bool, rules: &[(String, String)], action: &str, name: &str) -> bool {
    is_admin
        || rules
            .iter()
            .any(|(a, p)| action_matches(a, action) && path_matches(p, name))
}

pub fn visible(is_admin: bool, rules: &[(String, String)], name: &str) -> bool {
    is_admin || rules.iter().any(|(_, p)| path_matches(p, name))
}

#[cfg(test)]
mod tests {
    use super::*;

    fn rules(v: &[(&str, &str)]) -> Vec<(String, String)> {
        v.iter()
            .map(|(a, p)| (a.to_string(), p.to_string()))
            .collect()
    }

    #[test]
    fn glob_prefix_matches_under_path() {
        assert!(path_matches("stripe/*", "stripe/secret-key"));
        assert!(!path_matches("stripe/*", "db/root"));
    }

    #[test]
    fn exact_pattern_requires_exact_name() {
        assert!(path_matches("db/pw", "db/pw"));
        assert!(!path_matches("db/pw", "db/pw2"));
    }

    #[test]
    fn lone_star_matches_everything() {
        assert!(path_matches("*", "anything/at/all"));
    }

    #[test]
    fn action_wildcard_matches_any_action() {
        assert!(action_matches("*", "create"));
        assert!(action_matches("create", "create"));
        assert!(!action_matches("create", "delete"));
    }

    #[test]
    fn admin_bypasses_all_rules() {
        assert!(authorize(true, &[], "delete", "anything"));
    }

    #[test]
    fn payment_role_scoped_to_stripe() {
        let r = rules(&[("create", "stripe/*"), ("rotate", "stripe/*")]);
        assert!(authorize(false, &r, "create", "stripe/secret-key"));
        assert!(authorize(false, &r, "rotate", "stripe/webhook"));
        assert!(!authorize(false, &r, "delete", "stripe/secret-key"));
        assert!(!authorize(false, &r, "create", "db/root"));
    }

    #[test]
    fn visibility_follows_patterns() {
        let r = rules(&[("create", "stripe/*")]);
        assert!(visible(false, &r, "stripe/a"));
        assert!(!visible(false, &r, "db/a"));
        assert!(visible(true, &[], "db/a"));
    }

    #[test]
    fn action_validation() {
        assert!(is_valid_action("create"));
        assert!(is_valid_action("*"));
        assert!(!is_valid_action("read"));
        assert!(!is_valid_action(""));
    }
}