Skip to content

Refresh credentials atomically #444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f03b83f
Change the contract on credential to return a single field
keithduncan Apr 28, 2025
dedba06
None returns undef
keithduncan Apr 28, 2025
1e89e28
Environment credentials returns atomically
keithduncan Apr 28, 2025
b271239
Explicit returns itself from credential resolution
keithduncan Apr 28, 2025
98669bf
Implement AssumeRole atomically
keithduncan Apr 28, 2025
7278643
Implement AssumeRoleWithSAML atomically
keithduncan Apr 28, 2025
bae45b0
Make CredProcess atomic
keithduncan Apr 28, 2025
8b0edbe
Make ECSContainerProfile atomic
keithduncan Apr 28, 2025
a7c3dbf
Make file atomic
keithduncan Apr 28, 2025
0e8dd75
Make InstanceProfile atomic
keithduncan Apr 28, 2025
c9b8e2a
Make InstanceProfileV2 atomic
keithduncan Apr 28, 2025
f8a3138
Make provider chain atomic
keithduncan Apr 28, 2025
431c387
Make STS atomic
keithduncan Apr 28, 2025
e90f75a
Make the credentials contract that they implement refresh
keithduncan Apr 29, 2025
bec875b
Update tests for the refresh method
keithduncan Apr 29, 2025
cc05f3c
Remove handles forwarding of the credential methods, these aren't imp…
keithduncan Apr 29, 2025
d62e2c5
Update the signers to use ->refresh to get their fields
keithduncan Apr 29, 2025
84a8d21
handles doesn't allow with requirements to be satisfied
keithduncan Apr 29, 2025
08bf923
Fix JSONCaller retriving the access_key
keithduncan Apr 29, 2025
1a0a076
Add creds as an argument to sign
keithduncan Apr 29, 2025
67bfd50
Allow explicit to have an undef session token
keithduncan Apr 29, 2025
66aa01d
Fix the file provider when returning credentials from the profile
keithduncan Apr 29, 2025
731fb02
Fix refreshing creds for credprocess
keithduncan Apr 29, 2025
7998ea9
Remove comma creating void context for string rather than argument
keithduncan Apr 29, 2025
6160fbc
Fix warning in test about comparing numeric to undefined
keithduncan Apr 29, 2025
d463e28
Replace implementation of refresh with handles and move with to the e…
keithduncan Apr 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions benchmarks/util/dynamodb-decode.pl
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,15 @@ BEGIN
package Test::CustomCredentials {
use Moose;
use Paws::Credential;
use Paws::Credential::Explicit;
with 'Paws::Credential';

sub access_key { 'CustomAK' };
sub secret_key { 'CustomSK' };
sub session_token {};
sub refresh {
return Paws::Credential::Explicit->new(
access_key => 'CustomAK',
secret_key => 'CustomSK',
);
}

__PACKAGE__->meta->make_immutable;
};
Expand Down
2 changes: 1 addition & 1 deletion examples/athena.pl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
$status->QueryExecution->ResultConfiguration->OutputLocation . "\n"
if $opt->verbose;

my $a = Paws::Credential::ProviderChain->new->selected_provider;
my $a = Paws::Credential::ProviderChain->new->refresh;

# Paws::S3 is marked as unstable; the following wouldn't work with IAM roles.
my $s3 = Net::Amazon::S3->new(
Expand Down
8 changes: 5 additions & 3 deletions examples/sts-saml.pl
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,15 @@
$config = Config::INI::Reader->read_file($aws_creds_file);
}

my $a = $creds->refresh;

my $profile = lc $short_role;
try {
$config->{$profile} = {
region => $region,
aws_access_key_id => $creds->access_key,
aws_secret_access_key => $creds->secret_key,
aws_session_token => $creds->session_token,
aws_access_key_id => $a->access_key,
aws_secret_access_key => $a->secret_key,
aws_session_token => $a->session_token,
};
} catch(Paws::Exception $e) {
die sprintf "FATAL: %s - %s\n", $e->code, $e->message;
Expand Down
1 change: 0 additions & 1 deletion lib/Paws/API/Caller.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ package Paws::API::Caller;
is => 'ro',
does => 'Paws::Credential',
required => 1,
handles => [ 'access_key', 'secret_key', 'session_token' ],
);

