Skip to main content

cfn_guard/commands/
mod.rs

1use clap::{Parser, Subcommand};
2
3use crate::{
4    commands::{
5        completions::Completions, parse_tree::ParseTree, rulegen::Rulegen, test::Test,
6        validate::Validate,
7    },
8    utils::{reader::Reader, writer::Writer},
9};
10
11pub(crate) mod files;
12pub(crate) mod helper;
13pub mod parse_tree;
14pub mod rulegen;
15pub mod test;
16pub mod validate;
17
18mod aws_meta_appender;
19mod common_test_helpers;
20pub mod completions;
21pub mod reporters;
22mod tracker;
23
24//
25// Constants
26//
27// Application metadata
28pub const APP_NAME: &str = "cfn-guard";
29
30// Arguments for validate
31pub const ALPHABETICAL: (&str, char) = ("alphabetical", 'a');
32#[allow(dead_code)]
33pub const DATA: (&str, char) = ("data", 'd');
34pub const LAST_MODIFIED: (&str, char) = ("last-modified", 'm');
35#[allow(dead_code)]
36pub const OUTPUT_FORMAT: (&str, char) = ("output-format", 'o');
37#[allow(dead_code)]
38pub const INPUT_PARAMETERS: (&str, char) = ("input-parameters", 'i');
39pub const PAYLOAD: (&str, char) = ("payload", 'P');
40pub const PRINT_JSON: (&str, char) = ("print-json", 'p');
41pub const SHOW_SUMMARY: (&str, char) = ("show-summary", 'S');
42pub const TYPE: (&str, char) = ("type", 't');
43pub const VERBOSE: (&str, char) = ("verbose", 'v');
44// Arguments for validate, parse tree
45pub const RULES: (&str, char) = ("rules", 'r');
46// Arguments for parse-tree, rulegen
47#[allow(dead_code)]
48pub const OUTPUT: (&str, char) = ("output", 'o');
49// Arguments for parse-tree
50pub const PRINT_YAML: (&str, char) = ("print-yaml", 'y');
51// Arguments for test
52pub const RULES_FILE: (&str, char) = ("rules-file", 'r');
53pub const TEST_DATA: (&str, char) = ("test-data", 't');
54pub const DIRECTORY: (&str, char) = ("dir", 'd');
55// Arguments for rulegen
56#[allow(dead_code)]
57pub const TEMPLATE: (&str, char) = ("template", 't');
58// Arg group for validate
59pub(crate) const REQUIRED_FLAGS: &str = "required_flags";
60// Arg group for test
61pub const RULES_AND_TEST_FILE: &str = "rules-and-test-file";
62pub const DIRECTORY_ONLY: &str = "directory-only";
63pub const STRUCTURED: (&str, char) = ("structured", 'z');
64
65pub(crate) const DATA_FILE_SUPPORTED_EXTENSIONS: [&str; 5] =
66    [".yaml", ".yml", ".json", ".jsn", ".template"];
67pub(crate) const RULE_FILE_SUPPORTED_EXTENSIONS: [&str; 2] = [".guard", ".ruleset"];
68
69pub const FAILURE_STATUS_CODE: i32 = 19;
70pub const SUCCESS_STATUS_CODE: i32 = 0;
71pub const ERROR_STATUS_CODE: i32 = 5;
72pub const TEST_ERROR_STATUS_CODE: i32 = 1;
73pub const TEST_FAILURE_STATUS_CODE: i32 = 7;
74
75const ABOUT: &str = r#"
76Guard is a general-purpose tool that provides a simple declarative syntax to define
77policy-as-code as rules to validate against any structured hierarchical data (like JSON/YAML).
78Rules are composed of clauses expressed using Conjunctive Normal Form
79(fancy way of saying it is a logical AND of OR clauses). Guard has deep
80integration with CloudFormation templates for evaluation but is a general tool
81that equally works for any JSON- and YAML- data."#;
82
83#[derive(Debug, Parser)]
84#[command(name=APP_NAME)]
85#[command(about=ABOUT)]
86#[command(version)]
87pub struct CfnGuard {
88    #[command(subcommand)]
89    pub(crate) command: Commands,
90}
91
92impl CfnGuard {
93    pub fn execute(&self, writer: &mut Writer, reader: &mut Reader) -> crate::rules::Result<i32> {
94        self.command.execute(writer, reader)
95    }
96}
97
98#[derive(Debug, Subcommand)]
99pub(crate) enum Commands {
100    Validate(Validate),
101    Test(Test),
102    ParseTree(ParseTree),
103    Rulegen(Rulegen),
104    Completions(Completions),
105}
106
107pub trait Executable {
108    fn execute(&self, writer: &mut Writer, reader: &mut Reader) -> crate::rules::Result<i32>;
109}
110
111impl Executable for Commands {
112    fn execute(&self, writer: &mut Writer, reader: &mut Reader) -> crate::rules::Result<i32> {
113        match self {
114            Commands::Validate(cmd) => cmd.execute(writer, reader),
115            Commands::Test(cmd) => cmd.execute(writer, reader),
116            Commands::ParseTree(cmd) => cmd.execute(writer, reader),
117            Commands::Rulegen(cmd) => cmd.execute(writer, reader),
118            Commands::Completions(cmd) => cmd.execute(),
119        }
120    }
121}