Tag: Credentials


Referencing Credentials using Profiles

There are a number of ways to provide AWS credentials to your .NET applications. One approach is to embed your credentials in the appSettings sections of your App.config file. While this is easy and convenient, your AWS credentials might end up getting checked into source control or published to places that you didn’t mean. A better approach is to use profiles, which was introduced in version 2.1 of the AWS SDK for .NET. Profiles offer an easy-to-use mechanism to safely store credentials in a central location outside your application directory. After setting up your credential profiles once, you can refer to them by name in all of the applications you run on that machine. The App.config file will look similar to this example when using profiles.

<configuration>
   <appSettings>
      <add key="AWSProfileName" value="development"/>
      <add key="AWSRegion" value="us-west-2" />
   </appSettings>
</configuration>

The SDK supports two different profile stores. The first is what we call the SDK store which stores the profiles encrypted in the C:Users<username>AppDataLocalAWSToolkit folder. This is the same store used by the AWS Toolkit for Visual Studio and AWS Tools for PowerShell. The second store is the credentials file under c:Users<username>.aws. The credentials file is used by the other AWS SDKs and AWS Command Line Interface. The SDK will always check the SDK store first and then fallback to the credentials file.

Setting up Profiles with Visual Studio

The Visual Studio Toolkit lists all the profiles registered in the SDK store in the AWS Explorer. To add new profiles click the New Account Profile button.

When you create a new project in Visual Studio using one of the AWS project templates the project wizard will allow you to pick an existing profile or create a new profile. The selected profile will be referenced in the App.config of the new project.

 

Setting up Profiles with PowerShell

Profiles can also be setup using the AWS Tools for Windows PowerShell.

PS C:> Set-AWSCredentials -AccessKey 123MYACCESSKEY -SecretKey 456SECRETKEY -StoreAs development

Like the Toolkit these credentials will be accessible to the SDK and Toolkit after running this command. To use the profile in PowerShell run the following command before using AWS cmdlets.

PS C:> Set-AWSCredentials -ProfileName development

Setting up Profiles with the SDK

Profiles can also be managed using just the AWS SDK for .NET using the Amazon.Util.ProfileManager class. Here is how you can register a profile using the ProfileManager.

Amazon.Util.ProfileManager.RegisterProfile(profileName, accessKey, secretKey)

You can also list the registered profiles and unregistered profiles using the ListProfileNames and UnregisterProfile methods.

Getting the SDK from Nuget

If you get the SDK from NuGet the package’s install script will add an empty AWSProfileName tag to the App.config file if the app setting doesn’t already exist. You can use any of the already mentioned methods for registering profiles. Alternatively, you can use the PowerShell script account-management.ps1 that comes with the NuGet package and will be placed in /packages/AWSSDK-X.X.X.X/tools/ folder. This is an interactive script that will let you register, list and unregister profiles.

Credentials File Format

The previous methods for adding profiles have all been about adding credentials to the SDK store. To put credentials in the SDK store requires using one of these tools because the credentials are encrypted. The alternative is to use the credentials file. This is a plain text file similar to a .ini file. Here is an example of a credentials file with two profiles.

[default]
aws_access_key_id = <access-key>
aws_secret_access_key = <secret-key>

[development]
aws_access_key_id = <access-key>
aws_secret_access_key = <secret-key>

Default Profile

When you create a service client without specifying credentials or profile name the SDK will search for a default profile. The default profile’s name is "default" and it will first be searched for in the SDK store and then the credentials file. When the AWS Tools for PowerShell was released last year it introduced a default profile called "AWS PS Default". To make all of our tools have a consistent experience, we have changed AWS Tools for PowerShell to now use "default" for the default. To make sure we didn’t break any existing users, the AWS Tools for PowerShell will still try to load the old profile ("AWS PS Default") when "default" is not found, but will now save credentials to "default" profile unless otherwise specified.

Credentials Search Path

If an application is creating a service client without specifying credentials then the SDK uses the following order to find credentials.

  • Look for AWSAccessKey and AWSSecretKey in App.config.

    • Important to note that the 2.1 version of the SDK didn’t break any existing applications using the AWSAccessKey and AWSSecretKey app settings.
  • Search the SDK Store

    • If the AWSProfileName exists then see if this profile exists. If no AWSProfileName is specified look for the default profile called "default" in the SDK Store.
  • Search the credentials file

    • If the AWSProfileName exists then see if this profile exists. If no AWSProfileName is specified look for the default profile called "default" in the credentials file.
  • Search for Instance Profiles

    • These are credentials that can be found on EC2 instance that were created with instance profiles.