# converts the params the user passed to the call into objects that represent the call
Expand Down
6 changes: 2 additions & 4 deletions lib/Paws/Credential.pm
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package Paws::Credential;
use Moose::Role;

requires 'access_key';
requires 'secret_key';
requires 'session_token';
requires 'refresh';

sub are_set {
my $self = shift;
return (defined $self->access_key && defined $self->secret_key);
return (defined $self->refresh);
}

no Moose;
Expand Down
37 changes: 14 additions & 23 deletions lib/Paws/Credential/AssumeRole.pm
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
package Paws::Credential::AssumeRole;
use Moose;
use DateTime::Format::ISO8601;
use Paws::Credential::Explicit;
with 'Paws::Credential';

has credentials => (is => 'rw', isa => 'Paws::Credential::Explicit|Undef');

has expiration => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => sub { 0 }
);

has actual_creds => (is => 'rw');

sub access_key {
my $self = shift;
$self->_refresh;
$self->actual_creds->AccessKeyId;
}

sub secret_key {
my $self = shift;
$self->_refresh;
$self->actual_creds->SecretAccessKey;
}

sub session_token {
my $self = shift;
$self->_refresh;
$self->actual_creds->SessionToken;
}

has sts_region => (is => 'ro', isa => 'Str|Undef', default => sub { undef });

