AWS CloudFormation Guard as a Lambda
The Lambda version of the tool is a lightweight wrapper around the core cfn-guard code that can simply be invoked as a Lambda. We currently support 2 methods for deploying the Lambda.
Table of Contents
- Method 1: Installation using AWS CLI
- Method 2: Installation using SAM CLI
- Calling the AWS Lambda Function
- FAQs
Method 1: Installation using AWS CLI
Dependencies
- AWS CLI configured with permissions to deploy and invoke Lambdas
- Rust (See the installation instructions in the top-level README)
- If building on a Mac, you'll need Homebrew.
- If building on Ubuntu, you'll need to run
sudo apt-get update; sudo apt install build-essentialif you haven't already - If building on CentOS/RHEL you'll need to add the
musl-libcpackage repository to your yum config (see https://copr.fedorainfracloud.org/coprs/ngompa/musl-libc/)
Mac/Ubuntu
- Install and configure the dependencies.
- Run
rustup target add x86_64-unknown-linux-musl. - If you're on a Mac, add the following to
~/.cargo/config:[target.x86_64-unknown-linux-musl] linker = "x86_64-linux-musl-gcc" - Ensure you're in the
guard-lambdadirectory. - Run
cargo build --release --target x86_64-unknown-linux-musl. For a custom runtime, AWS Lambda looks for an executable calledbootstrapin the deployment package zip. Rename the generatedcfn-lambdaexecutable tobootstrapand add it to a zip archive. - Run
cp ./../target/x86_64-unknown-linux-musl/release/cfn-guard-lambda ./bootstrap && zip lambda.zip bootstrap && rm bootstrap. - Initialize the following shell variables with values corresponding to your account:
LAMBDA_FUNCTION_NAME=CloudFormationGuardLambda AWS_ACCOUNT_ID=111111111111 REGION=us-east-1 ROLE_NAME="Role" - Create an execution role for Lambda function. Refer the linked documentation for updated instructions. Alternatively, use the following command:
- Run the following command to submit
cfn-guardas an AWS Lambda function to your account:
Method 2: Installation using SAM CLI
Dependencies
-
SAM CLI installed
-
AWS CLI installed and configured with permissions to deploy via CloudFormation. SAM CLI will internally use the credentials you setup AWS CLI with. You may use the following IAM policy as a reference for least privileged access.
-
Docker installed
Building and deploying
- Make sure docker is running
- Navigate to
guard-lambdadirectory and runsam build --use-containerto build the code for the Lambda function - Run
sam deploy --guidedand complete the interactive workflow. This workflow will create a CloudFormation changeset and deploy it - Once it succeeds, the name of the function will be shown in the
CloudFormationGuardLambdaFunctionNameoutput - For subsequent updates, build the code again (step 2) and run
sam deploy(without--guided)
Calling the AWS Lambda Function
Payload Structure
The payload JSON to cfn-guard-lambda requires the following two fields:
data- (Mandatory, string) Infrastructure as code template data in YAML or JSON structure.rules- (Mandatory, list of strings) List of rules that you want to run your YAML or JSON structured data against.verbose- (Optional, boolean) A flag when set tofalsemakes Lambda emit a shorter version of the output. This is set totrueby default for backward compatibility.
Invoking cfn-guard-lambda
Initialize the variable LAMBDA_FUNCTION_NAME to the name of the deployed AWS Lambda Function, and invoke it using the following syntax:
Note: --cli-binary-format option is only required to override the default configuration setting to perform the parsing of
JSON input. If the command doesn't work with this option, try running it without this configuration override. Your current
AWS CLI version may have this configuration set to the required value.
Example
aws lambda invoke \
--function-name $LAMBDA_FUNCTION_NAME \
--cli-binary-format raw-in-base64-out \
--payload '{"data":"{\"Resources\":{\"NewVolume\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":500,\"Encrypted\":true,\"AvailabilityZone\":\"us-west-2b\"}},\"NewVolume2\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":50,\"Encrypted\":true,\"AvailabilityZone\":\"us-west-2c\"}}}}","rules":["let ec2_volumes = Resources.*[ Type == /EC2::Volume/ ]\nrule EC2_ENCRYPTION_BY_DEFAULT when %ec2_volumes !empty {\n %ec2_volumes.Properties.Encrypted == true \n <<\n Violation: All EBS Volumes should be encrypted \n Fix: Set Encrypted property to true\n >>\n}"],"verbose":false}' \
output.json
Note: --cli-binary-format option is only required to override the default configuration setting to perform the parsing of
JSON input. If the command doesn't work with this option, try running it without this configuration override. Your current
AWS CLI version may have this configuration set to the required value.
FAQs
Q: How do I troubleshoot a lambda call returning an opaque error message like:
}
A: Run the same rule set and template locally with cfn-guard to get a better message, such as:
cfn-guard-lambda is just a wrapper for the cfn-guard code and each can be used to test the other.