Skip to content

techservicesillinois/pie-cweventformat-lambda

Repository files navigation

CloudWatch Event Format

This AWS Lambda function takes CloudWatch Events and tries to format them using custom templates before publishing them to an SNS Topic. This will produce an email that is much easier to read than the default, and also deliver to other endpoints the same as before.

  • License: University of Illinois/NCSA Open Source License
  • Organization: University of Illinois at Urbana-Champaign, Technology Services
  • Author: Stephen J. Butler

Terraform Deployment

You can choose to build and deploy this app with terraform.

Building

This is a NodeJS 20.x project that builds using a Makefile. Building should be as simple as running these commands from the project directory:

make dist

This produces a file in the dist directory called cweventFormat.zip.

Resources

The terraform module will create and manage these resources for you:

  • SNS Topic: if you do not pass in the ARN of an SNS Topic then one will be created for you.
  • Lambda Role and Policies: IAM role and policies used by the Lambda function to publish to the SNS Topic and write CloudWatch Logs. No other permissions are needed at this time.
  • Lambda Function: part that does all the work to format events for publishing, deployed from the deploy_localzip path or deploy_s3zip.
  • CloudWatch Log Group: for logs generated by the Lambda function.
  • CloudWatch Metric Alarm: alarm that alerts on errors in the Lambda function. This publishes to the SNS Topic.

Variables: General

These variables are used by the project and are common to many of the components it manages.

Name Default Description
environment Deployment environment (dev, test, prod, devtest, qa).

Variables: Settings

These variables configure specific parameters for the Lambda's operation. This is most likely what you want to customize.

Name Default Description
event_rule_patterns {} CloudWatch Event Rules patterns in a map of NAME = PATTERN. You do not need to specify patterns here, and can instead do them in your own terraform code. If you do, you will need a aws_cloudwatch_event_rule, aws_cloudwatch_event_target, and aws_lambda_permission resources for each pattern.
notifications_topic_arn null SNS Topic to send formatted notifications to. If you do not specify a value here then an SNS Topic is created for you.

Variables: Lambda

These variables are used to configure the Lambda Function.

Name Default Description
name "cweventFormat" Base name (without the project) to use for the lambda function name. The project and revision will be added as a prefix to this.
description "Format CloudWatch Events for email delivery." Description of the function.
deploy_localzip null Path to the zip file to deploy.
deploy_s3zip null S3 bucket and prefix to the cweventFormat/environment.zip file to deploy.
timezone "UTC" Timezone name to set when running the lambda function ("America/Chicago", "UTC", etc).

Variables: Logs

These variables control where the Lambda Function logs are sent. You will always have a copy of the logs in CloudWatch Logs, but you can also have a copy sent to another Lambda Function or a Log Destination (for cross-account logging).

Name Default Description
log_encryption_arn null KMS Key ARN to encrypt to this log group.
log_subscription_arn null Lambda function ARN to subscribe to this log group.

Outputs

These outputs are useful for other parts of your terraform.

  • lambda
  • notifications_topic_arn

Example

Take a look at the terraform/1.0-aws4/example directory for how to use this module.

CloudFormation Deployment

You can choose to build and deploy this app with AWS SAM and CloudFormation. After building you will deploy the packaged-template.yaml and one or more template-event.yaml stacks.

Building

This is a NodeJS 20.x project that builds with AW SAM. Building should be as simple as running these commands from the project directory:

sam build
sam package \
  --s3-bucket your-sam-package-bucket \
  --s3-prefix cweventFormat \
  --output-template-file packaged-template.yaml

This will build the project and upload the code zip files into an S3 package bucket (--s3-bucket your-sam-package-bucket) that you specify. You can also change the --s3-prefix if you want to place the files somewhere else in the bucket. The ouput is a packaged-template.yaml file that you can use to create a CloudFormation stack.

Since you might need the packaged-template.yaml and template-event.yaml files you might want to include commands like these in your build script:

aws s3 cp packaged-template.yaml s3://your-sam-package-bucket/cweventFormat/packaged-template.yaml
aws s3 cp template-event.yaml s3://your-sam-package-bucket/cweventFormat/template-event.yaml

Resources

