ebnius
ebnius

Reputation: 930

EC2 instance with a cross account IAM role

I've created a cross account IAM role in one of my accounts(say account A) and would like to attach that role to an ec2 instance in another account(account B).

I tried creating a new role in account B with sts:AssumeRole pointing to the role in A and attached it to an ec2 instance in B. Doesn't seem to be working.

How can the ec2 instance assume the cross account role in A?

Upvotes: 21

Views: 24545

Answers (4)

Stefano Frazzetto
Stefano Frazzetto

Reputation: 197

According to the latest docs, you can create a named role profile in ~/.aws/config, on your EC2 instance in ACCOUNT B, as follows

[profile marketingadmin]
role_arn = arn:aws:iam::ACCOUNT_A:role/marketingadminrole
credential_source = Ec2InstanceMetadata

The following might be useful for similar scenarios

The credential_source attribute supports the following values:

  • Environment – Retrieves the source credentials from environment variables.

  • Ec2InstanceMetadata – Uses the IAM role attached to the Amazon EC2 > instance profile.

  • EcsContainer – Uses the IAM role attached to the Amazon ECS container.

Upvotes: 0

Sri Utnoor
Sri Utnoor

Reputation: 1

You can also export as below for step 5 above :

TEMP_ACCESS_ACCOUNT=$(aws sts assume-role --role-arn arn:aws:iam::Account_A_ID:role/RoleForB --role-session-name example)

export AWS_ACCESS_KEY_ID=$(echo ${TEMP_ACCESS_ACCOUNT} | jq -r '.["Credentials"]["AccessKeyId"]')

export AWS_SECRET_ACCESS_KEY=$(echo ${TEMP_ACCESS_ACCOUNT} | jq -r '.["Credentials"]["SecretAccessKey"]')

export AWS_SESSION_TOKEN=$(echo ${TEMP_ACCESS_ACCOUNT} | jq -r '.["Credentials"]["SessionToken"]')

Upvotes: 0

Exequiel Barrirero
Exequiel Barrirero

Reputation: 5868

Supposing the scenario with two accounts A & B the explanatory steps should be:

  1. In account A, I created a role (e.g RoleForB) to trust account B, and attach to the before created role a IAM policy to allow it to perform some read operations in account A. e.g ReadOnlyAccess
  2. In account B, I created a role (e.g AssumeRoleInA) and attach a policy to allow it to assume the role that is created in account A.
  3. In account B Associate to your EC2 instance ec2-profile the IAM role (AssumeRoleInA) created in step 2.
  4. In account B login into this EC2 instance to assume the role in Account A using the command aws sts assume-role --role-arn "arn:aws:iam::Account_A_ID:role/RoleForB" --role-session-name "EC2FromB".
  5. In account B EC2 terminal when the command is step 4. finished, you can see the access key ID, secret access key, and session token from wherever you've routed it, in our case stdout either manually or by using a script. You can then assign these values to environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN)

So Let’s check the configurations mentioned above step by step but with some mode detail:

  1. As before presented in account A, it builds the trust to account B by creating the role named RoleForB and attaching ReadOnlyAccess permission to it.
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::Account_B_ID:root"},
        "Action": "sts:AssumeRole"
    }
}
  1. In account B, create a role named AssumeRoleInA then attach the corresponding policy to allow it to assume the role named RoleForB in account A.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": [
        "arn:aws:iam::Account_A_ID:role/RoleForB"
      ]
    }
  ]
}
  1. In account B, create a new EC2 instance (if it does not exists yet), and associate it's ec2-profile with the IAM role named AssumeRoleInA.
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": {"Service": "ec2.amazonaws.com"},
        "Action": "sts:AssumeRole"
    }
}
  1. In account B login into this EC2 instance to assume the role in Account A using the command:
aws sts assume-role --role-arn "arn:aws:iam::Account_A_ID:role/RoleForB" --role-session-name "EC2FromB"`

eg:

jenkins@bb-jenkins-vault:~$ aws sts assume-role --role-arn arn:aws:iam::521111111144:role/DeployMaster --role-session-name "project-dev-jenkins-deploy"
{
    "AssumedRoleUser": {
        "AssumedRoleId": "AROAJBXGEHOQBXGEHOQ:project-dev-jenkins-deploy", 
        "Arn": "arn:aws:sts::521111111144:assumed-role/DeployMaster/project-dev-jenkins-deploy"
    }, 
    "Credentials": {
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", 
        "SessionToken": "FQoGZXIvYXCUm8iG6/zLdQ7foognvCDpxKP7cRJiZgc...CUm8iG6/zLdQ7foognvCDpxKP7c+OQF", 
        "Expiration": "2019-03-29T15:41:02Z", 
        "AccessKeyId": "AKIAI44QH8DHBEXAMPLE"
    }
}
  1. In account B EC2 terminal when the command is step 4. finished, you can see the access key ID, secret access key, and session token from wherever you've routed it, in our case stdout either manually or by using a script. You can then assign these values to environment variables
$ export AWS_ACCESS_KEY_ID=AKIAI44QH8DHBEXAMPLE
$ export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
$ export AWS_SESSION_TOKEN=FQoGZXIvYXCUm8iG6/zLdQ...<remainder of security token>
$ aws ec2 describe-instances --region us-east-1

complementary reading: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html

Upvotes: 14

Matt Houser
Matt Houser

Reputation: 36083

You cannot attach a cross-account IAM role to an EC2 instance directly. And having the sts:AssumeRole permissions does not automatically make the one role assume into the other.

Instead:

  1. Create your cross-account role in Account A.
  2. Create an IAM role for EC2 instances in Account B. Give this role permissions to execute sts:AssumeRole.
  3. Assign the IAM role from #2 to your EC2 instance.

Then, when you want to access the AWS API from your EC2 instance:

  1. Execute sts:AssumeRole to assume the cross-account role for Account A, to obtain temporary credentials.
  2. Use those temporary credentials to execute the rest of your API methods.

Upvotes: 31

Related Questions