17
votes

AWS Lambda logging on CloudWatch may become an huge hidden cost if you have a lot of them, because there are no way to tell AWS to stop logging on CloudWatch platform. The only way I have found to do that is to manage a custom IAM policy (associated with every lambda) and explicitally deny access to the logs:... actions:

{
        "Sid": "DisableAllLogs",
        "Resource": "*",
        "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Effect": "Deny"
}

Now I'm trying to fine graining the policy to let only some lambda to log. To do that I'm using the Condition parameters of the policy:

{
        "Sid": "EnableLogsForWantedLambdaTriggers",
        "Resource": "*",
        "Condition": {
            "ArnEquals": {
                "aws:SourceArn": "arn:aws:lambda:REGION:ACCOUNT-ID:function:FUNCTION-NAME"
            }
        },
        "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Effect": "Allow"
}

but in this way no log is sent to CloudWatch. I think that the source ARN is wrong but I can't figure out to find the correct one.

Any clues?

1
I assume you're creating the lambda in your CloudFormation as well? If so you should be able to grab the correct ARN with "Fn::GetAtt": ["FUNCTION-NAME", "Arn"]Squirrel
I assume that deleting the logs or archiving them after a while to save money has already been looked at. I would do that before making all functions log and then selecting certain ones and denying access to them.arjabbar
Unfortunately the big part of the costs are related to the CloudWatch calls instead of the log stored size, so setting expire date to 1 day is not enoughClaudio Bertozzi

1 Answers

3
votes

A possible workaround that I've found is to focus the policy on resources instead on the caller ARN of the action. So, if I now the lambda logGroupName and logStreamName (and I always now these) I can Allow only the actions over the resource that the logger will create, following the documented naming convention:

{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Sid": "EnableLogsForWantedLambdaTriggers",
        "Resource": [
            "arn:aws:logs:<region>:<ID>:log-group:<logGroupName>:log-stream:<logStreamName>"
        ],
        "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Effect": "Allow"
    }
  ]
}

in this way I have the choice to enable wanted lamda and/or (acting on stream name) selected function version ($LATEST, 1, 2, ...).

For example, the next will enable only the development version of the function ignoring the production ones:

{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Sid": "EnableLogsForWantedLambdaTriggers",
        "Resource": [
            "arn:aws:logs:<region>:<ID>:log-group:<logGroupName>:log-stream:*/*/*/[$LATEST]*"
        ],
        "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Effect": "Allow"
    }
  ]
}