AWS Developer Blog

Secure Local Development with the ProfileCredentialsProvider

We’ve talked in the past about the importance of secure credentials management. When your application is running in production, IAM roles for Amazon EC2 are a great way to securely deliver AWS credentials to your application. However, they’re by definition available only when your application is running on EC2 instances.

If you’re a developer making changes to an application, it’s often convenient to be able to fire up a local instance of the application to see your changes in action without having to spin up a full test environment in the cloud. If your application uses IAM roles for EC2 to pick up credentials when running in the cloud, this means you’ll need an additional way of injecting credentials when running locally on a developer’s box. It’s tempting to simply hardcode a set of credentials into the application for testing purposes, but this makes it distressingly easy to accidentally check those credentials in to source control.

The AWS SDK for Java includes a number of different credential providers that you can use as alternatives to hardcoded credentials. You can easily inject credentials into your application from system properties, environment variables, properties files, and more. All of these choices allow you to keep your credentials separate from your source code and reduce the risk of accidentally checking them in.

We’ve recently added a new credentials provider that loads credentials from a credentials profile file stored in your home directory. This option is particularly exciting because other tools like the AWS CLI and the AWS Toolkit for Eclipse also support reading credentials from and writing credentials to this file. You can configure your credentials in one place, and reuse them whether you’re running one-off CLI commands to check on the state of your resources, browsing around using the Toolkit, or running a local instance of one of your applications.

The default credentials profile file is located at System.getProperty("user.home") + ".aws/credentials". The format allows you to define multiple “profiles,” which makes it easy to maintain different sets of credentials for different projects with appropriately-scoped permissions; this way you don’t have to worry about a bug in the local version of your application accidentally wiping out your production system. Here’s a simple example:

  # Credentials for App-1's production stack (allowing only read-only
  # access for debugging production issues).
  [app-1-production]
  aws_access_key_id={access key id}
  aws_secret_access_key={secret access key}
  aws_session_token={optional session token}

  # Credentials for App-1's development stack, allowing full read-write
  # access.
  [app-1-development]
  aws_access_key_id={another access key id}
  aws_secret_access_key={another secret access key}

  # Default credentials to be used if no profile is specified.
  [default]
  aws_access_key_id=...
  aws_secret_access_key=...

If you’re running a recent version of the AWS CLI, you can set up a file in the correct format by running the aws configure command; you’ll be prompted to enter a set of credentials, which will be stored in the file. Similarly, if you’re running a recent version of the AWS Toolkit for Eclipse, any credentials you configure through its Preferences page will be written into the credentials profile file.

The AWS Toolkit for Eclipse Preferences Page

To use the ProfileCredentialsProvider when running local integration tests, simply add it to your credentials provider chain:

AmazonDynamoDBClient client = new AmazonDynamoDBClient(
      new AWSCredentialsProviderChain(

          // First we'll check for EC2 instance profile credentials.
          new InstanceProfileCredentialsProvider(),

          // If we're not on an EC2 instance, fall back to checking for
          // credentials in the local credentials profile file.
          new ProfileCredentialsProvider("app-1-development"));

The constructor parameter is the name of the profile to use; if you call the parameterless constructor, it will load the “default” profile. Another constructor overload allows you to override the location of the profiles file to load credentials from (or you can change this by setting the AWS_CREDENTIALS_PROFILES_FILE environment variable).

Have you already started using the new ProfileCredentialsProvider? Let us know what you think in the comments below!