kingfisher/tests/tls_mode.rs
2026-02-03 09:37:53 -08:00

200 lines
7.3 KiB
Rust

//! Tests for the `--tls-mode` CLI feature and TLS validation behavior.
//!
//! These tests verify that:
//! - The `--tls-mode` CLI flag is parsed correctly
//! - The `--ignore-certs` legacy flag is treated as `--tls-mode=off`
//! - Rules with `tls_mode: lax` are correctly parsed and respected
//! - The TLS mode behavior works as expected for different validators
use assert_cmd::Command;
use predicates::prelude::*;
/// Test that `--tls-mode` is recognized as a valid global option.
#[test]
fn tls_mode_flag_is_recognized() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--tls-mode=strict").arg("--help");
cmd.assert().success();
}
/// Test that all TLS mode values are accepted.
#[test]
fn tls_mode_accepts_all_values() {
for mode in ["strict", "lax", "off"] {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg(format!("--tls-mode={}", mode)).arg("--help");
cmd.assert().success();
}
}
/// Test that invalid TLS mode values are rejected.
#[test]
fn tls_mode_rejects_invalid_values() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--tls-mode=invalid").arg("--help");
cmd.assert().failure().stderr(predicate::str::contains("invalid"));
}
/// Test that `--ignore-certs` is still accepted (deprecated but supported).
#[test]
fn ignore_certs_flag_still_works() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--ignore-certs").arg("--help");
cmd.assert().success();
}
/// Test that --tls-mode appears in the help output.
#[test]
fn tls_mode_appears_in_help() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--help");
cmd.assert().success().stdout(predicate::str::contains("--tls-mode"));
}
/// Test that rules list subcommand runs with tls-mode flag.
#[test]
fn rules_list_works_with_tls_mode() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--tls-mode=lax").arg("rules").arg("list");
cmd.assert()
.success()
.stdout(predicate::str::contains("postgres").or(predicate::str::contains("Postgres")));
}
/// Test that a scan with `--tls-mode=strict` runs successfully.
#[test]
fn scan_with_strict_mode_runs() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--tls-mode=strict").arg("scan").arg("--no-validate").arg("-");
cmd.write_stdin("test input with no secrets");
cmd.assert().success();
}
/// Test that a scan with `--tls-mode=lax` runs successfully.
#[test]
fn scan_with_lax_mode_runs() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--tls-mode=lax").arg("scan").arg("--no-validate").arg("-");
cmd.write_stdin("test input with no secrets");
cmd.assert().success();
}
/// Test that a scan with `--tls-mode=off` runs successfully.
#[test]
fn scan_with_off_mode_runs() {
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"));
cmd.arg("--tls-mode=off").arg("scan").arg("--no-validate").arg("-");
cmd.write_stdin("test input with no secrets");
cmd.assert().success();
}
#[cfg(test)]
mod rule_tls_mode_tests {
use kingfisher_rules::{RuleSyntax, TlsMode};
use serde::Deserialize;
/// Helper struct for deserializing rule YAML files.
#[derive(Deserialize)]
struct RawRules {
rules: Vec<RuleSyntax>,
}
/// Test that the postgres rule has tls_mode: lax.
#[test]
fn postgres_rule_has_lax_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/postgres.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("postgres rules should parse");
let postgres_rule = raw.rules.iter().find(|r| r.id == "kingfisher.postgres.1");
assert!(postgres_rule.is_some(), "postgres rule should exist");
assert_eq!(
postgres_rule.unwrap().tls_mode,
Some(TlsMode::Lax),
"postgres rule should have tls_mode: lax"
);
}
/// Test that the mysql rule has tls_mode: lax.
#[test]
fn mysql_rule_has_lax_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/mysql.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("mysql rules should parse");
let mysql_rule = raw.rules.iter().find(|r| r.id == "kingfisher.mysql.1");
assert!(mysql_rule.is_some(), "mysql rule should exist");
assert_eq!(
mysql_rule.unwrap().tls_mode,
Some(TlsMode::Lax),
"mysql rule should have tls_mode: lax"
);
}
/// Test that the mongodb URI rule has tls_mode: lax.
#[test]
fn mongodb_uri_rule_has_lax_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/mongodb.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("mongodb rules should parse");
let mongodb_rule = raw.rules.iter().find(|r| r.id == "kingfisher.mongodb.3");
assert!(mongodb_rule.is_some(), "mongodb.3 rule should exist");
assert_eq!(
mongodb_rule.unwrap().tls_mode,
Some(TlsMode::Lax),
"mongodb.3 rule should have tls_mode: lax"
);
}
/// Test that the jdbc rule has tls_mode: lax.
#[test]
fn jdbc_rule_has_lax_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/jdbc.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("jdbc rules should parse");
let jdbc_rule = raw.rules.iter().find(|r| r.id == "kingfisher.jdbc.1");
assert!(jdbc_rule.is_some(), "jdbc rule should exist");
assert_eq!(
jdbc_rule.unwrap().tls_mode,
Some(TlsMode::Lax),
"jdbc rule should have tls_mode: lax"
);
}
/// Test that the jwt rule has tls_mode: lax.
#[test]
fn jwt_rule_has_lax_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/jwt.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("jwt rules should parse");
let jwt_rule = raw.rules.iter().find(|r| r.id == "kingfisher.jwt.1");
assert!(jwt_rule.is_some(), "jwt rule should exist");
assert_eq!(
jwt_rule.unwrap().tls_mode,
Some(TlsMode::Lax),
"jwt rule should have tls_mode: lax"
);
}
/// Test that rules without tls_mode (e.g., SaaS APIs) have None.
#[test]
fn github_rule_has_no_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/github.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("github rules should parse");
// GitHub rules should not have tls_mode set (SaaS API, always strict)
for rule in &raw.rules {
assert_eq!(rule.tls_mode, None, "github rule {} should not have tls_mode set", rule.id);
}
}
/// Test that rules without tls_mode (e.g., SaaS APIs) have None.
#[test]
fn aws_rule_has_no_tls_mode() {
let yaml = include_str!("../crates/kingfisher-rules/data/rules/aws.yml");
let raw: RawRules = serde_yaml::from_str(yaml).expect("aws rules should parse");
// AWS rules should not have tls_mode set (SaaS API, always strict)
for rule in &raw.rules {
assert_eq!(rule.tls_mode, None, "aws rule {} should not have tls_mode set", rule.id);
}
}
}