NAME

Amazon::Credentials - fetch Amazon credentials from file, environment or role

SYNOPSIS

my @order = qw( env file container role );
my $creds = Amazon::Credentials->new( { order => \@order } );

CLI

amazon-credentials --help

DESCRIPTION

Amazon::Credentials finds AWS credentials from a chain of providers, searching in a configurable order until credentials are found. The default search order is:

environment => container => role => web_identity => file

The following credential sources are supported:

You can control which sources are tried, and in what order, via the order option in the constructor. See "new".

This class also supports SSO credentials. See "set_sso_credentials" and "get_role_credentials" for details, or use the command line tool:

amazon-credentials.sh --role my-sso-role --account 01234567890

AWS_EC2_METADATA_DISABLED

Amazon::Credentials tries hard to find credentials, searching the environment, ECS container endpoint, EC2 instance metadata, and credential files in turn. In some situations — particularly local development or CI environments where no metadata endpoint is reachable — this eagerness causes an unwanted delay while the module waits for the metadata request to time out.

You have two options for dealing with this. The first is to set AWS_EC2_METADATA_DISABLED to a true value, which disables the search for role credentials via the EC2 instance metadata endpoint entirely. The second is to reduce the timeout via the timeout constructor option (default is 3 seconds), which limits how long the module waits for the metadata endpoint to respond:

my $creds = Amazon::Credentials->new( timeout => 1 );

The preferred approach when your application is designed to run in a specific environment is to pass an explicit order to the constructor, which avoids the search entirely:

my $creds = Amazon::Credentials->new( order => [qw(role)] );

The default credential search order is:

environment => container => role => web_identity => file (profile)

VERSION

This document reverse to verion 1.3.0 of Amazon::Credentials.

METHODS AND SUBROUTINES

new

new( options );

my $aws_creds = Amazon::Credential->new( { profile => 'sandbox', debug => 1 });

options is a hash of keys that represent various options you can pass to the constructor to control how it will look for credentials. Any of the options can also be retrieved using their corresponding 'get_{option} method.

options

as_string

as_string()

Returns the credentials as a JSON encode string.

credential_keys

my $credential_keys = $creds->credential_keys;

Return a hash reference containing the credential keys with standard key names. Note that the session token will only be present in the hash for temporary credentials.

format_credentials

format_credentials(format-string)

Returns the credentials as a formatted string. The <format> argument allows you to include a format string that will be used to output each of the credential parts.

format("export %s=%s\n");

The default format is a "%s %s\n".

find_credentials

find_credentials( option => value, ...);

You normally don't want to use this method. It's automatically invoked by the constructor if you don't pass in any credentials. Accepts a hash or hash reference consisting of keys (order or profile) in the same manner as the constructor.

get_creds_from_*

These methods are called internally when the new constructor is invoked. You should never need to call these methods. All of these methods will return a hash of credential information and metadata described below.

get_creds_from_container

get_creds_from_container()

Retrieves credentials from the container credential endpoint. Supports two mechanisms, tried in this order:

Relative URI — if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set, credentials are fetched from:

http://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI

Full URI — if AWS_CONTAINER_CREDENTIALS_FULL_URI is set, that URL is used directly. Covers Lambda execution roles, Fargate task roles, and EKS Pod Identity. An authorization token is added automatically if AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE or AWS_CONTAINER_AUTHORIZATION_TOKEN is set in the environment.

Returns an empty hash if neither environment variable is set.

get_creds_from_web_identity

get_creds_from_web_identity()

Retrieves temporary credentials by exchanging an OIDC/JWT web identity token for AWS credentials via STS AssumeRoleWithWebIdentity. This is the credential mechanism used by EKS IRSA (IAM Roles for Service Accounts) and GitHub Actions OIDC federation.

Required environment variables:

Optional:

The STS call is made without AWS request signing — the OIDC token itself authenticates the request, resolving the chicken-and-egg problem of needing credentials to obtain credentials. The regional STS endpoint is used when AWS_DEFAULT_REGION or AWS_REGION is set; otherwise the global sts.amazonaws.com endpoint is used.