Setting Profile in Code

It is also possible to specify the profile to use in code, in addition to using App.config. This code shows how to create an Amazon S3 client for the development profile.

Amazon.Runtime.AWSCredentials credentials = new Amazon.Runtime.StoredProfileAWSCredentials("development");
Amazon.S3.IAmazonS3 s3Client = new AmazonS3Client(credentials, Amazon.RegionEndpoint.USWest2);

Alternative Credentials File

Both the SDK store and the credentials file are located under the current user’s home directory. If your application is running under a different user – such as Local System – then the AWSProfilesLocation app setting can be set to use an alternative credentials file. For example, this App.Config tells the SDK to look for credentials in the C:aws_service_credentialscredentials file.

<configuration>
   <appSettings>
      <add key="AWSProfileName" value="development"/>
      <add key="AWSProfilesLocation" value="C:aws_service_credentialscredentials"/>
      <add key="AWSRegion" value="us-west-2" />
   </appSettings>
</configuration>

Using Credentials from AWS Security Token Service

by Jeremy Lindblom | on | in PHP | Permalink | Comments |  Share

A recent post on the AWS PHP Development forum inspired me to write a quick post about how to use credentials vended by AWS Security Token Service with the AWS SDK for PHP.

What is AWS Security Token Service?

AWS Security Token Service (AWS STS) is a web service that enables you to request temporary, limited-privilege AWS credentials for AWS Identity and Access Management (AWS IAM) users or for users that you authenticate via identity federation. One common use case for using temporary credentials is to grant mobile or client-side applications access to AWS resources by authenticating users through third-party identity providers (read more about Web Identity Federation).

Getting Temporary Credentials

AWS STS has five operations that return temporary credentials: AssumeRole, AssumeRoleWithWebIdentity, AssumeRoleWithSAML (recently added), GetFederationToken, and GetSessionToken. Using the GetSessionToken operation is easy, so let’s use that one as an example. Assuming you have an instance of AwsStsStsClient stored in the $sts variable, this is how you call the method:

$result = $sts->getSessionToken();

See? I told you it was easy. The result for GetSessionToken and the other AWS STS operations always contains a 'Credentials' value. If you print the result (e.g., print_r($result)), it looks like the following:

Array
(
    ...
    [Credentials] => Array
    (
        [SessionToken] => '<base64 encoded session token value>'
        [SecretAccessKey] => '<temporary secret access key value>'
        [Expiration] => 2013-11-01T01:57:52Z
        [AccessKeyId] => '<temporary access key value>'
    )
    ...
)

Using Temporary Credentials

You can use temporary credentials with another AWS client by instantiating the client and passing in the values received from AWS STS directly.

use AwsS3S3Client;

$result = $sts->getSessionToken();

$s3 = S3Client::factory(array(
    'key'    => $result['Credentials']['AccessKeyId'],
    'secret' => $result['Credentials']['SecretAccessKey'],
    'token'  => $result['Credentials']['SessionToken'],
));

You can also construct a Credentials object and use that when instantiating the client.

use AwsCommonCredentialsCredentials;
use AwsS3S3Client;

$result = $sts->getSessionToken();

$credentials = new Credentials(
    $result['Credentials']['AccessKeyId'],
    $result['Credentials']['SecretAccessKey'],
    $result['Credentials']['SessionToken']
);

$s3 = S3Client::factory(array('credentials' => $credentials));

However, the best way to provide temporary credentials is to use the createCredentials() helper method included with StsClient. This method extracts the data from an AWS STS result and creates the Credentials object for you.

$result = $sts->getSessionToken();
$credentials = $sts->createCredentials($result);

$s3 = S3Client::factory(array('credentials' => $credentials));

You can also use the same technique when setting credentials on an existing client object.

$credentials = $sts->createCredentials($sts->getSessionToken());
$s3->setCredentials($credentials);

Closing Notes

For information about why you might need to use temporary credentials in your application or project, see Scenarios for Granting Temporary Access in the AWS STS documentation.

If you would like to read more about providing credentials to the SDK, check out one of our other blog posts: Providing Credentials to the AWS SDK for PHP.

Providing credentials to the AWS SDK for PHP

by Michael Dowling | on | in PHP | Permalink | Comments |  Share

