Skip to content

Commit

Permalink
Merge pull request #28 from aws-cloudformation/release-0.5.1
Browse files Browse the repository at this point in the history
Release 0.5.1
  • Loading branch information
nathanataws authored Jun 25, 2020
2 parents 5cb0ac3 + 471bfa4 commit 225abe4
Show file tree
Hide file tree
Showing 37 changed files with 676 additions and 353 deletions.
35 changes: 35 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve CloudFormation Guard
title: "[BUG]"
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Please supply:

1. An example rule set and template that results in the error
1. The commands you used to invoke the tool
1. The output of a `-vvv` log level if it's not related to cfn-guard-lambda, or the relevant CloudWatch log messages if it is related to the lambda

**NOTE: Please be sure that the templates, rule sets and logs you provide as part of your bug report do not contain any sensitive information.**

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Operating System:**
[eg, MacOS, Windows, Ubuntu, etc]

**OS Version**
[eg Catalina, 10, 18.04, etc]

**Additional context**
Add any other context about the problem here.
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[Enhancement]"
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
language: rust

script:
- cd cfn-guard && cargo build --verbose --all && cargo test --verbose --all
script:
- cd cfn-guard-lambda && cargo build --verbose --all && cargo test --verbose --all
script:
- cd cfn-guard-rulegen && cargo build --verbose --all && cargo test --verbose --all
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ cfn-guard-lambda_update:
clean:
if test -f cloudformation-guard.tar.gz; then rm cloudformation-guard.tar.gz; fi

test:
cd cfn-guard; cargo test
cd cfn-guard-rulegen; cargo test
cd cfn-guard-lambda; make test

release_with_binaries: clean cfn-guard cfn-guard-rulegen
tar czvf cloudformation-guard.tar.gz -X Exclude.txt .

Expand Down
5 changes: 3 additions & 2 deletions cfn-guard-lambda/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cfn-guard-lambda/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cfn-guard-lambda"
version = "0.5.0"
version = "0.5.1"
edition = "2018"

[dependencies]
Expand Down
30 changes: 15 additions & 15 deletions cfn-guard-lambda/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,9 @@ endif

test: build
aws lambda update-function-code --function-name $(project_name) --zip-file fileb://./lambda.zip
aws lambda invoke --function-name $(project_name) --payload $(request_payload_fail) output.json
cat output.json | jq '.'
aws lambda invoke --function-name $(project_name) --payload $(request_payload_pass) output.json
cat output.json | jq '.'
aws lambda invoke --function-name $(project_name) --payload $(request_payload_err) output.json
cat output.json | jq '.'
$(MAKE) fail
$(MAKE) pass
$(MAKE) err

clean:
@sh -c "if test -f bootstrap; then rm bootstrap; fi"
Expand Down Expand Up @@ -159,22 +156,25 @@ build: clean
chmod +x bootstrap
zip lambda.zip bootstrap

install: build
aws lambda create-function --function-name $(project_name) --handler doesnt.matter --zip-file fileb://./lambda.zip --runtime provided --role $(role_arn) --environment Variables={RUST_BACKTRACE=1}
fail:
aws lambda invoke --function-name $(project_name) --payload $(request_payload_fail) output.json
cat output.json | jq '.'
aws lambda invoke --function-name $(project_name) --payload $(request_payload_pass) output.json
cat output.json | jq '.'
aws lambda invoke --function-name $(project_name) --payload $(request_payload_err) output.json
cat output.json | jq '.'

invoke:
aws lambda invoke --function-name $(project_name) --payload $(request_payload_fail) output.json
cat output.json | jq '.'
pass:
aws lambda invoke --function-name $(project_name) --payload $(request_payload_pass) output.json
cat output.json | jq '.'

err:
aws lambda invoke --function-name $(project_name) --payload $(request_payload_err) output.json
cat output.json | jq '.'

install: build
aws lambda create-function --function-name $(project_name) --handler doesnt.matter --zip-file fileb://./lambda.zip --runtime provided --role $(role_arn) --environment Variables={RUST_BACKTRACE=1}
$(MAKE) fail
$(MAKE) pass
$(MAKE) err

invoke: fail pass err