Returns an empty hash if the required environment variables are not set, if the token file cannot be read, or if the STS call fails.

get_creds_from_process

get_creds_from_process(process)

Retrieves credentials from a helper process defined in the config file. Returns the credentials tuple.

get_creds_from_role

get_creds_from_role()

Returns a hash, possibly containing access keys and a token.

get_default_region

Returns the region of the currently running instance or container. The constructor will set the region to this value unless you set your own region value. Use get_region to retrieve the value after instantiation or you can call this method again and it will make a second call to retrieve the instance metadata.

get_ec2_credentials (deprecated)

See "find_credentials"

is_token_expired

is_token_expired( window-interval )

Returns true if the token is about to expire (or is expired). window-interval is the time in minutes before the actual expiration time that the method should consider the token expired. The default is 5 minutes. Amazon states that new credentials will be available at least 5 minutes before a token expires.

normalize_arn

normalize_arn( arn )

# as an exported function
use Amazon::Credentials qw(normalize_arn);
my $iam_arn = normalize_arn($sts_arn);

# or as a method
my $iam_arn = $creds->normalize_arn($sts_arn);

Converts an STS assumed-role ARN to its equivalent IAM role ARN.

arn:aws:sts::123456789:assumed-role/my-role/session-name
  => arn:aws:iam::123456789:role/my-role

This is useful when an ARN obtained from GetCallerIdentity needs to be passed to IAM APIs such as SimulatePrincipalPolicy which require an IAM ARN and will reject STS assumed-role ARNs. Non-assumed-role ARNs (IAM users, IAM roles) are returned unchanged.

reset_credentials

By default this method will remove credentials from the cache if you pass a false or no value. Passing a true value will refresh your credentials from the original source (equivalent to calling set_credentials).

refresh_token (deprecated)

use refresh_credentials()

refresh_credentials()

Retrieves a fresh set of IAM credentials.

if ( $creds->is_token_expired ) {
  $creds->refresh_token()
}

set_credentials

Looks for your credentials according to the order specified by the order attribute passed in the constructor and stores the credentials in the cache.

Note that you should never have to call this method. If you call this method it will ignore your cache setting!

SSO CREDENTIALS

You can retrieve your SSO credentials after logging in using the sso_set_credentials or get_role_credentials methods.

After logging in using your SSO credentials...

aws sso login

...call one of the methods below to retrieve your credentials.

get_role_credentials

get_role_credentials( options )

options is a hash (not reference) of options

set_sso_credentials

set_sso_options(role-name, account-id, region)

Calls get_role_credentials and set AWS credenital environment variables. Region is optional, all other parameters are required.

use Amazon::Credentials qw(set_sso_credentials)

set_sso_credentials(@ENV{qw(AWS_ROLE_NAME AWS_ACCOUNT_ID)});

my $credentials = Amazon::Credentials->new;

SETTERS/GETTERS

All of the options described in the new method can be accessed by a getter or set using a setter of the same name.

Example:

$creds->set_cache(0);

DIAGNOSTICS

Set the debug option when you instantiate a Amazon::Credentials object to output debug and diagnostic messages. Note that you must also set the insecure option if you want to output full diagnostics. WARNING: Full diagnostics may include credentials. Be careful not to expose these values in logs.

CONFIGURATION AND ENVIRONMENT

The module will recognize several AWS specific environment variables described throughout this documentation.

BUGS AND LIMITATIONS

Amazon::Credentials will not attempt to retrieve temporary credentials for profiles that specify a role. If for example you define a role in your credentials file thusly:

[developer]

 role_arn = arn:aws:iam::123456789012:role/developer-access-role
 source_profile = dev

The module will not return credentials for the developer profile. While it would be theoretically possible to return those credentials, in order to assume a role, one needs credentials (chicken and egg problem).

