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 enough - Claudio 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"
    }
  ]
}