Providing Credentials to the SDK
================================

Introduction
------------

In order to authenticate requests, AWS services require you to provide your `AWS access keys
<http://aws.amazon.com/developers/access-keys/>`_, also known as your AWS **access key ID** and **secret access key**.
In the AWS SDK for PHP, these access keys are often referred to collectively as your **credentials**. This guide
demonstrates how to provide your credentials to the AWS SDK for SDK.

There are many ways to provide credentials:

#. :ref:`environment_credentials`
#. :ref:`instance_profile_credentials`
#. :ref:`credential_profiles`
#. :ref:`configuration_credentials`
#. :ref:`factory_credentials`
#. :ref:`set_credentials`
#. :ref:`temporary_credentials`

Which technique should you choose?
----------------------------------

The technique that you use to provide credentials to the SDK for your application is entirely up to you. Please read
each section on this page to determine what is the best fit for you. What you choose will depend on many different
factors, including:

* The environment you are operating in (e.g., development, testing, production)
* The host of your application (e.g., localhost, Amazon EC2, third-party server)
* How many sets of credentials you are using
* The type of project you are developing (e.g., application, CLI, library)
* How often you rotate your credentials
* If you rely on temporary or federated credentials
* Your deployment process
* Your application framework

Regardless of the technique used, it is encouraged that you follow the `IAM Best Practices
<http://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPractices.html>`_ when managing your credentials, including the
recommendation to not use your AWS account's root credentials. Instead, create separate IAM users with their own access
keys for each project, and tailor the permissions of the users specific to those projects.

*In general, it is recommended that you use IAM roles when running your application on Amazon EC2 and use credential
profiles or environment variables elsewhere.*

.. _environment_credentials:

Using credentials from environment variables
--------------------------------------------

If you do not provide credentials to a client object at the time of its instantiation (e.g., via the client's factory
method or via a service builder configuration), the SDK will attempt to find credentials in your environment when you
call your first operation. The SDK will use the ``$_SERVER`` superglobal and/or ``getenv()`` function to look for the
``AWS_ACCESS_KEY_ID`` and ``AWS_SECRET_ACCESS_KEY`` environment variables. These credentials are referred to as
**environment credentials**.

.. _instance_profile_credentials:

Using IAM roles for Amazon EC2 instances
----------------------------------------

*Using IAM roles is the preferred technique 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 EC2 instance's metadata server. These temporary credentials, often referred to
as **instance profile 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 explicitly provide credentials to the client object and no environment variable credentials are available,
the SDK attempts to retrieve instance profile 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.

.. note::

    Instance profile credentials and other temporary credentials generated by the AWS Security Token Service (AWS STS)
    are not supported by every service. Please check if the service you are using supports temporary credentials by
    reading `AWS Services that Support AWS STS <http://docs.aws.amazon.com/STS/latest/UsingSTS/UsingTokens.html>`_.

For more information, see `IAM Roles for Amazon EC2 <http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html>`_.

.. _caching_credentials:

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
``Guzzle\Cache\CacheAdapterInterface`` (see `Guzzle cache adapters
<http://docs.guzzlephp.org/en/latest/plugins/cache-plugin.html#cache-adapters>`_). This interface provides an
abstraction layer over various cache backends, including Doctrine Cache, Zend Framework 2 cache, etc.

.. code-block:: php

    <?php

    require 'vendor/autoload.php';

    use Doctrine\Common\Cache\FilesystemCache;
    use Guzzle\Cache\DoctrineCacheAdapter;

    // 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
    $s3Client = Aws\S3\S3Client::factory(array(
        'credentials.cache' => $cacheAdapter
    ));

In the preceding example, the addition of ``credentials.cache`` causes credentials to be cached to the local filesystem
using `Doctrine's caching system <https://github.com/doctrine/cache>`_. 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:

.. code-block:: php

    <?php

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

    use Doctrine\Common\Cache\FilesystemCache;
    use Guzzle\Cache\DoctrineCacheAdapter;

    $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.

