Reputation: 895
I am trying write the logs of a lambda function into a CloudWatch Log Group created by terraform.
This is the lambda policy json -
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1580216411252",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogDelivery",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": "arn:aws:logs:*:*:*"
}
]
}
This is the lambda assume policy json -
{
"Version": "2012-10-17",
"Statement": [{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}]
}
I have added this to the lambda.tf file -
resource "aws_cloudwatch_log_group" "example" {
name = "/test/logs/${var.lambda_function_name}"
}
Although the CloudWatch Log Group '/test/logs/${var.lambda_function_name}' is getting created through terraform, I am unable to write the log of the lambda function to this group.
If I change the lambda policy json to this -
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "Stmt1580204738067",
"Action": "logs:*",
"Effect": "Allow",
"Resource": "*"
}]
}
Then It automatically stores the log in /aws/lambda/ directory.
How can I make sure that the lambda logs get written into a CloudWatch Log Group that I create and not in the /aws/lambda/ group created by lambda itself?
Upvotes: 13
Views: 17918
Reputation: 181
You can follow most if not all of milieere did and it will do it. A quick shortcut you an also do is you can use the AWSLambdaBasicExecution
policy that's managed by AWS. This just simplifies Step 2
where you create a policy document. You can define it as a data
resource
data "aws_iam_policy" "lambda_basic_execution_policy" {
arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
You can then use it as an attachment like so
resource "aws_iam_role_policy_attachment" "lambda_flow_log_cloudwatch" {
role = aws_iam_role.lambda.name
policy_arn = data.aws_iam_policy.lambda_basic_execution_policy.arn
}
Just a bit cleaner in my opinion.
Upvotes: 2
Reputation: 171
Just adding the log group as a dependency to the lambda is not enough. You also have to attach the IAM policy to the lambda role.
The steps are following:
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
EOF
}
resource "aws_iam_policy" "function_logging_policy" {
name = "function-logging-policy"
policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
Action : [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
Effect : "Allow",
Resource : "arn:aws:logs:*:*:*"
}
]
})
}
resource "aws_iam_role_policy_attachment" "function_logging_policy_attachment" {
role = aws_iam_role.iam_for_lambda.id
policy_arn = aws_iam_policy.function_logging_policy.arn
}
resource "aws_cloudwatch_log_group" "lambda_log_group" {
name = "/aws/lambda/${var.lambda.function_name}"
retention_in_days = 7
lifecycle {
prevent_destroy = false
}
}
resource "aws_lambda_function" "lambda_function" {
filename = "../${var.lambda.function_filename}"
function_name = "${var.lambda.function_name}"
role = aws_iam_role.iam_for_lambda.arn
handler = "${var.lambda.handler}"
layers = [aws_lambda_layer_version.lambda_layer.arn]
depends_on = [aws_cloudwatch_log_group.lambda_log_group]
source_code_hash = filebase64sha256("../${var.lambda.function_filename}")
runtime = "python3.9"
}
The IAM policy creation & attachment comes from this article, the rest is from my personal project that worked for me.
Upvotes: 15
Reputation: 200527
If you want Terraform to manage the CloudWatch log group, you have to create the log group ahead of time with the exact name the Lambda function is going to use for its log group. You can't change the name at all. Then in your Terraform you need to make the log group a dependency of the Lambda function, to make sure Terraform has a chance to create the log group before Lambda creates it automatically.
Upvotes: 5