Search code examples
terraformterraform-provider-aws

How do I attach a managed IAM policy and an inline/custom IAM policy to IAM roles?


I want to attach a managed IAM Policy ARN (like AmazomS3FullAccess) and an inline/custom IAM policy (written in JSON in terraform file) to a single IAM Role.

by using aws_iam_role_policy_attachment I am able to attach only one policy, what's the way to attach both?

variables.tf
------------

variable "iam_policy_arn" {
  description = "IAM Policy to be attached to role"
  type        = list(string)
  default     = ["arn:aws:iam::aws:policy/AWSLambdaFullAccess", "arn:aws:iam::aws:policy/AmazonSSMFullAccess", "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess"]
}




main.tf
-------


resource "aws_iam_role" "test_role" {
  name = "test_role"

  assume_role_policy = <<-EOF
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Effect":"Allow",
      "Principal":{
        "Service":"ec2.amazonaws.com"
      },
      "Action":"sts:AssumeRole"
    },
    {
      "Effect":"Allow",
      "Principal":{
        "Service":"sagemaker.amazonaws.com",
        "AWS":"*"
      },
      "Action":"sts:AssumeRole"
    }
  ]
}    
  EOF
}
resource "aws_iam_role_policy_attachment" "role_policy_attachment" {
  role       = "${aws_iam_role.test_role.name}"
  count      = "${length(var.iam_policy_arn)}"
  policy_arn = "${element(var.iam_policy_arn,count.index)}"

}

resource "aws_iam_instance_profile" "test_profile" {
  name = "test_profile"
  role = "${aws_iam_role.test_role.name}"
}

now I want to attach a custom policy like below to the role

resource "aws_iam_role_policy" "test_policy" {
  name = "test_policy"
  role = aws_iam_role.test_role.id

  policy = <<-EOF
  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": [
          "ec2:Describe*"
        ],
        "Effect": "Allow",
        "Resource": "*"
      }
    ]
  }
  EOF
}

How do I attach a managed IAM policy and a custom IAM policy to IAM roles?


Solution

  • I was able to attach a managed IAM policy and an inline/custom IAM policy to IAM role using the below code.

    # variables.tf
    variable "cloudwatch_lambda_iam_policy_arn" {
      type        = list(string)
      description = "IAM Policy to be attached to AWS CloudWatch Lambda role"
      default     = ["arn:aws:iam::aws:policy/AmazonEC2FullAccess", "arn:aws:iam::aws:policy/AWSLambdaExecute", "arn:aws:iam::aws:policy/AmazonCloudDirectoryFullAccess", "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]
    }
    
    #------------------------------------------------------------
    
    # lambda.tf
    resource "aws_iam_role" "awsmetrics_exec_role" {
      name = "awsmetrics-exec-role"
    
      assume_role_policy = <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Action": "sts:AssumeRole",
          "Principal": {
            "Service": "lambda.amazonaws.com"
          },
          "Effect": "Allow",
          "Sid": ""
        }
      ]
    }
    EOF
    }
    
    # custom/inline policy
    resource "aws_iam_role_policy" "sts_assumerole_lambda" {
      name = "sts-assumerole-lambda"
      role = aws_iam_role.awsmetrics_exec_role.id
    
      policy = <<-EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "VisualEditor0",
          "Effect": "Allow",
          "Action": [
            "sts:AssumeRole",
            "sts:DecodeAuthorizationMessage",
            "sts:AssumeRoleWithSAML",
            "sts:AssumeRoleWithWebIdentity"
          ],
          "Resource": "*"
        }
      ]
    }
    EOF
    }
    
    # AWS managed policies
    resource "aws_iam_role_policy_attachment" "awsmetrics_role_policy_attachment" {
      role       = aws_iam_role.awsmetrics_exec_role.name
      count      = length(var.cloudwatch_lambda_iam_policy_arn)
      policy_arn = element(var.cloudwatch_lambda_iam_policy_arn, count.index)
    }