In order to authenticate requests, AWS services require you to provide your AWS 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 using one of the following methods:
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. Regardless of how you supply credentials to the SDK, it is encouraged that you follow the IAM Best Practices when managing your credentials.
If you do not provide credentials to a client object at the time of its
instantiation, the SDK will attempt to find credentials in your environment.
The first place the SDK will check for credentials is in your environment
variables. The SDK will use the getenv()
function function to look for the
AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
, and AWS_SESSION_TOKEN
environment variables. These credentials are referred to as
environment credentials.
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 service. 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.
To Avoid hitting metadata service every time, an instance of Aws\CacheInterface
can be passed in as the 'credentials'
option to a client constructor. This lets SDK
use cached instance profile credentials instead. For more information, see 'credentials'
option.
For more information, see IAM Roles for Amazon EC2.
With IAM roles for Amazon ECS tasks, you can specify an IAM role that can be used by the containers in a task. This provides a strategy for managing credentials for your applications to use, similar to the way that Amazon EC2 instance profiles provide credentials to EC2 instances.
Instead of creating and distributing your AWS credentials to the containers or
using the EC2 instance’s role, you can associate an IAM role with an ECS task definition or
RunTask
API operation.
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.
For more information, see IAM Roles for Amazon EC2 Container Service Tasks.
Using Aws\Credentials\AssumeRoleCredentialProvider
to create credentials by assuming a role,
you would need to provide 'client'
information with a StsClient
object and
'assume_role_params'
details.
For more information regarding 'assume_role_params'
, see AssumeRole.
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient([
'region' => 'us-west-2',
'version' => '2011-06-15'
]),
'assume_role_params' => [
'RoleArn' => '<string>', // REQUIRED
'RoleSessionName' => '<string>', // REQUIRED
...
]
]);
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:
The format of the AWS credentials file should look something like the following:
[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 a SDK configuration
file, or when you are instantiating a client, using the profile
option:
<?php
use Aws\DynamoDb\DynamoDbClient;
// Instantiate a client with the credentials from the project1 profile
$client = new DynamoDbClient([
'profile' => 'project1',
'region' => 'us-west-2',
'version' => 'latest'
]);
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.
You can provide hard-coded credentials to a SDK client by providing the "key", "secret", and optional "token" key value pairs to the "credentials" option of a client constructor.
$s3Client = new S3Client([
'version' => 'latest',
'region' => 'us-west-2',
'credentials' => [
'key' => 'my-access-key-id',
'secret' => 'my-secret-access-key',
],
]);
Warning
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.
A credential provider is a function that returns a GuzzleHttp\Promise\PromiseInterface
that is fulfilled with an Aws\Credentials\CredentialsInterface
instance or
rejected with an Aws\Exception\CredentialsException
. You can use credential
providers to implement your own custom logic for creating credentials or to
optimize credential loading.
Credential providers are passed into the credentials
client constructor
option. Credential providers are asynchronous, which forces them to be lazily
evaluated each time an API operation is invoked. As such, passing in a
credential provider function to an SDK client constructor will not immediately
validate the credentials. If the credential provider does not return a
credentials object, an API operation will be rejected with an
Aws\Exception\CredentialsException
.
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
// Use the default credential provider
$provider = CredentialProvider::defaultProvider();
// Pass the provider to the client.
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => $provider
]);
The SDK ships with several built-in providers that can be combined together along with any custom providers.
Important
Credential providers are invoked every time an API operation is performed.
If loading credentials is an expensive task (e.g., loading from disk or a
network resource) or if credentials are not cached by your provider, then
you should consider wrapping your credential provider in an
Aws\Credentials\CredentialProvider::memoize
function. The default
credential provider used by the SDK is automatically memoized.
Aws\Credentials\CredentialProvider::env
attempts to load credentials from
environment variables.
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => CredentialProvider::env()
]);
Aws\Credentials\CredentialProvider::ini
attempts to load credentials from
an ini credential file. The SDK will by default
attempt to load the "default" profile from a file located at
~/.aws/credentials
.
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
$provider = CredentialProvider::ini();
// Cache the results in a memoize function to avoid loading and parsing
// the ini file on every API operation.
$provider = CredentialProvider::memoize($provider);
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => $provider
]);
You can use a custom profile or ini file location by providing arguments to the function that creates the provider.
$profile = 'production';
$path = '/full/path/to/credentials.ini';
$provider = CredentialProvider::ini($profile, $path);
$provider = CredentialProvider::memoize($provider);
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => $provider
]);
Aws\Credentials\CredentialProvider::instanceProfile
attempts to load
credentials from Amazon EC2 instance profiles.
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
$provider = CredentialProvider::instanceProfile();
// Be sure to memoize the credentials
$memoizedProvider = CredentialProvider::memoize($provider);
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => $memoizedProvider
]);
Note
This attempt to load from Amazon EC2 instance profiles can be disabled by
setting the AWS_EC2_METADATA_DISABLED
environment variable to true
.
Aws\Credentials\CredentialProvider::ecsCredentials
attempts to load
credentials by a GET
request, whose uri is specified by environment variable
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
in the container.
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
$provider = CredentialProvider::ecsCredentials();
// Be sure to memoize the credentials
$memoizedProvider = CredentialProvider::memoize($provider);
$client = new S3Client([
'region' => 'us-west-2',
'version' => '2006-03-01',
'credentials' => $memoizedProvider
]);
Aws\Credentials\CredentialProvider::defaultProvider
is the default
credential provider. This provider is used if you omit a credentials
option
when creating a client. It first attempts to load credentials from environment
variables, then from an ini file (.aws/credentials
file first, followed by .aws/config
file),
then from an instance profile (EcsCredentials
first, followed by Ec2
metadata).
Note
The result of the default provider is automatically memoized.
Aws\Credentials\CredentialProvider::assumeRole
is a credential provider
that creates credentials using assume role parameters and StsClient
information.
memoize
function that handles automatically refreshing the credentials when they expire.See details with following example code.
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
use Aws\Sts\StsClient;
// Passing Aws\Credentials\AssumeRoleCredentialProvider options directly
$provider = CredentialProvider::assumeRole([
'client' => new StsClient(['region' => 'us-west-2', 'version' => 'latest']),
'assume_role_params' => [
'RoleArn' => 'arn:aws:iam::012345678910:role/role_name',
'RoleSessionName' => 'test_session',
]
]);
// To avoid unnecessarily fetching STS credentials on every API operation,
// memoize function will handle automatically refreshing the credentials when they expire
$provider = CredentialProvider::memoize($provider);
$client = new S3Client([
'region' => 'us-west-2',
'version' => 'latest',
'credentials' => $provider
]);
Credential providers are simply functions that when invoked return a promise
(GuzzleHttp\Promise\PromiseInterface
) that is fulfilled with an
Aws\Credentials\CredentialsInterface
object or rejected with an
Aws\Exception\CredentialsException
.
A best practice for creating providers is to create a function that is invoked
to create the actual credential provider. As an example, here's the source of
the env
provider (slightly modified for example purposes). Notice that it
is a function that returns the actual provider function. This allows you to
easily compose credential providers and pass them around as values.
use GuzzleHttp\Promise;
use GuzzleHttp\Promise\RejectedPromise;
// This function CREATES a credential provider.
public static function env()
{
// This function IS the credential provider.
return function () {
// Use credentials from environment variables, if available
$key = getenv(self::ENV_KEY);
$secret = getenv(self::ENV_SECRET);
if ($key && $secret) {
return Promise\promise_for(
new Credentials($key, $secret, getenv(self::ENV_SESSION))
);
}
$msg = 'Could not find environment variable '
. 'credentials in ' . self::ENV_KEY . '/' . self::ENV_SECRET;
return new RejectedPromise(new CredentialsException($msg));
};
}
It is sometimes necessary to create a credential provider that remembers the
previous return value. This can be useful for performance when loading
credentials is an expensive operation or when using the Aws\Sdk
class to
share a credential provider across multiple clients. You can add memoization to
a credential provider by wrapping the credential provider function in a
memoize
function:
use Aws\Credentials\CredentialProvider;
$provider = CredentialProvider::instanceProfile();
// Wrap the actual provider in a memoize function.
$provider = CredentialProvider::memoize($provider);
// Pass the provider into the Sdk class and share the provider
// across multiple clients. Each time a new client is constructed,
// it will use the previously returned credentials as long as
// they have not yet expired.
$sdk = new Aws\Sdk(['credentials' => $provider]);
$s3 = $sdk->getS3(['region' => 'us-west-2', 'version' => 'latest']);
$ec2 = $sdk->getEc2(['region' => 'us-west-2', 'version' => 'latest']);
assert($s3->getCredentials() === $ec2->getCredentials());
When the memoized credentials become expired, the memoize wrapper will invoke the wrapped provider in an attempt to refresh the credentials.
Credential providers can be chained using the
Aws\Credentials\CredentialProvider::chain()
function. This function accepts
a variadic number of arguments, each of which are credential provider
functions. This function then returns a new function that is the composition of
the provided functions such that they are invoked one after the other until one
of the providers returns a promise that is fulfilled successfully.
The defaultProvider
uses this composition in order to check multiple
providers before failing. The source of the defaultProvider
demonstrates
the use of the chain
function.
// This function returns a provider.
public static function defaultProvider(array $config = [])
{
// This function is the provider, which is actually the composition
// of multiple providers. Notice that we are memoizing the result by
// default as well.
return self::memoize(
self::chain(
self::env(),
self::ini(),
self::instanceProfile($config)
)
);
}
AWS Security Token Service (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).
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.
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:
$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>'
)
...
)
You can use temporary credentials with another AWS client by instantiating the client and passing in the values received from AWS STS directly.
use Aws\S3\S3Client;
$result = $stsClient->getSessionToken();
$s3Client = new S3Client([
'version' => '2006-03-01',
'region' => 'us-west-2',
'credentials' => [
'key' => $result['Credentials']['AccessKeyId'],
'secret' => $result['Credentials']['SecretAccessKey'],
'token' => $result['Credentials']['SessionToken']
]
]);
You can also construct a Aws\Credentials\Credentials
object and use that
when instantiating the client.
use Aws\Credentials\Credentials;
use Aws\S3\S3Client;
$result = $stsClient->getSessionToken();
$credentials = new Credentials(
$result['Credentials']['AccessKeyId'],
$result['Credentials']['SecretAccessKey'],
$result['Credentials']['SessionToken']
);
$s3Client = new S3Client([
'version' => '2006-03-01',
'region' => 'us-west-2',
'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.
$result = $stsClient->getSessionToken();
$credentials = $stsClient->createCredentials($result);
$s3Client = new S3Client([
'version' => '2006-03-01',
'region' => 'us-west-2',
'credentials' => $credentials
]);
For more 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.
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
.
$s3Client = new S3Client([
'version' => 'latest',
'region' => 'us-west-2',
'credentials' => false
]);
// Makes an anonymous request. The Object would need to be publicly
// readable for this to succeed.
$result = $s3Client->getObject([
'Bucket' => 'my-bucket',
'Key' => 'my-key',
]);