- NAME
- SYNOPSIS
- DESCRIPTION
- VERSION
- METHODS AND SUBROUTINES
- SSO CREDENTIALS
- SETTERS/GETTERS
- DIAGNOSTICS
- CONFIGURATION AND ENVIRONMENT
- BUGS AND LIMITATIONS
- DEPENDENCIES
- SECURITY CONSIDERATIONS
- INCOMPATIBILITIES
- CONTRIBUTING
- LICENSE AND COPYRIGHT
- AUTHOR
Amazon::Credentials - fetch Amazon credentials from file, environment or role
my @order = qw( env file container role );
my $creds = Amazon::Credentials->new( { order => \@order } );
CLI
amazon-credentials --help
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:
- Environment -
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionallyAWS_SESSION_TOKEN. - Container - ECS task roles via
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI(classic ECS), or any container runtime that providesAWS_CONTAINER_CREDENTIALS_FULL_URI- including Lambda execution roles, Fargate task roles, and EKS Pod Identity. - Instance role - EC2 instance profile credentials via the IMDSv2
metadata endpoint (
http://169.254.169.254). RespectsAWS_EC2_METADATA_DISABLED. - Web Identity - OIDC/JWT federation via STS
AssumeRoleWithWebIdentity. Used by EKS IRSA (IAM Roles for Service Accounts) and GitHub Actions. RequiresAWS_WEB_IDENTITY_TOKEN_FILEandAWS_ROLE_ARN. - File -
~/.aws/credentialsand~/.aws/configprofiles, including credential_process and SSO configurations.
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 --role my-sso-role --account 01234567890
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)
This document refers to version 1.3.0 of Amazon::Credentials.
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.
-
aws_access_key_id
AWS access key.
-
aws_secret_access_key
AWS secret access key.
Note: If you pass the access keys in the constructor then the constructor will not look in other places for credentials.
-
cache
Boolean that controls whether credentials are retained in the object after being fetched. Caching is enabled by default.
When caching is disabled, credentials are fetched on the first call to a getter and the closure for that credential is reset to undef immediately after the value is returned. Each subsequent getter call will re-fetch credentials. Use
credential_keys()to retrieve the full credential tuple in a single operation without the values ever being split across multiple calls.Note that disabling the cache limits the window during which credential values are held in memory, but Perl makes no guarantees about when or whether that memory is actually cleared by the interpreter. See "Caching and Memory" under "SECURITY CONSIDERATIONS".
-
container
If the process is running in a container, this value will contain a string indicating the credential source. The class supports two forms of container credentials:
Relative URI (classic ECS on EC2): credentials are fetched from the ECS container metadata endpoint using
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI:http://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URIFull URI (Lambda, Fargate, EKS Pod Identity): credentials are fetched from the full URL provided in
AWS_CONTAINER_CREDENTIALS_FULL_URI. The URL must behttps://,http://127.x.x.x,http://[::1], orhttp://169.254.170.23(EKS Pod Identity agent). An optional authorization token may be provided viaAWS_CONTAINER_AUTHORIZATION_TOKENorAWS_CONTAINER_AUTHORIZATION_TOKEN_FILE.The
containermetadata key in the returned credentials hash will be'ECS'for the relative URI form and'full_uri'for the full URI form. -
debug
Set to true for verbose troubleshooting information. Set
loggerto a logger that implements a logging interface (ala Log::Log4perl. -
env - Environment
If there exists an environment variable $AWS_PROFILE, then an attempt will be made to retrieve credentials from the credentials file using that profile, otherwise the class will for these environment variables to provide credentials.
AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKENNote that when you set the environment variable AWS_PROFILE, the order essentially is overridden and the class will look in your credential files (
~/.aws/config,~/.aws/credentials) to resolve your credentials. -
file - Configuration Files
- ~/.aws/config
- ~/.aws/credentials
The class will attempt to resolve credentials by interpretting the information in these two files. You can also specify a profile to use for looking up the credentials by passing it into the constructor or setting it the environment variable
AWS_PROFILE. If no profile is provided, the default credentials or the first profile found is used.my $aws_creds = Amazon::Credentials->new({ order => [qw/environment role file/] }); -
imdsv2
Boolean flag that causes
Amazon::Credentialsto use the IMDSv2 protocol when retrieving instance role credentials from the EC2 metadata service. IMDSv2 uses a session-oriented approach requiring a token to be fetched before making metadata requests, providing stronger protection against SSRF attacks.Default: true
AWS recommends IMDSv2 for all EC2 workloads. IMDSv1 can be disabled at the instance or account level as a security hardening measure, in which case this option must be enabled for instance role credential retrieval to succeed.
-
logger
Pass in your own logger that has a
debug()method. Otherwise the default logger will output debug messages to STDERR. =item orderAn array reference containing tokens that specifies the order in which the class will search for credentials.
default: env, role, container, file
Example:
my $creds = Amazon::Credentials->new( { order => [ qw/file env role/] }); -
print_error
Whether to print the error if no credenials are found.
raise_errorimpliesprint_error.default: true
-
profile
The profile name in the configuration file (
~/.aws/configor~/.aws/credentials).my $aws_creds = Amazon::Credentials->new({ profile => 'sandbox' });The class will also look for the environment variable
AWS_PROFILE, so you can invoke your script like this:$ AWS_PROFILE=sandbox my-script.pl -
raise_error
Whether to raise an error if credentials are not found.
default: true
-
region
Default region. The class will attempt to find the region in either the configuration files or the instance unless you specify the region in the constructor.
-
role - Instance Role
The class will use the http://169.254.169.254/latest/meta-data/iam/security-credential URL to look for an instance role and credentials.
Credentials returned by accessing the meta-data include a token that should be passed to Amazon APIs along with the access key and secret. That token has an expiration and should be refreshed before it expires.
if ( $aws_creds->is_token_expired() ) { $aws_creds->refresh_token() } -
timeout
When looking for credentials in metadata URLs, this parameter specifies the timeout value in seconds for HTTP metadata sevice requests.
default: 3s
-
user_agent
Pass in your own user agent, otherwise
Amazon::Credentials::HTTP::UserAgent(backed byHTTP::Tiny) will be used. The object must implement arequestmethod accepting anHTTP::Requestobject and returning a response object withcontent,content_type,is_success,code, andmessagemethods. Probably only useful to override for testing purposes.
as_string()
Returns the credentials as a JSON encode string.
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.
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
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( 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.
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.
-
aws_access_key_id
The AWS access key.
-
aws_secret_access_key
The AWS secret key.
-
token
Security token used with access keys.
-
expiration
Token expiration date.
-
role
IAM role if available.
-
source
The source from which the credentials were found.
- IAM - retrieved from container or instance role
- container -
'ECS'if retrieved viaAWS_CONTAINER_CREDENTIALS_RELATIVE_URI;'full_uri'if retrieved viaAWS_CONTAINER_CREDENTIALS_FULL_URI - web_identity - retrieved via STS AssumeRoleWithWebIdentity
- file - retrieved from file
- process - retrieved from an external process
- ENV - retrieved from environment
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()
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:
-
AWS_WEB_IDENTITY_TOKEN_FILEPath to a file containing the OIDC/JWT token.
-
AWS_ROLE_ARNARN of the IAM role to assume.
Optional:
-
AWS_ROLE_SESSION_NAMEA name for the assumed role session. Defaults to
amazon-credentials-session.
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(process)
Retrieves credentials from a helper process defined in the config file. Returns the credentials tuple.
get_creds_from_role()
Returns a hash, possibly containing access keys and a token.
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.
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( 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.
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).
use refresh_credentials()
Retrieves a fresh set of IAM credentials.
if ( $creds->is_token_expired ) {
$creds->refresh_token()
}
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!
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( options )
options is a hash (not reference) of options
-
role_name => role name (required)
-
account_id => AWS account id (required)
-
region => AWS region where SSO has been provisioned
default: $ENV{AWS_REGION}, $ENV{AWS_DEFAULT_REGION}, us-east-1
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;
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);
Set the debug option when you instantiate a Amazon::Credentials
object to output debug and diagnostic messages.
The module will recognize several AWS specific environment variables described throughout this documentation.
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
- AWS_REGION
- AWS_DEFAULT_REGION
- AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
- AWS_CONTAINER_CREDENTIALS_FULL_URI
- AWS_CONTAINER_AUTHORIZATION_TOKEN
- AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
- AWS_WEB_IDENTITY_TOKEN_FILE
- AWS_ROLE_ARN
- AWS_ROLE_SESSION_NAME
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.
Lower versions of these modules may be acceptable.
'Class::Accessor::Fast' => '0.31'
'Config::Tiny' => '2.28'
'File::HomeDir' => '1.00'
'HTTP::Request' => '6.00'
'HTTP::Tiny' => '0.088'
'JSON::PP' => '4.16'
'List::Util' => '1.5'
'Net::SSLeay' => '0'
'IO::Socket::SSL' => '0'
'POSIX::strptime' => '0.13'
...and possibly others
The security concern around your credentials is not that they can be retrieved and viewed - any process that compromises your environment can use the same discovery methods this module does. If your environment is compromised, an actor can resolve your credentials the same way this module does. The real threat is exfiltration: your credentials escaping your environment through logs, debug output, serialized objects, or core dumps.
Always take precautions to prevent accidental exfiltration of your credentials.
Starting with version 1.3.0, credentials are never stored as plain scalar attributes on the object. Instead they are captured in Perl closures. The object holds a code reference for each credential value; calling it returns the credential. The values themselves live only in the closure's lexical scope and are invisible to serialization:
use Data::Dumper;
my $creds = Amazon::Credentials->new;
print Dumper $creds;
# _access_key_id => sub { "DUMMY" },
# _secret_access_key => sub { "DUMMY" },
# _session_token => sub { "DUMMY" },
Dumper, JSON::PP::encode_json, exception stack traces, and
similar introspection tools will show only opaque code references -
never the credential values. This replaces the previous
encryption-based approach, which was both heavier (requiring
Crypt::CBC and Crypt::Cipher::AES) and weaker (the passkey lived
on the same object as the ciphertext unless you explictly sourced your
passkey from an external process).
Disabling the cache with cache => 0 means credentials are
fetched on first use and the closures are reset to undef immediately
after each getter call. This limits the window during which a live
value exists in memory.
my $credentials = Amazon::Credentials->new( cache => 0 );
However, Perl makes no guarantees about when or whether memory containing a sensitive value is actually cleared. The interpreter may retain a copy of the string in freed memory, in a copy-on-write buffer, or in an arena waiting to be reclaimed. Disabling the cache reduces the lifetime of credentials in the object, but it is not a substitute for running in a properly secured environment.
If you need the credential tuple at once without it ever being split
across multiple getter calls, use credential_keys():
my $keys = $creds->credential_keys;
# { aws_access_key_id => ..., aws_secret_access_key => ..., token => ... }
-
Option 2 - Remove them manually after use
Call
reset_credentials()with a false value after fetching credentials or after they are used by downstream processes. Call it with a true value to regenerate them. -
Using Multiple Instances of Amazon::Credentials
You may need to assume a role using initial credentials. In this case you can use multiple instances of Amazon::Credentials.
# 1. retrieve SSO credentials my $sso_credentials = Amazon::Credentials->new( sso_role_name => 'developer', sso_account_id => '01234567890' ); # 2. assume a role in another account my $role_arn = 'arn:aws:iam::09876543210:role/Route53AccountAccessRole'; my $role_session_name = "route53-role-$PID"; my $sts = Amazon::API::STS->new( credentials => $sso_credentials ); my $assume_role_result = $sts->AssumeRole( { RoleArn => $role_arn, RoleSessionName => $role_session_name, } ); my $assumed = $assume_role_result->{AssumeRoleResult}{Credentials}; # 3. create new credentials for assumed role my $role_credentials = Amazon::Credentials->new( aws_access_key_id => $assumed->{AccessKeyId}, aws_secret_access_key => $assumed->{SecretAccessKey}, expiration => $assumed->{Expiration}, token => $assumed->{SessionToken}, ); # 4. make a call using the assumed role my $rt53 = Amazon::API::Route53->new( credentials => $role_credentials ); my $response = $rt53->ListTagsForResources( { ResourceType => 'hostedzone', ResourceIds => \@zone_ids, } );
To troubleshoot this module you can pass a debug flag that writes
diagnostic information to STDERR. Because credentials are stored as
closures, they cannot appear in debug output produced by
Data::Dumper or similar tools - the object dump shows only code
references. You should still be careful with any application-level
logging that explicitly calls the getter methods and logs their return
values.
Use temporary credentials with short expiration times whenever possible. Amazon::Credentials provides methods to check expiration and refresh credentials when they have expired.
if ( $credentials->is_token_expired ) {
$credentials->refresh_token;
}
Consider the APIs you are calling. If all you need is access to a single S3 bucket, use credentials scoped to that bucket only. IAM permissions can be quite specific about what resources credentials can access and from where.
Starting with version 1.1.0, Amazon::Credentials does not
use the DEBUG environment variable to enable debug output. You must
explicitly pass debug => 1 to the constructor. This prevents
upstream modules that set DEBUG from inadvertently triggering debug
mode in Amazon::Credentials.
This module has not been tested on Windows OS.
You can find this project on GitHub at https://github.com/rlauer6/perl-Amazon-Credentials. PRs are always welcomed!
This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
Rob Lauer - rlauer6@comcast.net