In order to authenticate requests, the AWS SDK for PHP requires credentials in the form of an AWS access key ID and secret access key. In this post, we’ll discuss how to configure credentials in the AWS SDK for SDK.

Configuring credentials

There are several methods that can be used for configuring credentials in the SDK. The method that you use to supply credentials to your application is up to you, but we recommend that you use IAM roles when running on Amazon EC2 or use environment variables when running elsewhere.

Credentials can be specified in several ways:

  1. IAM roles (Amazon EC2 only)
  2. Environment variables
  3. Configuration file and the service builder
  4. Passing credentials into a client factory method

If you do not provide credentials to the SDK using a factory method or a service builder configuration file, the SDK checks if the AWS_ACCESS_KEY_ID and AWS_SECRET_KEY environment variables are present. If defined, these values are used as your credentials. If these environment variables are not found, the SDK attempts to retrieve IAM role credentials from an Amazon EC2 instance metadata server. If your application is running on Amazon EC2 and the instance metadata server responds successfully with credentials, they are used to authenticate requests. If none of the above methods successfully yield credentials, an AwsCommonExceptionInstanceProfileCredentialsException exception is thrown.

IAM roles (Amazon EC2 only)

IAM roles are the preferred method for providing credentials to applications running on Amazon EC2. IAM roles remove the need to worry about credential management from your application. They allow an instance to "assume" a role by retrieving temporary credentials from the instance’s metadata server. These temporary credentials allow access to the actions and resources that the role’s policy allows.

When launching an EC2 instance, you can choose to associate it with an IAM role. Any application running on that EC2 instance is then allowed to assume the associated role. Amazon EC2 handles all the legwork of securely authenticating instances to the IAM service to assume the role and periodically refreshing the retrieved role credentials, keeping your application secure with almost no work on your part.

If you do not provide credentials and no environment variable credentials available, the SDK attempts to retrieve IAM role credentials from an Amazon EC2 instance metadata server. These credentials are available only when running on Amazon EC2 instances that have been configured with an IAM role.

Caching IAM role credentials

While using IAM role credentials is the preferred method for providing credentials to an application running on an Amazon EC2 instance, the roundtrip from the application to the instance metadata server on each request can introduce latency. In these situations, you might find that utilizing a caching layer on top of your IAM role credentials can eliminate the introduced latency.

The easiest way to add a cache to your IAM role credentials is to specify a credentials cache using the credentials.cache option in a client’s factory method or in a service builder configuration file. The credentials.cache configuration setting should be set to an object that implements Guzzle’s GuzzleCacheCacheAdapterInterface. This interface provides an abstraction layer over various cache backends, including Doctrine Cache, Zend Framework 2 cache, etc.

<?php

require 'vendor/autoload.php';

use DoctrineCommonCacheFilesystemCache;
use GuzzleCacheDoctrineCacheAdapter;

// Create a cache adapter that stores data on the filesystem
$cacheAdapter = new DoctrineCacheAdapter(new FilesystemCache('/tmp/cache'));

// Provide a credentials.cache to cache credentials to the file system
$s3 = AwsS3S3Client::factory(array(
    'credentials.cache' => $cacheAdapter
));

With the addition of credentials.cache, credentials are now cached to the local filesystem using Doctrine’s caching system. Every request that uses this cache adapter first checks if the credentials are in the cache. If the credentials are found in the cache, the client then ensures that the credentials are not expired. In the event that cached credentials become expired, the client automatically refreshes the credentials on the next request and populates the cache with the updated credentials.

A credentials cache can also be used in a service builder configuration:

<?php

// File saved as /path/to/custom/config.php

use DoctrineCommonCacheFilesystemCache;
use GuzzleCacheDoctrineCacheAdapter;

$cacheAdapter = new DoctrineCacheAdapter(new FilesystemCache('/tmp/cache'));

return array(
    'includes' => array('_aws'),
    'services' => array(
        'default_settings' => array(
            'params' => array(
                'credentials.cache' => $cacheAdapter
            )
        )
    )
);

If you were to use the above configuration file with a service builder, then all of the clients created through the service builder would utilize a shared credentials cache object.

Environment variables

If you do not provide credentials to a client’s factory method or via a service builder configuration, the SDK attempts to find credentials in your environment by checking in the $_SERVER superglobal and using the getenv() function, looking for the AWS_ACCESS_KEY_ID and AWS_SECRET_KEY environment variables.

If you are hosting your application on AWS Elastic Beanstalk, you can set the AWS_ACCESS_KEY_ID and AWS_SECRET_KEY environment variables through the AWS Elastic Beanstalk console so that the SDK can use those credentials automatically.

