1
votes

I am trying to automate a marketplace ami which also does need access to the s3 bucket. Therefore I created an s3 bucket with

resource "aws_s3_bucket" "ddve6" {
  bucket = "js-ddve6-bucket"
}
output "S3_bucket_name" {
  value       = aws_s3_bucket.ddve6.bucket
  description = "The value you do need for DDVE configuration on the bucket name!"
}

So an ami can access this bucket I normally create an IAM Policy which I do create in terraform as well

resource "aws_iam_policy" "js_iam_policy_ddve6_s3" {
  name        = "js_ddve6_iam_policy"
  path        = "/"
  description = "My test policy"

  policy = file("jspolicy.json")
  # I do need to have a s3 storage created first
  depends_on = [aws_s3_bucket.ddve6]

}

jspolicy.json looks like:

{
   "Version": "2012-10-17",
   "Statement": [
          {
          "Effect": "Allow",
          "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
                ],
          "Resource": [
                "arn:aws:s3:::js-ddve6-bucket",
                "arn:aws:s3:::js-ddve6-bucket/*"
                ]
          }
   ]
}

to get this tight to an ec2 instance I usually do use and create a role into the aws console and attach this role for a access to ec2 with the common use case ec2. Attach the created Policy to this role and create a role without a permissions boundary. No tags so that I come to the config:

Trusted entitiesAWS service: ec2.amazonaws.com
Policies: js_ddve6_iam_policy 
Permissions boundary: Permissions boundary is not set

In terraform I created a role

resource "aws_iam_role" "js_ec2_s3_access_iam_role" {
  name               = "js_ddve6_iam_role"
  assume_role_policy = file("jsrolepolicy.json")
}

while the jsrolepolicy.json contains

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

I do assign a iam policy to a iam role with

resource "aws_iam_role_policy_attachment" "assign-policy-to-role-attach" {
  role       = aws_iam_role.js_ec2_s3_access_iam_role.name
  policy_arn = aws_iam_policy.js_iam_policy_ddve6_s3.arn

  depends_on = [aws_iam_policy.js_iam_policy_ddve6_s3]
}

and a aws_iam_instance_profile with

resource "aws_iam_instance_profile" "js_ddve_profile" {
  name = "jd_ddve_profile"
  role = aws_iam_role.js_ec2_s3_access_iam_role.name
}

with a

resource "aws_iam_instance_profile" "js_ddve_profile" {
  name = "jd_ddve_profile"
  role = aws_iam_role.js_ec2_s3_access_iam_role.name
}

the instance I do spin up does get the iam_instance_profile = aws_iam_instance_profile.js_ddve_profile.name

I do get a role but this role hat not the policy attached and I do not get the ec2 instance deployed with:

resource "aws_instance" "terraform_ddve" {
  ami           = lookup(var.ami_id, var.region)
  instance_type = var.instance_type
  subnet_id     = "subnet-024c26c397520c8f2"

  # key name
  key_name = var.key_name

  # Security group assign to instance
  vpc_security_group_ids = [aws_security_group.ddve6.id]
  # tighten things up
  iam_instance_profile = aws_iam_instance_profile.js_ddve_profile.name
  tags = {
    Name = var.ddve_name
  }
  # before we can start or create a ressource we need:
  depends_on = [aws_security_group.ddve6, aws_s3_bucket.ddve6, aws_ebs_volume.ebs_volume[0]]
}

WHY ????

1
Are there any errors during execution? Try adding the role as a dependency to the "attach" step although the reference to the role should imply dependency.peter n
Testing your provided code minus instance resource block produces the role with policy attached as expected. Adding a subnet and simple EC2 instance including your iam_instance_profile setting creates the instance including IAM Role as expected. Please provide any error output.T.H.

1 Answers

1
votes

This probably happens because creating your instance profile takes longer then expected. terraform does not wait for it to be "fully" available before creating your instance. Thus the instance deployment fails looking for a profile which does not yet exist.

The most basic way to overcome this issue is to add some delay into your code for the profile to have enough time to be created.


resource "aws_iam_instance_profile" "js_ddve_profile" {

  name = "jd_ddve_profile"
  role = aws_iam_role.js_ec2_s3_access_iam_role.name

  provisioner "local-exec" {
    command = "sleep 20"
  }
}