How to add a subscription filter using CloudFormation?

Viewed 3333

I'm generating a CloudFormation template with several AWS Lambda functions. As part of the CloudFormation template I also want to add a subscription filter so that CloudWatch logs will be sent to a different account. However, since I don't know the name of the logs groups at advance and couldn't find any way to have a reference to them I wasn't able to solve it.

Is there a way to do so?

3 Answers

You can use a function to get the log group name. For example:

"LogGroupName": {
    "Fn::Join": [
        "",
        [
            "/aws/lambda/",
            {
                "Ref": "MyLambdaFunction"
            }
        ]
    ]
}

Note that MyLambdaFunction is the name of your Lambda function block in the CloudFormation template.

You can try to use custom function to invoke your lambda which in turn can run your lambda with a test payload or something like that, which eventually will create a log stream then you can refer to that log group for subscription as mentioned by praveen earlier.

The way Serverless does it should work for you. It creates a log group resource with a name matching what your Lambda function will use. You can then reference that log group wherever you need it. You will have to give your Lambda function a name and not use the default naming behavior. You can use the stack name to make it unique.

Something like:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "FunctionLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Sub": "/aws/lambda/MyFunction-${AWS::StackName}"
        }
      }
    },
    "MyFunctionNameRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "ManagedPolicyArns": ["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [{
            "Action": ["sts:AssumeRole"],
            "Effect": "Allow",
            "Principal": {
              "Service": ["lambda.amazonaws.com"]
            }
          }]
        }
      }
    },
    "MyFunction": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "def index():\n  return 'hello world'\n"
        },
        "FunctionName": {
          "Fn::Sub": "MyFunction-${AWS::StackName}"
        },
        "Handler": "handler.index",
        "MemorySize": 128,
        "Role": {
          "Fn::GetAtt": [
            "MyFunctionNameRole",
            "Arn"
          ]
        },
        "Runtime": "python3.6"
      },
      "DependsOn": [
        "FunctionLogGroup"
      ]
    },
    "MySubscriptionFilter": {
      "Type" : "AWS::Logs::SubscriptionFilter",
      "Properties" : {
        "DestinationArn": "TODO TODO",
        "FilterPattern": "",
        "LogGroupName": {"Ref": "FunctionLogGroup"},
        "RoleArn": "TODO TODO"
      }
    }
  }
}
Related