.. _credential_profiles:

Using the AWS credentials file and credential profiles
------------------------------------------------------

Starting with the AWS SDK for PHP version 2.6.2, you can use an AWS credentials file to specify your credentials. This
is a special, INI-formatted file stored under your HOME directory, and is a good way to manage credentials for your
development environment. The file should be placed at ``~/.aws/credentials``, where ``~`` represents your HOME
directory.

Using an AWS credentials file offers a few benefits:

1. Your projects' credentials are stored outside of your projects, so there is no chance of accidentally committing
   them into version control.
2. You can define and name multiple sets of credentials in one place.
3. You can easily reuse the same credentials between projects.
4. Other AWS SDKs and tools support, or will soon support, this same credentials file. This allows you to reuse your
   credentials with other tools.

The format of the AWS credentials file should look something like the following:

.. code-block:: ini

    [default]
    aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID
    aws_secret_access_key = YOUR_AWS_SECRET_ACCESS_KEY

    [project1]
    aws_access_key_id = ANOTHER_AWS_ACCESS_KEY_ID
    aws_secret_access_key = ANOTHER_AWS_SECRET_ACCESS_KEY

Each section (e.g., ``[default]``, ``[project1]``), represents a separate credential **profile**. Profiles can be
referenced from an SDK configuration file, or when you are instantiating a client, using the ``profile`` option:

.. code-block:: php

    <?php

    use Aws\DynamoDb\DynamoDbClient;

    // Instantiate a client with the credentials from the project1 profile
    $dynamoDbClient = DynamoDbClient::factory(array(
        'profile' => 'project1',
        'region'  => 'us-west-2',
    ));

If no credentials or profiles were explicitly provided to the SDK and no credentials were defined in environment
variables, but a credentials file is defined, the SDK will use the "default" profile. You can change the default
profile by specifying an alternate profile name in the ``AWS_PROFILE`` environment variable.

.. _hardcoded_credentials:

Setting credentials explicitly in your code
-------------------------------------------

The SDK allows you to explicitly set your credentials in your project in a few different ways. These techniques are
useful for rapid development, integrating with existing configurations systems (e.g., your PHP framework of choice), and
using :ref:`temporary credentials <temporary_credentials>`. However, **be careful to not hard-code your credentials**
inside of your applications. Hard-coding your credentials can be dangerous, because it is easy to accidentally 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.

.. _configuration_credentials:

Using a configuration file with 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 used by every
client. The service builder is configured using either JSON configuration files or PHP scripts that return an array.

The following is an example of a configuration script that returns an array of configuration data that can be used by
the service builder:

.. code-block:: php

    <?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.

.. code-block:: php

    <?php

    use Aws\Common\Aws;

    // 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:

.. code-block:: php

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

.. _factory_credentials:

Passing credentials into a client factory method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A simple way to specify your credentials is by injecting them directly into the factory method when instantiating the
client object.

.. code-block:: php

    <?php

    use Aws\S3\S3Client;

    // Instantiate the S3 client with your AWS credentials
    $s3Client = S3Client::factory(array(
        'key'    => 'YOUR_AWS_ACCESS_KEY_ID',
        'secret' => 'YOUR_AWS_SECRET_ACCESS_KEY',
    ));

In some cases, you may already have an instance of a ``Credentials`` object. You can use this instead of specifying your
access keys separately.

.. code-block:: php

    <?php

    use Aws\S3\S3Client;
    use Aws\Common\Credentials\Credentials;

    $credentials = new Credentials('YOUR_ACCESS_KEY', 'YOUR_SECRET_KEY');

    // Instantiate the S3 client with your AWS credentials
    $s3Client = S3Client::factory(array(
        'credentials' => $credentials
    ));

You may also want to read the section in the Getting Started Guide about
:ref:`using a client's factory method <client_factory_method>` for more details.

.. _set_credentials:

Setting credentials after instantiation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

At any time after instantiating the client, you can set the credentials the client should use with the
``setCredentials()`` method.

