-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add lambda wrapper for cfn guard (#12)
* Add lambda wrapper for cfn guard - Add function to valdiate input json data and rules - Add function to return result in json format - Create cfn guard lib - Create directory for cfn-guard-lambda, call cfn guard lib from the lambda wrapper - Add test directory for functional tests
- Loading branch information
Showing
10 changed files
with
261 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
[workspace] | ||
|
||
members = [ | ||
"cfn-guard" | ||
"cfn-guard", | ||
"cfn-guard-lambda" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[package] | ||
name = "cfn-guard-lambda" | ||
version = "1.0.0" | ||
authors = ["Omkar Hegde <[email protected]>", "aws-cloudformation-developers <[email protected]>"] | ||
description = "Lambda version of cfn-guard. Checks AWS CloudFormation templates for policy compliance using a simple, policy-as-code, declarative syntax" | ||
license = "Apache-2.0" | ||
edition = "2018" | ||
|
||
[dependencies] | ||
lambda_runtime = "0.2.1" | ||
serde = "1.0.92" | ||
serde_derive = "1.0.92" | ||
simple-error = "0.2.0" | ||
simple_logger = "1.3.0" | ||
log = "0.4.6" | ||
cfn-guard = { version = "0.10.0", path = "../cfn-guard" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use std::error::Error; | ||
|
||
use cfn_guard; | ||
use lambda_runtime::{error::HandlerError, lambda, Context}; | ||
use log::{self, info}; | ||
use serde_derive::{Deserialize, Serialize}; | ||
use simple_logger; | ||
|
||
#[derive(Deserialize, Debug)] | ||
struct CustomEvent { | ||
#[serde(rename = "data")] | ||
data: String, | ||
#[serde(rename = "rules")] | ||
rules: String, | ||
} | ||
|
||
#[derive(Serialize)] | ||
struct CustomOutput { | ||
message: String, | ||
} | ||
|
||
fn main() -> Result<(), Box<dyn Error>> { | ||
simple_logger::init_with_level(log::Level::Info)?; | ||
lambda!(call_cfn_guard); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn call_cfn_guard(e: CustomEvent, _c: Context) -> Result<CustomOutput, HandlerError> { | ||
info!("Template is [{}]", &e.data); | ||
info!("Rule Set is [{}]", &e.rules); | ||
let (result) = match cfn_guard::run_checks(&e.data, &e.rules) | ||
{ | ||
Ok(t) => t, | ||
Err(e) => (e.to_string()), | ||
}; | ||
|
||
Ok(CustomOutput { | ||
message: result, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,9 @@ authors = ["diwakar <[email protected]>"] | |
edition = "2018" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
[lib] | ||
name = "cfn_guard" | ||
path = "src/lib.rs" | ||
|
||
[dependencies] | ||
nom = "5.1.2" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use crate::rules::errors::{Error, ErrorKind}; | ||
use crate::rules::evaluate::RootScope; | ||
use crate::rules::path_value::PathAwareValue; | ||
use crate::commands::tracker::StackTracker; | ||
use crate::commands::validate::ConsoleReporter; | ||
use crate::rules::{Evaluate, Result}; | ||
use std::convert::TryFrom; | ||
|
||
pub fn validate_and_return_json( | ||
data: &str, | ||
rules: &str, | ||
) -> Result<String> { | ||
let mut input_data = match serde_json::from_str::<serde_json::Value>(&data) { | ||
Ok(value) => PathAwareValue::try_from(value), | ||
Err(e) => return Err(Error::new(ErrorKind::ParseError(e.to_string()))), | ||
}; | ||
|
||
let span = crate::rules::parser::Span::new_extra(&rules, "lambda"); | ||
|
||
match crate::rules::parser::rules_file(span) { | ||
|
||
Ok(rules) => { | ||
match input_data { | ||
Ok(root) => { | ||
let root_context = RootScope::new(&rules, &root); | ||
let stacker = StackTracker::new(&root_context); | ||
let reporter = ConsoleReporter::new(stacker, true, true); | ||
rules.evaluate(&root, &reporter)?; | ||
let json_result = reporter.get_result_json(); | ||
return Ok((json_result)); | ||
} | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
Err(e) => return Err(Error::new(ErrorKind::ParseError(e.to_string()))), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
mod rules; | ||
mod commands; | ||
mod command; | ||
|
||
pub extern "C" fn run_checks( | ||
data: &str, | ||
rules: &str, | ||
) -> crate::rules::Result<String> { | ||
return crate::commands::helper::validate_and_return_json(&data, &rules); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use cfn_guard; | ||
|
||
mod tests { | ||
use super::*; | ||
#[test] | ||
fn test_run_check() { | ||
let mut data = String::from( | ||
r#" | ||
{ | ||
"Resources": { | ||
"VPC" : { | ||
"Type" : "AWS::ApiGateway::Method", | ||
"Properties" : { | ||
"AuthorizationType" : "10.0.0.0/24" | ||
} | ||
} | ||
} | ||
} | ||
"#, | ||
); | ||
let rule = "AWS::ApiGateway::Method { Properties.AuthorizationType == \"NONE\"}"; | ||
let mut expected = String::from( | ||
r#" | ||
[ | ||
{ | ||
"eval_type": "Rule", | ||
"context": "default", | ||
"from": null, | ||
"to": null, | ||
"status": "FAIL", | ||
"children": [ | ||
{ | ||
"eval_type": "Type", | ||
"context": "AWS::ApiGateway::Method", | ||
"from": null, | ||
"to": null, | ||
"status": "FAIL", | ||
"children": [ | ||
{ | ||
"eval_type": "Filter", | ||
"context": "Path=/Resources/VPC,Type=MapElement", | ||
"from": null, | ||
"to": null, | ||
"status": "PASS", | ||
"children": [ | ||
{ | ||
"eval_type": "Clause", | ||
"context": "GuardAccessClause[ check = Type EQUALS String(\"AWS::ApiGateway::Method\"), loc = Location[file=#1@14] ]", | ||
"from": null, | ||
"to": null, | ||
"status": "PASS", | ||
"children": [] | ||
} | ||
] | ||
}, | ||
{ | ||
"eval_type": "Type", | ||
"context": "AWS::ApiGateway::Method#0(/Resources/VPC)", | ||
"from": null, | ||
"to": null, | ||
"status": "FAIL", | ||
"children": [ | ||
{ | ||
"eval_type": "Clause", | ||
"context": "GuardAccessClause[ check = Properties.AuthorizationType EQUALS String(\"NONE\"), loc = Location[file=lambda#1@27] ]", | ||
"from": { | ||
"String": [ | ||
"/Resources/VPC/Properties/AuthorizationType", | ||
"10.0.0.0/24" | ||
] | ||
}, | ||
"to": { | ||
"String": [ | ||
"lambda/1/27/Clause/", | ||
"NONE" | ||
] | ||
}, | ||
"status": "FAIL", | ||
"children": [] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
] | ||
"#, | ||
); | ||
|
||
// Remove white spaces from expected and calculated result for easy comparison. | ||
expected.retain(|c| !c.is_whitespace()); | ||
|
||
let mut serialized = cfn_guard::run_checks(&data, &rule).unwrap(); | ||
serialized.retain(|c| !c.is_whitespace()); | ||
|
||
assert_eq!(expected, serialized); | ||
} | ||
|
||
} |