cfn_guard/commands/
mod.rs1use 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
24pub const APP_NAME: &str = "cfn-guard";
29
30pub 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');
44pub const RULES: (&str, char) = ("rules", 'r');
46#[allow(dead_code)]
48pub const OUTPUT: (&str, char) = ("output", 'o');
49pub const PRINT_YAML: (&str, char) = ("print-yaml", 'y');
51pub 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#[allow(dead_code)]
57pub const TEMPLATE: (&str, char) = ("template", 't');
58pub(crate) const REQUIRED_FLAGS: &str = "required_flags";
60pub 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}