Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terraform - How to create IAM role for AWS Lambda and deploy both?

I am learning Terraform. I am trying to create a new Lambda function. And I realized that I also need to create an IAM role. So I am trying to do both using Terraform. But it does not allow me to create the role.

This is my Terraform file

provider "aws" {
  profile = "default"
  region  = "eu-west-1"
}

data "aws_iam_policy" "AWSLambdaBasicExecutionRole" {
  arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}

resource "aws_iam_role" "terraform_function_role" {
  name               = "terraform_function_role"
  assume_role_policy = "${data.aws_iam_policy.AWSLambdaBasicExecutionRole.policy}"
}

resource "aws_lambda_function" "terraform_function" {
  filename         = "terraform_function.zip"
  function_name    = "terraform_function"
  handler          = "index.handler"
  role             = "${aws_iam_role.terraform_function_role.id}"
  runtime          = "nodejs8.10"
  source_code_hash = "${filebase64sha256("terraform_function.zip")}"
}

This is the error that I am getting

Error creating IAM Role terraform_function_role: MalformedPolicyDocument: Has prohibited field Resource
status code: 400

How do I fix this?

like image 596
Rahul Kadam Avatar asked Jul 31 '19 10:07

Rahul Kadam


People also ask

How do you attach IAM role to Lambda function?

Attach the IAM policy to an IAM roleNavigate to the IAM console and choose Roles in the navigation pane. Choose Create role. Choose AWS service and then choose Lambda. Choose Next: Permissions.

Can we create Lambda function using Terraform?

Although you can create and run Lambda functions from the AWS web console, Terraform is a great tool for managing Lambda functions via IaC (Infrastructure as Code.


1 Answers

IAM Role's trust relationship (or assume role policy) defines which resource / service can assume the role. In this, we don't define the Resource field. Hence we can't attach IAM policies or use that policy as is. The correct format for Trust Relationship is:

{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Principal": {
            "Service": "lambda.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
    }]
}

In this scenario, all Lambda functions in your account can assume this role.

You can refer this AWS link for more examples.

Edit: Based on @ydaetskcoR comment, here's a working example:

provider "aws" {
  profile = "default"
  region  = "eu-west-1"
}

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

resource "aws_iam_role" "terraform_function_role" {
  name               = "terraform_function_role"
  assume_role_policy = "${data.aws_iam_policy_document.AWSLambdaTrustPolicy.json}"
}

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

resource "aws_lambda_function" "terraform_function" {
  filename         = "terraform_function.zip"
  function_name    = "terraform_function"
  handler          = "index.handler"
  role             = "${aws_iam_role.terraform_function_role.arn}"
  runtime          = "nodejs8.10"
  source_code_hash = "${filebase64sha256("terraform_function.zip")}"
}

The changes from your code include the following:

  • Updated aws_iam_policy_document resource for assume role permissions
  • Changed aws_iam_role resource to use the above mentioned policy document
  • Created aws_iam_role_policy_attachment to attach LambdaBasicExecution policy (which enables logging to CloudWatch)
  • Updated aws_lambda_function resource to use IAM Role's ARN instead of Id because Lambda function needs the ARN
like image 74
krishna_mee2004 Avatar answered Oct 14 '22 14:10

krishna_mee2004