Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_iam_instance_profile DataSource should return Role Name in addition to or instead of Role ID #4080

Closed
mplanchard opened this issue Apr 5, 2018 · 10 comments · Fixed by #4300
Labels
bug Addresses a defect in current functionality. enhancement Requests to existing resources that expand the functionality or scope.
Milestone

Comments

@mplanchard
Copy link

mplanchard commented Apr 5, 2018

Terraform Version

0.11.5

AWS Provider Version

1.13.0

Affected Resource(s)

  • aws_iam_instance_profile

Terraform Configuration Files

resource "aws_cloudformation_stack" "docker_staging_stack" {
    name = "docker-staging-stack"
    template_url = "https://editions-us-east-1.s3.amazonaws.com/aws/stable/Docker.tmpl"
    timeout_in_minutes = 60
    parameters = {
        KeyName = "docker-staging-manager",
    }
    capabilities = ["CAPABILITY_IAM"]
}

// Generate a CMK for decrypting deployment secrets
resource "aws_kms_key" "docker_staging_deploy" {
    description = "Docker staging deployment key"
    tags = {
        environment = "staging"
    }
}

// Give it an alias for programmatic access
resource "aws_kms_alias" "docker_staging_deploy" {
    name = "alias/docker/deploy/staging"
    target_key_id = "${aws_kms_key.docker_staging_deploy.id}"
}

