Skip to main content

cfn_guard_lambda/
main.rs

1// Copyright Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use cfn_guard::{run_checks, ValidateInput};
5use lambda_runtime::{service_fn, tracing, Error, LambdaEvent};
6use serde_derive::{Deserialize, Serialize};
7
8fn default_as_true() -> bool {
9    true
10}
11
12#[derive(Serialize, Deserialize, Debug)]
13pub struct CustomEvent {
14    #[serde(rename = "data")]
15    pub data: String,
16    #[serde(rename = "rules")]
17    pub rules: Vec<String>,
18    #[serde(rename = "verbose", default = "default_as_true")] // for backward compatibility
19    pub verbose: bool,
20}
21
22#[derive(Serialize)]
23pub struct CustomOutput {
24    pub message: Vec<serde_json::Value>,
25}
26
27#[tokio::main]
28#[allow(dead_code)]
29async fn main() -> Result<(), Error> {
30    tracing_subscriber::fmt()
31        .with_max_level(tracing::Level::INFO)
32        .without_time()
33        .init();
34    lambda_runtime::run(service_fn(call_cfn_guard)).await
35}
36
37pub async fn call_cfn_guard(event: LambdaEvent<CustomEvent>) -> Result<CustomOutput, Error> {
38    let (e, _context) = event.into_parts();
39    tracing::info!("Template is: [{}]", &e.data);
40    tracing::info!("Rules are: [{:?}]", &e.rules);
41    let mut results_vec = Vec::new();
42    for rule in e.rules.iter() {
43        let result = match run_checks(
44            ValidateInput {
45                content: &e.data,
46                file_name: "lambda-payload",
47            },
48            ValidateInput {
49                content: rule,
50                file_name: "lambda-rule",
51            },
52            e.verbose,
53        ) {
54            Ok(t) => t,
55            Err(e) => e.to_string(),
56        };
57        let json_value: serde_json::Value = serde_json::from_str(&result)?;
58        results_vec.push(json_value)
59    }
60    Ok(CustomOutput {
61        message: results_vec,
62    })
63}
64
65impl std::fmt::Display for CustomEvent {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
67        write!(f, "{}", serde_json::to_string_pretty(&self).unwrap())?;
68        Ok(())
69    }
70}
71
72impl std::fmt::Display for CustomOutput {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
74        for message in &self.message {
75            write!(
76                f,
77                "{}",
78                match serde_json::to_string_pretty(message) {
79                    Ok(message) => message,
80                    Err(_) => unreachable!(),
81                }
82            )?;
83        }
84        Ok(())
85    }
86}