Search code examples
amazon-web-servicesterraformterraform-provider-aws

Define Lambda policy and assume role policy


I'm writing a Lambda function that should be triggered (after X amount of time) using a CloudWatch event. I have almost the configuration working, but I can't get the policy business from AWS right. This is what I have so far:

data "aws_iam_policy_document" "this" {
  statement {
    actions = ["sts:AssumeRole"]
    effect  = "Allow"
    principals {
      identifiers = ["lambda.amazonaws.com"]
      type        = "Service"
    }
  }
  statement {
    actions   = [
      "logs:CreateLogStream",
      "logs:PutLogEvents",
    ]
    effect    = "Allow"
    resources = ["arn:aws:logs:*:*:*"]
  }
}

resource "aws_iam_role_policy_attachment" "this" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  role       = aws_iam_role.this.name
}

resource "aws_iam_role" "this" {
  assume_role_policy = data.aws_iam_policy_document.this.json
  name               = "AWSLambdaSpringCloudFunctionBasicExecutionRole"
}

I just want the Lambda to be able to write to CloudWatch and be triggered by the CloudWatch Event source...that's all, no more permissions. I'm creating the Log Group via Terraform, so no need for logs:CreateLogGroup.

When I do terraform apply (version 0.12.24) this error pops out:

aws_iam_role.this: Creating...

Error: Error creating IAM Role AWSLambdaSpringCloudFunctionBasicExecutionRole: MalformedPolicyDocument: Has prohibited field Resource
    status code: 400, request id: 12ad676e-b98e-4c60-bedd-bf17487bd51d

Is there a way to declare the AWS Lambda policy and assume role policy together? If not, what are the recommended Terraform resources/data sources for doing this?


UPDATE: Complete Solution

As Oleksii pointed out, I was using the wrong resource to create the IAM policy:

data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
    effect  = "Allow"
    principals {
      identifiers = ["lambda.amazonaws.com"]
      type        = "Service"
    }
  }
}

resource "aws_iam_role_policy_attachment" "assume_role" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  role       = aws_iam_role.lambda.name
}

resource "aws_iam_role" "lambda" {
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
  name               = "Use Any Identifier/Name You Want Here For IAM Role"
}

data "aws_iam_policy_document" "logs" {
  statement {
    actions   = [
      "logs:CreateLogStream",
      "logs:PutLogEvents",
    ]
    effect    = "Allow"
    resources = ["arn:aws:logs:*:*:*"]
  }
}

resource "aws_iam_policy_attachment" "logs" {
  name       = "Use Any Identifier/Name You Want Here For IAM Policy Logs"
  policy_arn = aws_iam_policy.logs.arn
  roles      = [aws_iam_role.lambda.name]
}

resource "aws_iam_policy" "logs" {
  name   = "Use Any Identifier/Name You Want Here For IAM Policy Logs"
  policy = data.aws_iam_policy_document.logs.json
}

Solution

  • You're trying to define multiple statements in assume_role_policy, which is not a regular policy, but a "trust relation" type of policy. It only describes who can assume role and under which conditions.

    From my understanding (limited Terraform knowledge) you need to move second statement to its own policy and then attach it via aws_iam_role_policy_attachment