// Define a policy allowing access to the key and the secrets bucket
resource "aws_iam_policy" "docker_staging_deploy" {
    name = "docker_staging_deploy"
    policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DockerStagingDpeloyAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:s3:::/docker-secrets/staging/*",
                "${aws_kms_key.docker_staging_deploy.arn}"
            ]
        }
    ]
}
EOF
}

// list of all instances in the manager security group
data "aws_instances" "docker_staging_stack_managers" {
    filter {
        name = "instance.group-id"
        values = ["${aws_cloudformation_stack.docker_staging_stack.outputs.ManagerSecurityGroupID}"]
    }
}

// an arbitrary instance (in this case the first), so we can backtrack to the role
data "aws_instance" "docker_staging_stack_manager" {
    instance_id = "${data.aws_instances.docker_staging_stack_managers.ids[0]}"
}

// the instance profile, still back-tracking to the IAM role
data "aws_iam_instance_profile" "docker_staging_stack_manager" {
    name = "${data.aws_instance.docker_staging_stack_manager.iam_instance_profile}"
}

// Here we could get to the role if we had its normal name. However, all we
// have is its hidden ID, which doesn't work in this field
data "aws_iam_role" "docker_staging_stack_manager" {
    role = "${data.aws_iam_instance_profile.docker_staging_stack_manager.role_id}"
}

Expected Behavior

We're working with the Docker Cloudformation template, and attempting to use terraform to add a policy to the Instance Profile automatically created by the template. The template's outputs are pretty paltry:

  outputs.DefaultDNSTarget = docker-sta-External-15V4VNFM1D6K-322570444.us-east-1.elb.amazonaws.com
  outputs.ELBDNSZoneID = Z35SXDOTRQ7X7K
  outputs.ManagerSecurityGroupID = sg-8f977ac6
  outputs.Managers = https://us-east-1.console.aws.amazon.com/ec2/v2/home?region=us-east-1#Instances:tag:aws:autoscaling:groupName=docker-staging-stack-ManagerAsg-NIUL3V4K1ZSF;sort=desc:dnsName
  outputs.NodeSecurityGroupID = sg-df947996
  outputs.SwarmWideSecurityGroupID = sg-9d816cd4
  outputs.VPCID = vpc-27e1815c
  outputs.ZoneAvailabilityComment = This region has at least 3 Availability Zones (AZ). This is ideal to ensure a fully functional Swarm in case you lose an AZ.

If it were possible to navigate back to the dynamically generated role associated with the EC2 instances, we could add our policy to that role, no problem. However, there is no Data Source that allows searching for a Role by anything other than a complete name (which we don't have, since it was automatically generated).

However, I found a way (as shown in the configs above) to wind my way all the way to the Instance Policy, which is associated with the Role I'm trying to find. Unfortunately, it only exposes the unique Role ID, which is not used by any other Role-related Data Source or Resource, making it basically useless.

Ideally there would either be a way to get the RoleName from the aws_iam_instance_profile, or to use the RoleID to search for a role. The former seems better, since RoleNames are used throughout all other Role-related resources.

References

None that I could find

@catsby
Copy link
Contributor

catsby commented Apr 5, 2018

Hey –

The name attribute should be accessible for data aws_iam_instance_profile, even if it's not explicitly listed on the docs:

It accepts name, which is then exported as well (albeit implicitly documented as such).

I believe this would work for you, can you try it out?

data "aws_iam_role" "docker_staging_stack_manager" {
    name = "${data.aws_iam_instance_profile.docker_staging_stack_manager.name}"
    unique_id = "${data.aws_iam_instance_profile.docker_staging_stack_manager.role_id}"
}

@catsby catsby added bug Addresses a defect in current functionality. enhancement Requests to existing resources that expand the functionality or scope. waiting-response Maintainers are waiting on response from community or contributor. labels Apr 5, 2018
@mplanchard
Copy link
Author

mplanchard commented Apr 5, 2018

@catsby I'm happy to try, but I think that is the name of the instance profile, not the associated role, right?

In my particular example, terraform show yields the following:

data.aws_iam_instance_profile.docker_staging_stack_manager:
  id = AIPAJHGJ37PW3A4ZTEFHI
  arn = arn:aws:iam::438106514358:instance-profile/docker-staging-stack-ProxyInstanceProfile-1NGPN4I5GR9M2
  create_date = 2018-04-04 13:15:30 +0000 UTC
  name = docker-staging-stack-ProxyInstanceProfile-1NGPN4I5GR9M2
  path = /
  role_id = AROAI4ICLKBNMOOC4QDXA

The role it's referencing, on the other hand, has the name docker-staging-stack-ProxyRole-TXOBPZIAMLLF

@mplanchard
Copy link
Author

mplanchard commented Apr 5, 2018

Running it initially I get

Error: data.aws_iam_role.docker_staging_stack_manager: "unique_id": this field cannot be set

Removing unique_id and running plan, I get the following block:

 <= data.aws_iam_role.docker_staging_stack_manager
      id:                                <computed>
      arn:                               <computed>
      assume_role_policy:                <computed>
      assume_role_policy_document:       <computed>
      create_date:                       <computed>
      description:                       <computed>
      name:                              "docker-staging-stack-ProxyInstanceProfile-1NGPN4I5GR9M2"
      path:                              <computed>
      role_id:                           <computed>
      unique_id:                         <computed>

Running terraform refresh && terraform show``, there is no data.aws_iam_rolesection in the output ofterraform show`

The general role format of the AWS URLs is like:

https://console.aws.amazon.com/iam/home?region=us-east-1#/roles/<role_name>

Putting the instance profile name in there yields a "No Entity Found" error, while putting the expected role name yields the expected role.

@catsby catsby removed the waiting-response Maintainers are waiting on response from community or contributor. label Apr 5, 2018
@catsby
Copy link
Contributor

catsby commented Apr 5, 2018

Thanks for the follow up! I'm not sure we (HashiCorp) be able to tackle this right away, hopefully someone from the community will be able to

@mplanchard
Copy link
Author

It seems like it should be pretty easy. The AWS API does return the role name, as you can see in the response from the CLI:

(py36) mplanchard@mplanchard-lnx:~/git/it_devops/terraform/dev$ aws iam get-instance-profile --instance-profile-name=docker-staging-stack-ProxyInstanceProfile-1NGPN4I5GR9M2
{
    "InstanceProfile": {
        "Path": "/",
        "InstanceProfileName": "docker-staging-stack-ProxyInstanceProfile-1NGPN4I5GR9M2",
        "InstanceProfileId": "AIPAJHGJ37PW3A4ZTEFHI",
        "Arn": "arn:aws:iam::438106514358:instance-profile/docker-staging-stack-ProxyInstanceProfile-1NGPN4I5GR9M2",
        "CreateDate": "2018-04-04T13:15:30Z",
        "Roles": [
            {
                "Path": "/",
                "RoleName": "docker-staging-stack-ProxyRole-TXOBPZIAMLLF",
                "RoleId": "AROAI4ICLKBNMOOC4QDXA",
                "Arn": "arn:aws:iam::438106514358:role/docker-staging-stack-ProxyRole-TXOBPZIAMLLF",
                "CreateDate": "2018-04-04T13:15:17Z",
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "autoscaling.amazonaws.com",
                                    "ec2.amazonaws.com"
                                ]
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                }
            }
        ]
    }
}

I'm not a Go programmer, but I started taking a stab at updating the tests here. I'm sure I'm doing something wrong, but I can't get the tests to fail! I've updated the tests as follows:

func TestAccAWSDataSourceIAMInstanceProfile_basic(t *testing.T) {
	roleName := fmt.Sprintf("test-datasource-user-%d", acctest.RandInt())
	profileName := fmt.Sprintf("test-datasource-user-%d", acctest.RandInt())

	resource.Test(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccDatasourceAwsIamInstanceProfileConfig(roleName, profileName),
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttrSet("data.aws_iam_instance_profile.test", "role_id"),
                                        # I added the line below!
                                        resource.TestCheckResourceAttrSet("data.aws_iam_instance_profile.test", "role_name"), 
					resource.TestCheckResourceAttr("data.aws_iam_instance_profile.test", "path", "/testpath/"),
					resource.TestMatchResourceAttr("data.aws_iam_instance_profile.test", "arn",
						regexp.MustCompile("^arn:aws:iam::[0-9]{12}:instance-profile/testpath/"+profileName+"$")),
				),
			},
		},
	})
}

It seems like this should fail, but it doesn't.

@mplanchard
Copy link
Author

FYI, I am currently working around this using a local-exec calling out to the AWS CLI as follows:

  provisioner "local-exec" {
    command = <<EOF
aws iam get-instance-profile --instance-profile-name=${data.aws_iam_instance_profile.docker_staging_stack_manager.name} \
    | grep -oP 'RoleName": "\K(${aws_cloudformation_stack.docker_staging_stack.name}[-0-9A-Za-z]+)(?=",)' \
    | xargs -I '{}' aws iam attach-role-policy --policy-arn ${aws_iam_policy.docker_staging_deploy.arn} --role-name '{}'
EOF
  }

This grabs the instance profile JSON, parses it to get the associated role name (which is all the data source needs to do to actually be useful), and then pipes that to the attach-role-policy command.

@bflad
Copy link
Contributor

bflad commented Apr 23, 2018

The role_arn and role_name attributes were added to the aws_iam_instance_profile data source via #4300 and will release with v1.16.0 of the AWS provider, likely in a few days.

@bflad
Copy link
Contributor

bflad commented Apr 25, 2018

This has been released in version 1.16.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

@mplanchard
Copy link
Author

Thanks @bflad - we'll update asap and replace our existing hack

@ghost
Copy link

ghost commented Apr 6, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Apr 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Addresses a defect in current functionality. enhancement Requests to existing resources that expand the functionality or scope.
Projects
None yet
3 participants