AWS Security Blog

A Safer Way to Distribute AWS Credentials to EC2

If you have applications running on EC2 that also access other AWS services like Amazon S3 or Amazon DynamoDB, then these applications require credentials out on the EC2 instance.  You can hard-code AWS access keys into your application, but you’re faced with the added responsibility of distributing them to the instance securely and then the management headache of regularly rotating them within large, autoscaling fleets.

This week’s guest blogger, Will Kruse, Security Engineer on the AWS Identity and Access Management (IAM) team, will explain how you can easily and securely manage your AWS access keys using a feature called IAM roles for EC2. He’ll also provide sample commands that let you locate any previously hard-coded secret keys.


Managing AWS Credentials with Roles for EC2

The most common AWS credential that developers hard-code into an EC2-based application is the long-term access key ID and secret access key, as they are required to access any other AWS service . For example, you might have something like the following code snippet embedded in your application that calls Amazon S3 to store or retrieve objects:

private static final String AWS_ACCESS_KEY_ID = "AKXXXXXXXXXXXXXXXXXXX";
private static final String AWS_SECRET_ACCESS_KEY = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";

private static AmazonS3Client createClient()
{
           BasicAWSCredentials credentials = new BasicAWSCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY);
           AmazonS3Client s3Client = new AmazonS3Client(credentials);
           return s3Client;
}

Instead of embedding long-term AWS credentials in your code, you can use the IAM Roles for EC2 feature to automatically get the credentials you need to access S3 at runtime. Temporary security credentials are securely made available on your EC2 host, and they’re automatically rotated for you periodically.  Below are step-by-step instructions to configure IAM Roles for EC2 for a use case where you need your application on EC2 to retrieve a configuration file called “xyz.properties” located in an S3 bucket under your account.

1. Create an IAM role with appropriate permissions

Follow the directions in the IAM user guide to create an AWS service role for EC2 that grants the necessary privileges.  To define the permissions for your application to retrieve the configuration file from S3, we’ve created a role called “XYZ-App-Fetch-Config” with the following policy attached to it:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:GetObject"
      ],
      "Sid": "Stmt0123456789",

      "Resource": [
        "arn:aws:s3:::<your S3 bucket name>/xyz.properties"
      ],
      "Effect": "Allow"
    }
  ]
}

In accordance with security best practice, this policy follows the principle of Least Privilege by granting only the minimal necessary set of permissions, as follows:

  • It specifically identifies the S3 object to be retrieved, the configuration file.
  • The policy only allows “GetObject.”  No S3 list or put permissions are required.
  • The policy itself is attached to the “XYZ-App-Fetch-Config” role that will be assumed by the EC2 instance running     your application. This lets you control which instances/applications get the permissions in this role.

2. Update Your Application to Use IAM Role

The best part about this step is that you only need to delete code!  There’s nothing to add; the SDK and EC2 handle the “muck” for you.  The initial code sample to call S3 shrinks down to:

private static final String AWS_ACCESS_KEY_ID = "AKXXXXXXXXXXXXXXXXXXX";
private static final String AWS_SECRET_ACCESS_KEY = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";

private static AmazonS3Client createClient()
{
BasicAWSCredentials credentials = new BasicAWSCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY);
AmazonS3Client s3Client = new AmazonS3Client(credentials);
return s3Client;
}

When you call S3 this way, the temporary security credentials that describe which EC2 instance has access and permission are retrieved automatically.  These temporary security credentials have an added benefit over hard-coded credentials in that they are only valid for a limited time period, and are automatically rotated.  If you’re interested in the technical details, have a look at the IAM Roles for EC2 documentation.

3.      Launch Your Application on EC2

Now it’s time to put the pieces together! Start your EC2 instance with the role you created earlier (our example is “XYZ-App-Fetch-Config”) by following the Launching an Instance with an IAM Role instructions.  Note that if you’re launching the EC2 instance as an IAM user (which we recommend), make sure that your user has IAM:PassRole permissions for the “XYZ-App-Fetch-Config” role.  Here’s a screenshot of the EC2 launch wizard where we specify the role:

Screenshot of ensuring that the user has IAM:PassRole permissions for the “XYZ-App-Fetch-Config” role

Upload your configuration file to S3, start your application, and watch it seamlessly pull your configuration file!

Finding hard-coded credentials in your code

Hopefully you’re excited about deploying credentials to EC2 that are automatically rotated.  Now that you’re using Roles, a good security practice would be to go through your code and remove any references to AKID/Secret.  We suggest running the following regular expressions against your code base:

  • Search for access key IDs: (?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9]).  In English, this regular expression says: Find me 20-character, uppercase, alphanumeric strings that don’t have any uppercase, alphanumeric characters immediately before or after.
  • Search for secret access keys: (?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=]).  In English, this regular expression says: Find me 40-character, base-64 strings that don’t have any base 64 characters immediately before or after.

If grep is your preferred tool, run a recursive, Perl-compatible search using the following commands:

grep -RP '(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])' *
grep -RP '(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])' *

We can’t guarantee these regular expressions will work forever (we reserve the right to change the format of access key IDs and secret access keys) but they’re a start.

Once you’ve found any hard-coded credentials, be sure to remove them from your code base and consider deleting or rotating them in IAM as you probably don’t know where they have been copied and who might be using them. You can do so safely by: (a) launching new EC2 instances with IAM roles; (b) once you’ve migrated your applications over to the new instances, shut down the old instances; and (c) deactivate the old hard-coded credentials from the Security Credentials page in the AWS Management Console.

Conclusion

IAM Roles for EC2 makes service-to-service integration easier to implement and more secure. To learn more, go to IAM Roles for EC2 documentation.

– Ben

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.