Configuration file and the service builder

The SDK provides a service builder that can be used to share configuration values across multiple clients. The service builder allows you to specify default configuration values (e.g., credentials and regions) that are applied to every client. The service builder is configured using either JSON configuration files or PHP scripts that return an array.

Here’s an example of a configuration script that returns an array of configuration data that can be used by the service builder:

<?php

// File saved as /path/to/custom/config.php

return array(
    // Bootstrap the configuration file with AWS specific features
    'includes' => array('_aws'),
    'services' => array(
        // All AWS clients extend from 'default_settings'. Here we are
        // overriding 'default_settings' with our default credentials and
        // providing a default region setting.
        'default_settings' => array(
            'params' => array(
                'key'    => 'your-aws-access-key-id',
                'secret' => 'your-aws-secret-access-key',
                'region' => 'us-west-1'
            )
        )
    )
);

After creating and saving the configuration file, you need to instantiate a service builder.

<?php

// Assuming the SDK was installed via Composer
require 'vendor/autoload.php';

use AwsCommonAws;

// Create the AWS service builder, providing the path to the config file
$aws = Aws::factory('/path/to/custom/config.php');

At this point, you can now create clients using the get() method of the Aws object:

$s3 = $aws->get('s3');

Passing credentials into a factory method

A simple way to specify your credentials is by injecting them directly into the factory method of a client. This is useful for quick scripting, but be careful to not hard-code your credentials inside of your applications. Hard-coding your credentials inside of an application can be dangerous because it is easy to commit your credentials into an SCM repository, potentially exposing your credentials to more people than intended. It can also make it difficult to rotate credentials in the future.

<?php

$s3 = AwsS3S3Client::factory(array(
    'key'    => 'my-access-key-id',
    'secret' => 'my-secret-access-key'
));

IAM Roles for Amazon EC2 Instances (Credential Management Part 4)

by Trevor Rowe | on | in Ruby | Permalink | Comments |  Share

This is the fourth and final part (part 1, part 2, part 3) in a series on how to securely manage your AWS access credentials.

This week I am focusing on using AWS Identity and Access Management (IAM) roles for Amazon EC2 instances with the AWS SDK for Ruby (aws-sdk). Simply put, IAM roles for EC2 instances remove the need to try to bootstrap your instances with credentials. Example:

# look ma! No credentials (when run from EC2)!
require 'aws-sdk'
AWS::S3.new.buckets['my-bucket'].objects.map(&:keys)

You can stop worrying about how to get credentials onto a box that Auto Scaling just spun-up on your behalf. Your cron scripts on instances no longer have to search around for credentials on disk or worry about when they get rotated.

One of the best features of IAM roles for EC2 instances is the credentials on EC2 are auto-rotated! Instances started with an IAM instance profile will get temporary credentials deployed on a regular basis to the EC2 instance metadata service.

My favorite feature? The aws-sdk gem just works when running on an instance with an IAM profile.

How it Works

  • You create an IAM instance profile
  • Start one or more instances, with the instance profile
  • Upon instance boot, session credentials will be available on your instance(s)
  • Credentials are rotated regularly (before they expire)

You can reuse an instance profile as many times as you like. The aws-sdk gem will automatically attempt to load credentials from the metadata service when no other credentials are provided.

Create an Instance Profile with the aws-sdk Gem

An instance profile consists of a role. The role consists of a policy. Each of these has a name. I am going to use the aws-sdk to create a sample profile starting with the policy.

For this example, I’ll be building an instance profile that has limited permissions. I only want applications on EC2 to be able to read from Amazon S3 (list and get buckets/objects). First, I need to build the policy.

require 'aws-sdk'

AWS.config(:access_key_id => '...', :secret_access_key => '…')

# the role, policy and profile all have names, pick something descriptive
role_name = 's3-read-only'
policy_name = 's3-read-only'
profile_name = 's3-read-only'

# required so that Amazon EC2 can generate session credentials on your behalf
assume_role_policy_document = '{"Version":"2008-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]}'

# build a custom policy    
policy = AWS::IAM::Policy.new
policy.allow(:actions => ["s3:Get*","s3:List*"], :resources => '*')

Now that I have a policy built, I am going to build a role and add the policy to the role. I am going to use the policy and role names I chose above.

iam = AWS::IAM.new

# create the role
iam.client.create_role(
  :role_name => role_name,
  :assume_role_policy_document => assume_role_policy_document)

