Using IAM Roles for EC2 Credentials - Ansible: Up and Running (2015)

Ansible: Up and Running (2015)

Appendix C. Using IAM Roles for EC2 Credentials

If you’re going to run Ansible inside of a VPC, you can take advantage of Amazon’s Identity and Access Management (IAM) roles so that you do not even need to set environment variables to pass your EC2 credentials to the instance.

Amazon’s IAM roles let you define users and groups and control what those users and groups are permitted to do with EC2 (e.g., get information about your running instances, create instances, create images). You can also assign IAM roles to running instances, so you can effectively say: “This instance is allowed to start other instances.”

When you make requests against EC2 using a client program that supports IAM roles, and an instance is granted permissions by an IAM role, the client will fetch the credentials from the EC2 instance metadata service and use those to make requests against the EC2 service end point.

You can create an IAM role through the Amazon Web Services (AWS) management console, or at the command line using the AWS Command Line Interface tool, or AWS CLI.

AWS Management Console

Here’s how you would use the AWS management console to create an IAM role that has “Power User Access,” meaning that it is permitted to do pretty much anything with AWS except to modify IAM users and groups.

1. Log in to the AWS management console.

2. Click on “Identity & Access Management.”

3. Click on “Roles” at the left.

4. Click the “Create New Role” button.

5. Give your role a name. I like to use “ansible” as the name for the role for my instance that will run Ansible.

6. Under “AWS Service Roles,” select “Amazon EC2.”

7. Select “Power User Access.” The web interface should then show you a policy name and a policy document, and give you an opportunity to edit them if you like. The default policy name will look something like PowerUserAccess-ansible-201411182152, and the policy document is a JSON string that should look like Example C-1.

8. Click “Next Step.”

9. Click “Create Role.”

Example C-1. IAM power user policy document

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"NotAction": "iam:*",

"Resource": "*"

}

]

}

When you create a role through the web interface, AWS also automatically creates an instance profile with the same name as the role (e.g., “ansible”), and associates the role with the instance profile name. When you create an instance with the ec2 module, if you pass the instance profile name as the instance_profile_name parameter, then the created instance will have the permissions of that role.

Command-Line

You can also create the role and the instance profile using the AWS CLI tool, but it’s a bit more work. You need to:

1. Create a role, specifying the trust policy. The trust policy describes the entities that can assume the role and the access conditions for the role.

2. Create a policy that describes what the role is permitted to do. In our case, we want to create the equivalent of the power user, where the role can perform any AWS-related action except manipulate IAM roles and groups.

3. Create an instance profile.

4. Associate the role with the instance profile.

You’ll need to create two IAM policy files first, which are in JSON format. The trust policy is shown in Example C-2. This is the same trust policy that AWS automatically generates when you create the role via the web interface.

The role policy that describes what the role is allowed to do is shown in Example C-3.

Example C-2. trust-policy.json

{

"Version": "2012-10-17",

"Statement": [

{

"Sid": "",

"Effect": "Allow",

"Principal": {

"Service": "ec2.amazonaws.com"

},

"Action": "sts:AssumeRole"

}

]

}

Example C-3. power-user.json

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"NotAction": "iam:*",

"Resource": "*"

}

]

}

Example C-4 shows how you’d create an instance profile on the command line, once you’ve created the files shown in Examples C-2 and C-3.

Example C-4. Creating an instance profile at the command line

# Make sure that trust-policy.json and power-user.json are in the

# current directory, or change the file:// arguments to include the

# complete path

$ aws iam create-role --role-name ansible --assume-role-policy-document \

file://trust-policy.json

$ aws iam put-role-policy --role-name ansible --policy-name \

PowerUserAccess-ansible-20141118 --policy-document file://power-user.json

$ aws iam create-instance-profile --instance-profile-name ansible

$ aws iam add-role-to-instance-profile --instance-profile-name ansible \

--role-name ansible

As you can see, it’s much simpler to do this via the web interface, but if you want to automate this, then you can use the command line instead. Check out the AWS Identity and Access Management User Guide for more details on IAM.

Once you’ve created the instance profile, you can then launch an EC2 instance with that instance profile. You can do this with the ec2 module using the instance_profile_name parameter:

- name: launch an instance with iam role

ec2:

instance_profile_name: ansible

# Other parameters not shown

If you SSH into this instance, you can query the EC2 metadata service to confirm that this instance is associated with the Ansible profile. The output should look something like this:

$ curl http://169.254.169.254/latest/meta-data/iam/info

{

"Code" : "Success",

"LastUpdated" : "2014-11-17T02:44:03Z",

"InstanceProfileArn" : "arn:aws:iam::549704298184:instance-profile/ansible",

"InstanceProfileId" : "AIPAINM7F44YGDNIBHPYC"

}

You can also directly inspect the credentials, although it’s not something you need to do. The Boto library will automatically retrieve these credentials when the Ansible ec2 modules or dynamic inventory script executes:

$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ansible

{

"Code" : "Success",

"LastUpdated" : "2015-02-09T21:45:20Z",

"Type" : "AWS-HMAC",

"AccessKeyId" : "ASIAIYXCUETJPY42AC2Q",

"SecretAccessKey" : "ORp9gldiymIKH9+rFtWEx8BjGRteNTQSRnLnlmWq",

"Token" : "AQoDYXdzEGca4AMPC5W69pvtENpXjw79oH9...",

"Expiration" : "2015-02-10T04:10:36Z"

}

These credentials are temporary, and Amazon will rotate them automatically for you.

You can now use this instance as your control machine, without needing to specify your credentials via environment variables. The Ansible ec2 modules will automatically retrieve the credentials from the metadata service.