Cloud architecture, Chef, AWS, and Python stuff

Why IAM Roles for EC2 Is a Big Deal

Yesterday – Amazon announced IAM roles for EC2 instances (IAM roles for EC2 instances – Simplified Secure Access to AWS service APIs from EC2). It may not seem like a shiny new feature. But it is pretty fantastic.

Before the IAM roles were released – anyone writing an application for AWS and deploying it on EC2 had to deal with getting their AWS Access Key and Secret Key into their application. These are just as important as a database password and should never be put into source version control.

Some of the approaches I’ve seen used were:

  • A configuration file placed on the EC2 instance with the keys.
  • Putting the keys into the instance user-data at launch.
  • Pushing the keys to the application on first launch.

Sure these approaches work – but none of them will work well if you have to rotate your keys (which is a best practice for any application regardless of where it is hosted – especially if someone who knows the keys/passwords leaves the organization). They can also be problematic when auto-scaling is introduced. Especially when the keys must be pushed to your application from another server.

With IAM roles for EC2 – you define your permissions much like an IAM user (which you were already using….right?!). And then simply attach the role to an instance when you launch it.

The EC2 instance has a special internally accessible url you can query to get instance metadata. This is where the AWS Access Key and Secret Key will be available.

How is this different for security than the existing ways?

Amazon will automatically rotate these credentials multiple times a day. You don’t ever need to worry about rotating your keys again. Even when an employee leaves the organization.

Here is an example of how the code would have looked before to access an AWS resource. Note: This example is from the AWS Blog and is in Java. The boto library for Python hasn’t been updated to include support for IAM roles, although it appears to be in-progress and should be updated soon.

  AWSCredentials creds = new BasicAWSCredentials(
  CredentialProvider session = new STSSessionCredentialsProvider(creds);
  AmazonDynamoDB dynamo = new AmazonDynamoDBClient(session);

Here is how the new code will look with the latest AWS SDKs:

  AmazonDynamoDB dynamo = new AmazonDynamoDBClient();

It’s easier to code – and deployment is a breeze. You don’t have to try and get those credentials into your application via OS environment variables/config files/etc.

When developing locally – you will not have access to the instance metadata (unless you develop on EC2), so take advantage of the SDK’s default way it loads credentials when not provided explicitely.

For Python/Boto – when not specified, it looks for local environment variables:

AWS_SECRET_ACCESS_KEY - Your AWS Secret Access Key

Alternatively – you can use a boto config file located in either:

  • /etc/boto.cfg (for site-wide settings, all users)
  • ~/.boto (for user-specific settings)
aws_access_key_id = <your access key>
aws_secret_access_key = <your secret key>

More details on configuring boto: BotoConfig

This feature may not seem like a huge savings for configuration/deployment. But it’s huge for security and longer-term maintenance. And that helps you get back to writing code for new stuff.