# add the policy to role
iam.client.put_role_policy(
  :role_name => role_name,
  :policy_name => policy_name,
  :policy_document => policy.to_json)

Last step is to create a profile for your role.

resp = iam.client.create_instance_profile(
  :instance_profile_name => instance_profile_name)

# this may be handy later
profile_arn = resp[:instance_profile][:arn]

iam.client.add_role_to_instance_profile(
  :instance_profile_name => instance_profile_name,
  :role_name => role_name)

Using an IAM Instance Profile

You can now use the instance profile name (or ARN we captured above) to run instances with your special profile.

# you can use the profile name or ARN as the :iam_instance_profile option
ec2 = AWS::EC2.new
ec2.instances.create(:image_id => "ami-12345678", :iam_instance_profile => profile_name)

Thats it! Your new instance will boot with session credentials available that the aws-sdk can consume with zero configuration. Happy computing!

Credential Providers (Credential Management Part 3)

by Trevor Rowe | on | in Ruby | Permalink | Comments |  Share

In part 1 of this series, I wrote about how to configure your access credentials with the AWS SDK for Ruby (aws-sdk gem). In part 2 we learned how to rotate your access credentials using the aws-sdk gem.

This week we explore credential providers and how they can help you keep your secrets safe and fresh.

Credential Providers

A credential provider is an object that responds to the following methods:

  • #access_key_id
  • #secret_access_key
  • #session_token
  • #refresh

Internally, the aws-sdk gem uses a chain of credential providers to load credentials from various locations including:

  • AWS.config
  • ENV (from multiple key prefixes)
  • EC2 instance metadata service

You can fully customize this behavior by configuring your own custom credential provider, as follows.

AWS.config(:credential_provider => CustomCredentialProvider.new)

Why Use a Custom Credential Provider?

In the previous post in this series we discussed rotating credentials. It can be painful to build logic that restarts processes or applications that are using stale or soon-to-be removed/expired credentials.

If your application uses a custom credential provider, the application does not need to be restarted. The SDK automatically calls #refresh on the credential provider when it receives a response from AWS that indicates its credentials are expired.

In-house hosted applications and utility scripts can use a custom provider to load credentials from a simple web service that vends current credentials. This web service could even go as far as vending session credentials that auto-expire and are limited to specific AWS operations. This greatly reduces exposure if these credentials are ever leaked.

Build a Custom Credential Provider

Here is a really simple custom credential provider that makes a HTTPS request to https://internal.domain/ and expects a JSON response of credentials.

require 'net/https'

class CustomCredentialProvider

  include AWS::Core::CredentialProviders::Provider

  private

  def get_credentials
    begin
      http = Net::HTTP.new('internal.domain', 443)
      http.use_ssl = true
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
      response = http.request(Net::HTTP::Get.new('/'))

      # symbolize keys to :access_key_id, :secret_access_key
      if response.code == '200'
        JSON.load(response.body).inject({}) {|h,(k,v)| h.merge(k.to_sym => v) }
      else
        {}
      end
    rescue
      {}
    end
  end

end

The include statement in the example above does much of the heavy lifting. It defines all of the public methods required for a credential provider. It also caches the credentials until #refresh is called. We only have to define #get_credentials and return a hash with symbol keys (or an empty hash if we fail).

You can make this example more robust if you:

  • Set network timeouts
  • Rescue Exceptions raised by HTTP that do not extend StandardError
  • Add basic retry logic to handle transient network errors

In the next (and last) post in this series I will explore how the aws-sdk gem uses the EC2 metadata service.

Rotating Credentials (Credential Management Part 2)

by Trevor Rowe | on | in Ruby | Permalink | Comments |  Share

In a previous blog post I wrote about ways to securely configure your AWS access credentials when using the aws-sdk gem. This week I want to talk about a security best practice, credential rotation.

Did you know that AWS recommends that you rotate your access keys every 90 days?

Even if you are very careful with your AWS access credentials, you may find yourself in a situation where someone has gained access to your secrets. If you build your applications with a regular key rotation solution, then an out-of-bounds replacement of keys can be painless. In the heat of the moment when you are scrambling to replace compromised keys, this can be a life saver.

Rotating Credentials

The process for rotating credentials boils down to the following steps:

  • Generate new keys
  • Securely distribute keys to your applications
  • Ensure the applications refresh their keys
  • Disable the old access keys
  • Ensure everything still works
  • Delete the old access keys