has sts => (is => 'ro', isa => 'Paws::STS', lazy => 1, default => sub {
Expand All @@ -44,10 +27,12 @@ package Paws::Credential::AssumeRole;
has RoleArn => (is => 'rw', isa => 'Str', required => 1);
has RoleSessionName => (is => 'rw', isa => 'Str', required => 1);

sub _refresh {
sub refresh {
my $self = shift;

return if $self->expiration >= time;
if ( $self->credentials && $self->expiration >= time ) {
return $self->credentials;
}

my $result = $self->sts->AssumeRole(
RoleSessionName => $self->RoleSessionName,
Expand All @@ -57,8 +42,14 @@ package Paws::Credential::AssumeRole;
(defined $self->Policy) ? (Policy => $self->Policy) : (),
);

my $creds = $self->actual_creds($result->Credentials);
$self->credentials(Paws::Credential::Explicit->new(
access_key => $result->Credentials->AccessKeyId,
secret_key => $result->Credentials->SecretAccessKey,
session_token => $result->Credentials->SessionToken,
));
$self->expiration(DateTime::Format::ISO8601->parse_datetime($result->Credentials->Expiration)->epoch);

return $self->credentials;
}

no Moose;
Expand Down
38 changes: 12 additions & 26 deletions lib/Paws/Credential/AssumeRoleWithSAML.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,18 @@ package Paws::Credential::AssumeRoleWithSAML;
use Moose;
use DateTime::Format::ISO8601;
use Paws::Credential::None;

use Paws::Credential::Explicit;
with 'Paws::Credential';

has credentials => (is => 'rw', isa => 'Paws::Credential::Explicit|Undef');

has expiration => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => sub { 0 }
);

has actual_creds => (is => 'rw');

sub access_key {
my $self = shift;
$self->_refresh;
$self->actual_creds->AccessKeyId;
}

sub secret_key {
my $self = shift;
$self->_refresh;
$self->actual_creds->SecretAccessKey;
}

sub session_token {
my $self = shift;
$self->_refresh;
$self->actual_creds->SessionToken;
}

has sts_region => (is => 'ro', isa => 'Str|Undef', default => sub { undef });

has sts => (is => 'ro', isa => 'Paws::STS', lazy => 1, default => sub {
Expand All @@ -46,10 +28,12 @@ package Paws::Credential::AssumeRoleWithSAML;
has PrincipalArn => (is => 'rw', isa => 'Str', required => 1);
has SAMLAssertion => (is => 'rw', isa => 'Str', required => 1);

sub _refresh {
sub refresh {
my $self = shift;

return if $self->expiration >= time;
if ( $self->credentials && $self->expiration >= time ) {
return $self->credentials;
}

my $result = $self->sts->AssumeRoleWithSAML(
RoleArn => $self->RoleArn,
Expand All @@ -59,11 +43,13 @@ package Paws::Credential::AssumeRoleWithSAML;
(defined $self->Policy) ? (Policy => $self->Policy) : (),
);

my $creds = $self->actual_creds($result->Credentials);

$self->credentials(Paws::Credential::Explicit->new(
access_key => $result->Credentials->AccessKeyId,
secret_key => $result->Credentials->SecretAccessKey,
session_token => $result->Credentials->SessionToken,
));
$self->expiration(DateTime::Format::ISO8601->parse_datetime($result->Credentials->Expiration)->epoch);
}

no Moose;

1;
127 changes: 23 additions & 104 deletions lib/Paws/Credential/CredProcess.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,34 @@ package Paws::Credential::CredProcess;
use JSON::MaybeXS qw/decode_json/;
use Paws::Exception;
use DateTime::Format::ISO8601;
use Paws::Credential::Explicit;

with 'Paws::Credential';

has credential_process => (is => 'ro', isa => 'Str', required => 1);

has credentials => (is => 'rw', isa => 'Paws::Credential::Explicit|Undef');

has expiration => (
is => 'rw',
isa => 'Int|Undef',
lazy => 1,
default => sub { 0 }
);

has actual_creds => (
is => 'ro',
isa => 'HashRef',
builder => '_build_actual_creds',
clearer => '_clear_actual_creds',
lazy => 1
);

sub _build_actual_creds {
sub refresh {
my $self = shift;

if ( $self->credentials ) {
if (not defined $self->expiration) {
return $self->credentials;
}

if ($self->expiration >= time ) {
return $self->credentials;
}
}

my $creds;
my $rc;
{
Expand All @@ -44,103 +52,14 @@ package Paws::Credential::CredProcess;
$self->expiration(undef);
}

return $creds;
}

sub access_key {
my $self = shift;
$self->_refresh;
$self->actual_creds->{ AccessKeyId };
}

sub secret_key {
my $self = shift;
$self->_refresh;
$self->actual_creds->{ SecretAccessKey }
}

sub session_token {
my $self = shift;
$self->_refresh;
$self->actual_creds->{ SessionToken };
}

sub _refresh {
my $self = shift;
$self->credentials(Paws::Credential::Explicit->new(
access_key => $creds->{ AccessKeyId },
secret_key => $creds->{ SecretAccessKey },
session_token => $creds->{ SessionToken },
));

return if not defined $self->expiration;
return if $self->expiration >= time;
$self->_clear_actual_creds;
return $self->credentials;
}

with 'Paws::Credential';

no Moose;
1;
### main pod documentation begin ###

=encoding UTF-8

=head1 NAME

Paws::Credential::File

=head1 SYNOPSIS

use Paws::Credential::File;

my $paws = Paws->new(config => {
credentials => Paws::Credential::File->new(
profile => 'profile1',
credentials_file => '/etc/aws_system_credentials',
)
});
# will open /etc/aws_system_credentials


my $paws = Paws->new(config => {
credentials => Paws::Credential::File->new(
profile => 'profile1',
file_name => 'my_creds',
)
});
# will open $HOME/.aws/my_creds

my $paws = Paws->new(config => {
credentials => Paws::Credential::File->new(
profile => 'profile1',
dir => '/etc/',
)
});
# will open /etc/credentials


=head1 DESCRIPTION

The File credential provider is to read credentials from AWS SDK config files

=head2 profile: Str

The section in the ini file where credentials will be looked up:

Defaults to the environment variable C<AWS_DEFAULT_PROFILE>, and if that is not defined, to "default"

=head2 credentials_file: Str

The path of the ini file to open

Defaults to the path + file_name (C<$HOME/.aws/credentials> by default) if the environment variable AWS_CONFIG_FILE doesn't exist

=head2 path: Str

Path to the ini file

Defaults to C<$HOME/.aws>

=head2 file_name: Str

Name of the ini file

Defaults to C<credentials>

=cut
Loading