The terraform module will create and manage these resources for you:

  • SNS Topic: if you do not pass in the ARN of an SNS Topic then one will be created for you.
  • Lambda Role and Policies: IAM role and policies used by the Lambda function to publish to the SNS Topic and write CloudWatch Logs. No other permissions are needed at this time.
  • Lambda Function: part that does all the work to format events for publishing, deployed from the s3://your-sam-package-bucket/cweventFormat. The Lambda function also uses the SNS Topic as a Dead Letter Queue (DLQ) for failed events.
  • CloudWatch Log Group: for logs generated by the Lambda function.
  • CloudWatch Metric Alarm: alarm that alerts on errors in the Lambda function. This publishes to the SNS Topic.

Parameters: Common

These parameters are used by the stack and are common to many of the components it manages.

Name Default Description
NotificationTopicARN "" SNS Topic to send formatted notifications to. If you do not specify a value here then an SNS Topic is created for you.

Parameters: Lambda

These parameters are used to configure the Lambda Function.

Name Default Description
LambdaName "cweventFormat" Base name (without the stack prefix) to use for the lambda function name.
LambdaTimezone "UTC" Timezone name to set when running the lambda function ("America/Chicago", "UTC", etc).

Parameters: Logs

These parameters control where the Lambda Function logs are sent and how long they are retained. You will always have a copy of the logs in CloudWatch Logs, but you can also have a copy sent to another Lambda Function or a Log Destination (for cross-account logging).

Name Default Description
LogRetentionInDays 30 Number of days to retain log streams in CloudWatch Logs.
LogSubscriptionARN "" Lambda function ARN or CloudWatch Logs Destination to subscribe to this log group.

Parameters: Events

There is a companion template file called template-event.yaml that you can use to connect this Lambda to various CloudWatch Events, using Event Patterns.

You can deploy this companion template multiple times, for each event pattern type you want to listen to.

Name Default Description
LambdaStackName Name of the CloudFormation Stack used to deploy the cweventFormat Lambda.
EventPattern CloudWatch Event pattern to trigger the lambda on.

Outputs

These outputs are useful for other parts of your CloudFormation stacks.

  • ${StackName}:LambdaRoleName
  • ${StackName}:LambdaRoleARN
  • ${StackName}:LambdaFunctionName
  • ${StackName}:LambdaFunctionARN
  • ${StackName}:NotificationTopicARN

Example

Here is an example template you can use to deploy the cweventFormat with a couple sample events:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Send emails about certain events in the AWS Account.

Resources:
  CWEventFormat:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/your-sam-package-bucket/cweventFormat/packaged-template.yaml
      Parameters:
        LambdaTimezone: America/Chicago

  AWSHealthEvents:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/your-sam-package-bucket/cweventFormat/template-event.yaml
      Parameters:
        LambdaStackName: !Select [ 1, !Split [ "/", !Ref CWEventFormat ] ]
        EventPattern: |
          {
            "source": [ "aws.health" ],
            "detail-type": [ "AWS Health Event" ]
          }
  GuardDutyFindingEvents:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/uiuc-sbutler1-sandbox/cweventFormat/sam/template-event.yaml
      Parameters:
        LambdaStackName: !Select [ 1, !Split [ "/", !Ref CWEventFormat ] ]
        EventPattern: |
          {
            "source": [ "aws.guardduty" ],
            "detail-type": [ "GuardDuty Finding" ]
            "detail": {
              "severity": [ { "numeric": [ ">=", 7 ] } ]
            }
          }

  EC2StateChangeEvents:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/your-sam-package-bucket/cweventFormat/template-event.yaml
      Parameters:
        LambdaStackName: !Select [ 1, !Split [ "/", !Ref CWEventFormat ] ]
        EventPattern: |
          {
            "source": [ "aws.ec2" ],
            "detail-type": [ "EC2 Instance State-change Notification" ]
          }
  EC2InstanceConnectEvents:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/your-sam-package-bucket/cweventFormat/template-event.yaml
      Parameters:
        LambdaStackName: !Select [ 1, !Split [ "/", !Ref CWEventFormat ] ]
        EventPattern: |
          {
            "detail-type": [ "AWS API Call via CloudTrail" ],
            "detail": {
              "eventSource": [ "ec2-instance-connect.amazonaws.com" ],
              "eventName": [ "SendSSHPublicKey" ]
            }
          }