Note that get_creds_from_web_identity resolves this problem for OIDC-federated environments (EKS IRSA, GitHub Actions) by calling STS AssumeRoleWithWebIdentity, which does not require AWS signing — the OIDC token authenticates the request directly.

DEPENDENCIES

Lower versions of these modules may be acceptable.

'Class::Accessor::Fast' => '0.31'
'Config::Tiny'          => '2.28'
'Date::Format'          => '2.24'
'File::HomeDir'         => '1.00'
'File::chdir'           => '0.1010'
'HTTP::Request'         => '6.00'
'List::Util'            => '1.5'
'POSIX::strptime'       => '0.13'

...and possibly others

In order to enable true encryption of your credentials when cached, Crypt::CBC is also required.

SECURITY CONSIDERATIONS

The security concern around your credentials is not actually the fact that the credentials can be retrieved and viewed - any process that compromises your environment can use the same methods this class does to resolve those credentials. Let me repeat that. If your environment is compromised then an actor can use all of the methods employed in this module to access your credentials.

The major issue you should be concerned about is exposing your credentials outside of the environment running your program. Thats is, the exfiltration of your credentials. Once you have resolved these credentials you may inadvertantly reveal them in many ways. Dumping objects to logs, saving your credentials in files or even outputing them to your console may expose your credentials. This module will now at the very least obfuscate them when they are stored in memory. Accidental dumping of objects will not reveal your credentials in plain-text.

Always take precautions to prevent accidental exfiltration of your credentials.

How Amazon::Credentials Helps Prevent Exfiltration

For performance and historical reasons the default is for Amazon::Credentials to cache your credentials. Starting with version 1.1.0, the module will attempt to encrypt the credentials before storing them. The module uses Crypt::CBC (if available) with the default cipher and a random (or user defined) passkey.

Even if Crypt::CBC is not available, the module will try to obfuscate the credentials. A determined actor can still decrypt these keys if they have access to the obfuscated values and your passkey. You have several options to better secure your credentials from exposure.

Securing Your Logs

To troubleshoot potential bugs in this module or to understand what Amazon::Credentials is doing you can pass a debug flag that will write potentially helpful info to STDERR.

To prevent possible exposure of credentials in debug messages, the module will not write log messages that contain your credentials even if your debug flag is set to a true value. In order to debug output of all content you the insecure flag to any of the values shown below.

Use Temporary Credentials

One additional tip to help prevent the use of your credentials even if they have been exposed in logs or files. Use temporary credentials with short expiration times whenever possible. Amazon::Credentials provides methods to determine if your credentials have expired and a method to refresh them when they have.

if ( $credentials->is_token_expired ) {
  $credentials->refresh_token;
}

Use Granular Credentials

Consider the APIs that you are calling with these credentials. If all you need to do is access a bucket or a key within a bucket, use credentials that ONLY allow access to that bucket. IAM permissions can be quite specific regarding what and from where credentials can be used to access resources.

Additonal Notes on Logging

Versions 1.0.18 and 1.0.19 allowed you to enable debugging by setting the environment variable DEBUG to any true value to enable basic debug output. Version 1.0.18 would log information to STDERR including payloads that might contain credentials. Version 1.0.19 would prevent writing any payload with credentials unless the debug mode was set to 2 or 'insecure'. Keep in mind however that you should avoid allowing upstream programs to use environment variables to set debugging modes that you might pass to Amazon::Credentials.

Starting with version 1.1.0 the Amazon::Credentials will not use the environment variable DEBUG to enable debugging! You must explicitly pass the debug flag in the constructor to enable debugging. This was done to prevent potential upstream modules that you might use who allow an environment variable to set debug mode to also inadvertantly trigger debug mode for Amazon::Credentials.

INCOMPATIBILITIES

This module has not been tested on Windows OS.

CONTRIBUTING

You can find this project on GitHub at https://github.com/rlauer6/perl-Amazon-Credentials. PRs are always welcomed!

LICENSE AND COPYRIGHT

This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.

AUTHOR

Rob Lauer - rlauer6@comcast.net