uninstall:
aws lambda delete-function --function-name $(project_name)
78 changes: 69 additions & 9 deletions cfn-guard-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,28 @@ The Lambda version of the tool is a lightweight wrapper around the core [cfn-gua

The primary interface for building and deploying the tool is the [Makefile](Makefile). Examples for the payload it expects can be found there.

## Dependencies
## Table of Contents
* [Installation](#installation)
* [Build and run post-install](#to-build-and-run-post-install)
* [Calling the Lambda Function](#calling-the-lambda-function)
* [FAQ](#faq)

## Installation
### Dependencies
* AWS CLI [configured](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) with permissions to deploy and invoke Lambdas
* An [AWS Lambda Execution Role](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html) in IAM
* A shell environment variable called `CFN_GUARD_LAMBDA_ROLE_ARN` set to the ARN of that role
* [Rust](https://rustup.rs/) (See the installation instructions in the [top-level README](../README.md#install-rust))
* If building on a Mac, you'll need [Homebrew](https://brew.sh/).
* If building on Ubuntu, you'll need to run `sudo apt-get update; sudo apt install build-essential` if you haven't already

## To install CloudFormation Guard Lambda the first time

If you're on a Mac, add the following to `~/.cargo/config`:

```
[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"
```
### Mac/Ubuntu
1. Install and configure the [dependencies](#dependencies).
1. If you're on a Mac, add the following to `~/.cargo/config`:
```
[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"
```
1. Ensure you're in the `cfn-guard-lambda` directory
1. Run `make pre-reqs`.
1. Run `make install`.
Expand Down Expand Up @@ -113,6 +119,60 @@ cat output.json | jq '.'
"exit_status": "ERR"
}
```
## Calling the Lambda Function
### Request Structure
Requests to `cfn-guard-lambda` require the following 3 fields:
* `template` - The string version of the YAML or JSON CloudFormation Template
* `ruleSet` - The string version of the rule set file
* `strict_checks` - A boolean indicating whether to apply [strict checks](../cfn-guard/README.md#about)
#### Example
There are example payloads in the [Makefile](Makefile). Here's one we use to test a rule set that should not pass:
```
request_payload_fail = '{ "template": "{\n \"Resources\": {\n \"NewVolume\" : {\n \"Type\" : \"AWS::EC2::Volume\",\n \"Properties\" : {\n \"Size\" : 100,\n \"Encrypted\": true,\n \"AvailabilityZone\" : \"us-east-1b\"\n }\n },\n \"NewVolume2\" : {\n \"Type\" : \"AWS::EC2::Volume\",\n \"Properties\" : {\n \"Size\" : 99,\n \"Encrypted\": true,\n \"AvailabilityZone\" : \"us-east-1b\"\n }\n } }\n}",\
"ruleSet": "let require_encryption = true\nlet disallowed_azs = [us-east-1a,us-east-1b,us-east-1c]\n\nAWS::EC2::Volume AvailabilityZone NOT_IN %disallowed_azs\nAWS::EC2::Volume Encrypted != %require_encryption\nAWS::EC2::Volume Size == 101 |OR| AWS::EC2::Volume Size == 99\nAWS::IAM::Role AssumeRolePolicyDocument.Version == 2012-10-18\nAWS::EC2::Volume Lorem == true\nAWS::EC2::Volume Encrypted == %ipsum\nAWS::EC2::Volume AvailabilityZone != /us-east-.*/",\
"strict_checks": true}'

#======================================================================
# Request Payload Fail:
#======================================================================
# Template
#{"Resources": {
# "NewVolume" : {
# "Type" : "AWS::EC2::Volume",
# "Properties" : {
# "Size" : 100,
# "Encrypted": true,
# "AvailabilityZone" : "us-east-1b"
# }
# },
# "NewVolume2" : {
# "Type" : "AWS::EC2::Volume",
# "Properties" : {
# "Size" : 99,
# "Encrypted": true,
# "AvailabilityZone" : "us-east-1b"
# }
# }
#}

# Rule Set
# let require_encryption = true
# let disallowed_azs = [us-east-1a,us-east-1b,us-east-1c]

# AWS::EC2::Volume AvailabilityZone NOT_IN %disallowed_azs
# AWS::EC2::Volume Encrypted != %require_encryption
# AWS::EC2::Volume Size == 101 |OR| AWS::EC2::Volume Size == 99
# AWS::IAM::Role AssumeRolePolicyDocument.Version == 2012-10-18
# AWS::EC2::Volume Lorem == true
# AWS::EC2::Volume Encrypted == %ipsum
# AWS::EC2::Volume AvailabilityZone != /us-east-.*/

# Strict Checks
# true
#======================================================================
```
## FAQ
Expand Down
12 changes: 6 additions & 6 deletions cfn-guard-lambda/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// © 2020 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This AWS Content is provided subject to the terms of the AWS Customer Agreement available at http://aws.amazon.com/agreement or other written agreement between Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL or both.
// © Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This AWS Content is provided subject to the terms of the AWS Customer Agreement available at http://aws.amazon.com/agreement or other written agreement between Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL or both.

use std::error::Error;

use cfn_guard;
use lambda_runtime::{error::HandlerError, lambda, Context};
use log::{self, debug};
use log::{self, info};
use serde_derive::{Deserialize, Serialize};
use simple_logger;

Expand All @@ -14,7 +14,7 @@ struct CustomEvent {
template: String,
#[serde(rename = "ruleSet")]
rule_set: String,
strict_checks: bool
strict_checks: bool,
}

#[derive(Serialize)]
Expand All @@ -24,16 +24,16 @@ struct CustomOutput {
}

fn main() -> Result<(), Box<dyn Error>> {
simple_logger::init_with_level(log::Level::Debug)?;
simple_logger::init_with_level(log::Level::Info)?;
lambda!(my_handler);

Ok(())
}

fn my_handler(e: CustomEvent, _c: Context) -> Result<CustomOutput, HandlerError> {
//dbg!(&e);
debug!("Template is [{}]", &e.template);
debug!("Rule Set is [{}]", &e.rule_set);
info!("Template is [{}]", &e.template);
info!("Rule Set is [{}]", &e.rule_set);
let (result, exit_code) = cfn_guard::run_check(&e.template, &e.rule_set, e.strict_checks);

let exit_status = match exit_code {
Expand Down
2 changes: 1 addition & 1 deletion cfn-guard-rulegen/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cfn-guard-rulegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cfn-guard-rulegen"
version = "0.5.0"
version = "0.5.1"
edition = "2018"

[dependencies]
Expand Down
42 changes: 21 additions & 21 deletions cfn-guard-rulegen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

A CLI tool to automatically generate [CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) rules from CloudFormation Templates.

### Runtime Arguments

Rulegen uses the Rust Clap library to parse arguments. Its `--help` output will show you what options are available:

```
$> cfn-guard-rulegen --help
CloudFormation Guard RuleGen
Generate CloudFormation Guard rules from a CloudFormation template
USAGE:
cfn-guard-rulegen [FLAGS] <TEMPLATE>
FLAGS:
-h, --help Prints help information
-v Sets the level of verbosity - add v's to increase output
-V, --version Prints version information
ARGS:
<TEMPLATE>
```
# Example

If you supply the `cfn-guard-rulegen` tool with a CloudFormation template:
Expand Down Expand Up @@ -126,27 +147,6 @@ will compile the release binary and drop it in the `bin/` directory under the di
1. Run `cargo build --release`.
2. Run the binary with `target\release\cfn-guard-rulegen.exe`

### Runtime Arguments

Rulegen uses the Rust Clap library to parse arguments. Its `--help` output will show you what options are available:

```
$> cfn-guard-rulegen --help
CloudFormation Guard RuleGen 0.5.0
Generate CloudFormation Guard rules from a CloudFormation template
USAGE:
cfn-guard-rulegen [FLAGS] <TEMPLATE>
FLAGS:
-h, --help Prints help information
-v Sets the level of verbosity - add v's to increase output
-V, --version Prints version information
ARGS:
<TEMPLATE>
```

### Logging

Expand Down
8 changes: 6 additions & 2 deletions cfn-guard-rulegen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// © 2020 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This AWS Content is provided subject to the terms of the AWS Customer Agreement available at http://aws.amazon.com/agreement or other written agreement between Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL or both.
// © Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This AWS Content is provided subject to the terms of the AWS Customer Agreement available at http://aws.amazon.com/agreement or other written agreement between Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL or both.

use log::{self, debug, info, trace};
use serde_json::Value;
Expand Down Expand Up @@ -44,7 +44,10 @@ fn gen_rules(cfn_resources: HashMap<String, Value>) -> Vec<String> {
for (name, cfn_resource) in cfn_resources {
trace!("{} is {:?}", name, &cfn_resource);
let props: HashMap<String, Value> =
serde_json::from_value(cfn_resource["Properties"].clone()).unwrap();
match serde_json::from_value(cfn_resource["Properties"].clone()) {
Ok(s) => s,
Err(_) => continue
};
for (prop_name, prop_val) in props {
let stripped_val = match prop_val.as_str() {
Some(v) => String::from(v),
Expand Down Expand Up @@ -79,3 +82,4 @@ fn gen_rules(cfn_resources: HashMap<String, Value>) -> Vec<String> {
}
rule_set.into_iter().collect()
}

Loading

0 comments on commit 225abe4

Please sign in to comment.