2
votes

I want to create an alert if something goes wrong with Lambda function especially when lambda throws an exception. I am planning to configure SNS topic to send a message if that alert is triggered.

All lambdas are created using CloudFormation scripts, so I am searching for a CloudFormation template to configure alarms on CloudWatch logs. I was not able to find a good/working sample. Sample code below .

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudTrail API Activity Alarm Template for CloudWatch Logs",
  "Parameters" : {
      "LogGroupName" : {
          "Type" : "String",
          "Default" : "CloudTrail/DefaultLogGroup",
          "Description" : "Enter CloudWatch Logs log group name. Default is CloudTrail/DefaultLogGroup"
      },
      "Email" : {
          "Type" : "String",
          "Description" : "Email address to notify when an API activity has triggered an alarm"
      }
  },
  "Resources" : {
    "SecurityGroupChangesAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
          "AlarmName" : "CloudTrailSecurityGroupChanges",
          "AlarmDescription" : "Alarms when an API call is made to create, update or delete a Security Group.",
          "AlarmActions" : [{ "Ref" : "AlarmNotificationTopic" }],
          "MetricName" : "SecurityGroupEventCount",
          "Namespace" : "CloudTrailMetrics",
          "ComparisonOperator" : "GreaterThanOrEqualToThreshold",
          "EvaluationPeriods" : "1",
          "Period" : "300",
          "Statistic" : "Sum",
          "Threshold" : "1"
      }
    },

    "AlarmNotificationTopic": {
      "Type": "AWS::SNS::Topic",
      "Properties": {
          "Subscription": [
              {
                  "Endpoint": { "Ref": "Email" },
                  "Protocol": "email"
              }
          ]
      }
    }
  }
}
1

1 Answers

2
votes

In order to do this, we need to create a subscription filter on the log group for that lambda with FilterPattern: "Exception"

So whenever there is an Exception word in log message it will trigger a monitor lambda.

Following is a cloudformation template in YAML that I have written

Resources:
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: 'AllowLambdaAccess'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: "Allow"
                Resource:
                  Fn::Join:
                    - ''
                    - - 'arn:aws:logs:'
                      - Ref: AWS::Region
                      - ':'
                      - Ref: AWS::AccountId
                      - ':log-group:/aws/lambda/*'
              - Action:
                  - ec2:DescribeNetworkInterfaces
                  - ec2:CreateNetworkInterface
                  - ec2:DeleteNetworkInterface
                Effect: "Allow"
                Resource: "*"
      RoleName: !Sub "${AWS::StackName}-LambdaExecutionRole"
  SubscriptionFilter: 
    Type: "AWS::Logs::SubscriptionFilter"
    DependsOn: "LambdaInvokePermission"
    Properties: 
      LogGroupName: !Sub "/aws/lambda/${LogGroupName}"
      FilterPattern: "Exception"
      DestinationArn: 
        Fn::GetAtt: 
          - "LambdaFunction"
          - "Arn"
  LambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        S3Bucket: !Ref S3BucketName
        S3Key: !Ref ZipFile
      Description: Monitor Lambda Function
      Handler: 'index.handler'
      MemorySize: 1536
      Role: !GetAtt 
        - LambdaExecutionRole
        - Arn
      Runtime: nodejs6.10  
      Environment:
        Variables:
          SMTP_SERVER: !Ref SMTPServer
          SMTP_PORT: !Ref SMTPPort
          EMAIL_FROM: !Ref FromEmail
          EMAIL_TO: !Ref ToEmail
      Timeout: 300
      FunctionName: !Sub "${AWS::StackName}-LambdaFunction"
      VpcConfig:
        SecurityGroupIds: !Split [ ",", !Ref SecurityGroupId ]
        SubnetIds: !Split [ ",", !Ref SubnetIds ]
    DependsOn:
      - LambdaExecutionRole
  LambdaInvokePermission: 
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: !Ref "LambdaFunction"
        Action: "lambda:InvokeFunction"
        Principal: !Sub "logs.${AWS::Region}.amazonaws.com"
        SourceArn:  
            Fn::Join:
                - ''
                - - 'arn:aws:logs:'
                  - Ref: AWS::Region
                  - ':'
                  - Ref: AWS::AccountId
                  - !Sub ':log-group:/aws/lambda/${LogGroupName}*'