.. code-block:: php

    <?php

    use Aws\S3\S3Client;
    use Aws\Common\Credentials\Credentials

    $s3Client = S3Client::factory();

    $credentials = new Credentials('YOUR_ACCESS_KEY', 'YOUR_SECRET_KEY');
    $s3Client->setCredentials($credentials);

This can be used to change the credentials, set temporary credentials, refresh expired credentials, etc.

Using the ``setCredentials()`` method will also trigger a ``client.credentials_changed`` event, so you can program other
parts of your application to react to the change. To do this, you just need to add a listener to the client object.

.. code-block:: php

    use Aws\S3\S3Client;
    use Aws\Common\Credentials\Credentials

    // Create 2 sets of credentials
    $credentials1 = new Credentials('ACCESS_KEY_1', 'SECRET_KEY_1');
    $credentials2 = new Credentials('ACCESS_KEY_2', 'SECRET_KEY_2');

    // Instantiate the client with the first credential set
    $s3Client = S3Client::factory(array('credentials' => $credentials1));

    // Get the event dispatcher and register a listener for the credential change
    $dispatcher = $s3Client->getEventDispatcher();
    $dispatcher->addListener('client.credentials_changed', function ($event) {
        $formerAccessKey = $event['former_credentials']->getAccessKey();
        $currentAccessKey = $event['credentials']->getAccessKey();
        echo "Access key has changed from {$formerAccessKey} to {$currentAccessKey}.\n";
    });

    // Change the credentials to the second set to trigger the event
    $s3Client->setCredentials($credentials2);
    //> Access key has changed from ACCESS_KEY_1 to ACCESS_KEY_2.

.. _temporary_credentials:

Using temporary credentials from AWS STS
----------------------------------------

`AWS Security Token Service <http://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html>`_ (AWS STS) enables you to
request limited-privilege, **temporary credentials** for 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
<http://docs.aws.amazon.com/STS/latest/UsingSTS/CreatingWIF.html>`_).

.. note::

    Temporary credentials generated by AWS STS are not supported by every service. Please check if the service you are
    using supports temporary credentials by reading `AWS Services that Support AWS STS
    <http://docs.aws.amazon.com/STS/latest/UsingSTS/UsingTokens.html>`_.

Getting temporary credentials
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

AWS STS has several operations that return temporary credentials, but the ``GetSessionToken`` operation is the simplest
for demonstration purposes. Assuming you have an instance of ``Aws\Sts\StsClient`` stored in the ``$stsClient``
variable, this is how you call it:

.. code-block:: php

    $result = $stsClient->getSessionToken();

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>'
        )
        ...
    )

Providing temporary credentials to the SDK
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

.. code-block:: php

    use Aws\S3\S3Client;

    $result = $stsClient->getSessionToken();

    $s3Client = 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.

.. code-block:: php

    use Aws\Common\Credentials\Credentials;
    use Aws\S3\S3Client;

    $result = $stsClient->getSessionToken();

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

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

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

.. code-block:: php

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

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

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

.. code-block:: php

    $credentials = $stsClient->createCredentials($stsClient->getSessionToken());
    $s3Client->setCredentials($credentials);

For more information about why you might need to use temporary credentials in your application or project, see
`Scenarios for Granting Temporary Access <http://docs.aws.amazon.com/STS/latest/UsingSTS/STSUseCases.html>`_ in the AWS
STS documentation.

.. _anonymous_access:

Creating Anonymous Clients
--------------------------

In some cases, you may want to create a client that is not associated with any credentials. This allows you to make
anonymous requests to a service. For example, both S3 Objects and CloudSearch Domains can be configured to allow
anonymous access.

To create an anonymous client, you can set the ``'credentials'`` option to ``false``.

.. code-block:: php

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

    // Makes an anonymous request. The Object would need to be publicly readable for this to succeed.
    $result = $s3Client->getObject(array(
        'Bucket' => 'my-bucket',
        'Key'    => 'my-key',
    ));
