Skip to main content

cfn_guard/commands/
helper.rs

1// Copyright Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use enumflags2::BitFlags;
5
6use crate::commands::reporters::validate::generic_summary::GenericSummary;
7use crate::commands::validate::{DataFile, OutputFormatType, Reporter};
8use crate::rules::errors::Error;
9use crate::rules::eval::eval_rules_file;
10use crate::rules::eval_context::root_scope;
11use crate::rules::path_value::traversal::Traversal;
12use crate::rules::path_value::PathAwareValue;
13use crate::rules::Result;
14use std::convert::TryFrom;
15use std::io::BufWriter;
16use std::rc::Rc;
17
18#[allow(dead_code)]
19pub struct ValidateInput<'a> {
20    pub content: &'a str,
21    pub file_name: &'a str,
22}
23
24#[allow(dead_code)]
25pub fn validate_and_return_json(
26    data: ValidateInput,
27    rules: ValidateInput,
28    verbose: bool,
29) -> Result<String> {
30    let path_value = match serde_json::from_str::<serde_json::Value>(data.content) {
31        Ok(value) => PathAwareValue::try_from(value),
32        Err(_) => {
33            let value = serde_yaml::from_str::<serde_yaml::Value>(data.content)?;
34            PathAwareValue::try_from(value)
35        }
36    }
37    .map_err(|e| {
38        Error::ParseError(format!(
39            "Unable to process data in file {}, Error {e},",
40            data.file_name,
41        ))
42    })?;
43
44    let input_data = DataFile {
45        content: "".to_string(), // not used later
46        path_value,
47        name: data.file_name.to_owned(),
48    };
49
50    let span = crate::rules::parser::Span::new_extra(rules.content, rules.file_name);
51
52    let rules_file_name = rules.file_name;
53    return match crate::rules::parser::rules_file(span) {
54        Ok(Some(rules)) => {
55            let mut write_output = BufWriter::new(Vec::new());
56            let root = input_data.path_value;
57            let traversal = Traversal::from(&root);
58            let mut root_scope = root_scope(&rules, Rc::new(root.clone()));
59            let status = eval_rules_file(&rules, &mut root_scope, Some(&input_data.name))?;
60            let root_record = root_scope.reset_recorder().extract();
61
62            if verbose {
63                return Ok(serde_json::to_string_pretty(&root_record)?);
64            }
65
66            let reporter = &GenericSummary::new(BitFlags::empty()) as &dyn Reporter;
67
68            reporter.report_eval(
69                &mut write_output,
70                status,
71                &root_record,
72                rules_file_name,
73                data.file_name,
74                data.content,
75                &traversal,
76                OutputFormatType::JSON,
77            )?;
78
79            match String::from_utf8(write_output.buffer().to_vec()) {
80                Ok(val) => Ok(val),
81                Err(e) => Err(Error::ParseError(e.to_string())),
82            }
83        }
84        Ok(None) => Ok(String::default()),
85        Err(e) => Err(Error::ParseError(e.to_string())),
86    };
87}