For best effect, you should automate this process. If you have to do it by hand, the process will be much more error prone and you will likely do it less often. You can use the aws-sdk gem to do much of the work for you.

This simple example demonstrates how to generate a new key pair, disable old keys and then eventually delete the old keys. I inserted placeholders for where you should distribute your new keys and refresh your applications with the new keys.

iam = AWS::IAM.new

# create new set of access credentials
new_keys = iam.access_keys.create

# you should persist the new key pair somewhere secure to start with
new_keys.id # access key id
new_keys.secret # secret access key

## deploy the new keys to your applications now, make
## sure they pick up the new keys

# deactivate the old keys
old_keys = iam.access_keys['AKID12346789…'] # old access key id
old_keys.deactivate!

## the old keys still exist, they are temporarily disabled, use
## this time to test your applications to ensure they are working

# if you are confident your applications are using the new keys
# you can then safely delete the old key pair
old_keys.delete

How you distribute your keys and refresh your application is going to be very specific to your own needs. Just be certain to test your applications before you delete your disabled keys. You can not restore them once they have been deleted.

For the next post in this series, I will write about credential providers and how the aws-sdk makes it easy for your applications to pick up new credentials without restarts or downtime. This can be very useful when you are rotating credentials.

Credential Management – Part 1

by Trevor Rowe | on | in Ruby | Permalink | Comments |  Share

When using AWS, it is important to keep your access credentials secure. It can be challenging to make your credentials available to your application securely. The AWS SDK for Ruby provides a number of helpful interfaces for configuring your credentials that help you keep your secrets safe.

This blog post focuses on securely configuring the aws-sdk gem with your credentials. I will follow up with additional blog posts about rotating credentials, and using roles for instances.

Credential Configuration

The aws-sdk gem requires that you provide your access credentials before making a request. The gem tries to locate your credentials in a number of default locations. If it is unable to find your credentials, it raises an error. The locations it searches are:

  • AWS.config
  • ENV
  • EC2 instance metadata
  • Rails Configuration (RAILS_ROOT/config/aws.yml)

AWS.config

You can use AWS.config to statically configure your credentials for all AWS requests. Simply call AWS.config with your :access_key_id and :secret_access_key (you may also provide a :session_token).

require 'aws-sdk'

AWS.config(:access_key_id => '...', :secret_access_key => '...')

Alternatively, you may provide credentials directly to the service interfaces. This can be helpful if you are working with multiple sets of credentials for multiple AWS accounts (or IAM users).

s3 = AWS::S3.new(:access_key_id => '...', :secret_access_key => '...')    

As tempting as it might be, you should never put access credentials in source code. This makes your secrets available to anyone with access to your source code. It also creates a maintenance burden when you need to rotate your credentials. There are many alternatives, including loading credentials from a configuration file that is not tracked with source control.

require 'aws-sdk'
require 'yaml'

# configure aws-sdk gem from a yaml configuration file
AWS.config(YAML.load_file(path_to_configuration_file))

In the preceding example, the YAML file might look like this:

:access_key_id: 'YOUR_ACCESS_KEY_ID'
:secret_access_key: 'YOUR_SECRET_ACCESS_KEY'

ENV

You can alternatively provide credentials to your application via ENV. By default, the aws-sdk gem searches ENV using two different prefixes for your keys (‘AWS’ and ‘AMAZON’).

ENV['AWS_ACCESS_KEY_ID']
ENV['AWS_SECRET_ACCESS_KEY']
ENV['AWS_SESSION_TOKEN']

EC2 Instance Metadata

The aws-sdk gem supports loading credentials from the instance metadata service on Amazon EC2 instances. If you have started your instance using an AWS IAM instance profile, this will just work, no configuration required. I will dive into this deeper in a followup blog post.

Credential Loading in Rails (RAILS_ROOT/config/aws.yml)

If you are using the aws-sdk gem in a Rails application, the gem attempts to load credentials from RAILS_ROOT/config/aws.yml. This file is ERB-parsed and then loaded by YAML. This file should be formatted in the same way as RAILS_ROOT/config/database.yml. It should have one top-level entry for the Rails.env you are running.

# RAILS_ROOT/config/aws.yml
development:
  access_key_id: DEV_ACCESS_KEY_ID
  secret_access_key: DEV_ACCESS_KEY_ID

If this file contains your secrets in plain text and does not use ERB to load them securely, you should not track this file with source control.

You can now read part two in this series: Rotating Credentials.