diff --git a/pkgs/development/perl-modules/net-amazon-s3-credentials-provider.patch b/pkgs/development/perl-modules/net-amazon-s3-credentials-provider.patch new file mode 100644 index 000000000000..e24c44d7e159 --- /dev/null +++ b/pkgs/development/perl-modules/net-amazon-s3-credentials-provider.patch @@ -0,0 +1,291 @@ +commit 4afa16864ac8ae23a450abf95db023b0c8bea698 +Author: Shea Levy +Date: Thu Aug 29 07:09:34 2013 -0400 + + Use CredentialsProviders à la the Java API + + Signed-off-by: Shea Levy + +diff --git a/lib/Net/Amazon/Auth/CredentialsProvider.pm b/lib/Net/Amazon/Auth/CredentialsProvider.pm +new file mode 100755 +index 0000000..527acae +--- /dev/null ++++ b/lib/Net/Amazon/Auth/CredentialsProvider.pm +@@ -0,0 +1,9 @@ ++package Net::Amazon::Auth::CredentialsProvider; ++ ++use Moose::Role 0.85; ++ ++requires 'get_credentials'; ++ ++sub refresh { } ++ ++1; +diff --git a/lib/Net/Amazon/Auth/CredentialsProviderChain.pm b/lib/Net/Amazon/Auth/CredentialsProviderChain.pm +new file mode 100755 +index 0000000..85cd8e0 +--- /dev/null ++++ b/lib/Net/Amazon/Auth/CredentialsProviderChain.pm +@@ -0,0 +1,41 @@ ++package Net::Amazon::Auth::CredentialsProviderChain; ++ ++use Moose 0.85; ++use MooseX::StrictConstructor 0.16; ++use Net::Amazon::Auth::EnvironmentVariableCredentialsProvider; ++use Net::Amazon::Auth::InstanceProfileCredentialsProvider; ++ ++with 'Net::Amazon::Auth::CredentialsProvider'; ++ ++has 'providers' => ( is => 'ro', isa => 'ArrayRef[Net::Amazon::Auth::CredentialsProvider]', required => 1 ); ++ ++sub refresh { ++ my $self = shift; ++ ++ map { $_->refresh } @{$self->providers}; ++} ++ ++sub get_credentials { ++ my $self = shift; ++ ++ foreach my $provider (@{$self->providers}) { ++ my $res = $provider->get_credentials; ++ if (defined $res->{access_key_id}) { ++ return $res; ++ } ++ } ++ ++ return {}; ++} ++ ++sub default_chain { ++ my $class = shift; ++ return $class->new(providers => [ ++ Net::Amazon::Auth::EnvironmentVariableCredentialsProvider->new, ++ Net::Amazon::Auth::InstanceProfileCredentialsProvider->new ++ ]); ++} ++ ++__PACKAGE__->meta->make_immutable; ++ ++1; +diff --git a/lib/Net/Amazon/Auth/EnvironmentVariableCredentialsProvider.pm b/lib/Net/Amazon/Auth/EnvironmentVariableCredentialsProvider.pm +new file mode 100755 +index 0000000..ac38a84 +--- /dev/null ++++ b/lib/Net/Amazon/Auth/EnvironmentVariableCredentialsProvider.pm +@@ -0,0 +1,26 @@ ++package Net::Amazon::Auth::EnvironmentVariableCredentialsProvider; ++ ++use Moose 0.85; ++use MooseX::StrictConstructor 0.16; ++ ++extends 'Net::Amazon::Auth::FixedCredentialsProvider'; ++ ++around BUILDARGS => sub { ++ my $orig = shift; ++ my $class = shift; ++ ++ my %args = ( ++ access_key_id => $ENV{AWS_ACCESS_KEY_ID}, ++ secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} ++ ); ++ ++ if (exists $ENV{AWS_SESSION_TOKEN}) { ++ $args{session_token} = $ENV{AWS_SESSION_TOKEN}; ++ } ++ ++ return $class->$orig(\%args); ++}; ++ ++__PACKAGE__->meta->make_immutable; ++ ++1; +diff --git a/lib/Net/Amazon/Auth/FixedCredentialsProvider.pm b/lib/Net/Amazon/Auth/FixedCredentialsProvider.pm +new file mode 100755 +index 0000000..21d56c7 +--- /dev/null ++++ b/lib/Net/Amazon/Auth/FixedCredentialsProvider.pm +@@ -0,0 +1,23 @@ ++package Net::Amazon::Auth::FixedCredentialsProvider; ++ ++use Moose 0.85; ++use MooseX::StrictConstructor 0.16; ++ ++with 'Net::Amazon::Auth::CredentialsProvider'; ++ ++has 'access_key_id' => ( is => 'ro', isa => 'Maybe[Str]', required => 1 ); ++has 'secret_access_key' => ( is => 'ro', isa => 'Maybe[Str]', required => 1 ); ++has 'session_token' => ( is => 'ro', isa => 'Maybe[Str]', required => 0 ); ++ ++sub get_credentials { ++ my $self = shift; ++ return { ++ access_key_id => $self->access_key_id, ++ secret_access_key => $self->secret_access_key, ++ session_token => $self->session_token ++ }; ++} ++ ++__PACKAGE__->meta->make_immutable; ++ ++1; +diff --git a/lib/Net/Amazon/Auth/InstanceProfileCredentialsProvider.pm b/lib/Net/Amazon/Auth/InstanceProfileCredentialsProvider.pm +new file mode 100755 +index 0000000..b9f826a +--- /dev/null ++++ b/lib/Net/Amazon/Auth/InstanceProfileCredentialsProvider.pm +@@ -0,0 +1,57 @@ ++package Net::Amazon::Auth::InstanceProfileCredentialsProvider; ++ ++use Moose 0.85; ++use MooseX::StrictConstructor 0.16; ++use HTTP::Date; ++use JSON; ++ ++with 'Net::Amazon::Auth::CredentialsProvider'; ++ ++has '_ua' => ( is => 'rw', isa => 'LWP::UserAgent', required => 0 ); ++has '_access_key_id' => ( is => 'rw', isa => 'Str', required => 0 ); ++has '_secret_access_key' => ( is => 'rw', isa => 'Str', required => 0 ); ++has '_session_token' => ( is => 'rw', isa => 'Str', required => 0 ); ++has '_expiration_date' => ( is => 'rw', isa => 'Int', required => 0, default => 0 ); ++ ++sub BUILD { ++ my $self = shift; ++ my $ua = LWP::UserAgent->new; ++ $ua->timeout(10); ++ $self->_ua($ua); ++} ++ ++sub refresh { ++ my $self = shift; ++ ++ my $role_name_response = ++ $self->_ua->get("http://169.254.169.254/latest/meta-data/iam/security-credentials/"); ++ if ($role_name_response->code == 200) { ++ my $credentials_response = $self->_ua->get("http://169.254.169.254/latest/meta-data/iam/security-credentials/" . $role_name_response->content); ++ ++ if ($credentials_response->code == 200) { ++ my $credentials = decode_json($credentials_response->content); ++ $self->_expiration_date(str2time($credentials->{Expiration})); ++ $self->_access_key_id($credentials->{AccessKeyId}); ++ $self->_secret_access_key($credentials->{SecretAccessKey}); ++ $self->_session_token($credentials->{Token}); ++ } ++ } ++} ++ ++sub get_credentials { ++ my $self = shift; ++ ++ if (time() - $self->_expiration_date > -5 * 60) { #Credentials available 5 minutes before expiry ++ $self->refresh; ++ } ++ ++ return { ++ access_key_id => $self->_access_key_id, ++ secret_access_key => $self->_secret_access_key, ++ session_token => $self->_session_token ++ }; ++} ++ ++__PACKAGE__->meta->make_immutable; ++ ++1; +diff --git a/lib/Net/Amazon/S3.pm b/lib/Net/Amazon/S3.pm +index 907113e..a369e4b 100755 +--- a/lib/Net/Amazon/S3.pm ++++ b/lib/Net/Amazon/S3.pm +@@ -133,9 +133,10 @@ use LWP::UserAgent::Determined; + use URI::Escape qw(uri_escape_utf8); + use XML::LibXML; + use XML::LibXML::XPathContext; ++use Net::Amazon::Auth::FixedCredentialsProvider; ++use Net::Amazon::Auth::CredentialsProviderChain; + +-has 'aws_access_key_id' => ( is => 'ro', isa => 'Str', required => 1 ); +-has 'aws_secret_access_key' => ( is => 'ro', isa => 'Str', required => 1 ); ++has 'credentials_provider' => ( is => 'ro', isa => 'Net::Amazon::Auth::CredentialsProvider', required => 0, default => sub { return Net::Amazon::Auth::CredentialsProviderChain->default_chain; } ); + has 'secure' => ( is => 'ro', isa => 'Bool', required => 0, default => 0 ); + has 'timeout' => ( is => 'ro', isa => 'Num', required => 0, default => 30 ); + has 'retry' => ( is => 'ro', isa => 'Bool', required => 0, default => 0 ); +@@ -144,7 +145,23 @@ has 'libxml' => ( is => 'rw', isa => 'XML::LibXML', required => 0 ); + has 'ua' => ( is => 'rw', isa => 'LWP::UserAgent', required => 0 ); + has 'err' => ( is => 'rw', isa => 'Maybe[Str]', required => 0 ); + has 'errstr' => ( is => 'rw', isa => 'Maybe[Str]', required => 0 ); +-has 'aws_session_token' => ( is => 'ro', isa => 'Str', required => 0 ); ++ ++around BUILDARGS => sub { ++ my $orig = shift; ++ my $class = shift; ++ ++ my $args = $class->$orig(@_); ++ ++ if (exists $args->{aws_access_key_id}) { ++ $args->{credentials_provider} = Net::Amazon::Auth::FixedCredentialsProvider->new({ ++ access_key_id => $args->{aws_access_key_id}, ++ secret_access_key => $args->{aws_secret_access_key}, ++ session_token => $args->{aws_session_token} ++ }); ++ delete @{$args}{qw(aws_access_key_id aws_secret_access_key aws_session_token)}; ++ } ++ return $args; ++}; + + __PACKAGE__->meta->make_immutable; + +@@ -223,6 +240,24 @@ sub BUILD { + + $self->ua($ua); + $self->libxml( XML::LibXML->new ); ++ ++ die "No AWS credentials found!" unless defined $self->credentials_provider->get_credentials->{access_key_id}; ++} ++ ++# Backwards compatibility ++sub aws_access_key_id { ++ my $self = shift; ++ return $self->credentials_provider->get_credentials->{access_key_id}; ++} ++ ++sub aws_secret_access_key { ++ my $self = shift; ++ return $self->credentials_provider->get_credentials->{secret_access_key}; ++} ++ ++sub aws_session_token { ++ my $self = shift; ++ return $self->credentials_provider->get_credentials->{session_token}; + } + + =head2 buckets +diff --git a/lib/Net/Amazon/S3/HTTPRequest.pm b/lib/Net/Amazon/S3/HTTPRequest.pm +index 69c6327..d49e95b 100755 +--- a/lib/Net/Amazon/S3/HTTPRequest.pm ++++ b/lib/Net/Amazon/S3/HTTPRequest.pm +@@ -63,8 +63,9 @@ sub query_string_authentication_uri { + my $path = $self->path; + my $headers = $self->headers; + +- my $aws_access_key_id = $self->s3->aws_access_key_id; +- my $aws_secret_access_key = $self->s3->aws_secret_access_key; ++ my $creds = $self->s3->credentials_provider->get_credentials; ++ my $aws_access_key_id = $creds->{access_key_id}; ++ my $aws_secret_access_key = $creds->{secret_access_key}; + my $canonical_string + = $self->_canonical_string( $method, $path, $headers, $expires ); + my $encoded_canonical +@@ -86,9 +87,10 @@ sub query_string_authentication_uri { + + sub _add_auth_header { + my ( $self, $headers, $method, $path ) = @_; +- my $aws_access_key_id = $self->s3->aws_access_key_id; +- my $aws_secret_access_key = $self->s3->aws_secret_access_key; +- my $aws_session_token = $self->s3->aws_session_token; ++ my $creds = $self->s3->credentials_provider->get_credentials; ++ my $aws_access_key_id = $creds->{access_key_id}; ++ my $aws_secret_access_key = $creds->{secret_access_key}; ++ my $aws_session_token = $creds->{session_token}; + + if ( not $headers->header('Date') ) { + $headers->header( Date => time2str(time) ); diff --git a/pkgs/top-level/perl-packages.nix b/pkgs/top-level/perl-packages.nix index 1b66e7a28e58..0d4d7b82ce3d 100644 --- a/pkgs/top-level/perl-packages.nix +++ b/pkgs/top-level/perl-packages.nix @@ -5687,7 +5687,10 @@ rec { sha256 = "94f2bd6b317a9142e400d7d17bd573dc9d22284c3ceaa4864474ba674e0e2e9f"; }; buildInputs = [ LWP TestException ]; - propagatedBuildInputs = [ DataStreamBulk DateTimeFormatHTTP DigestHMAC DigestMD5File FileFindRule HTTPDate HTTPMessage LWPUserAgentDetermined MIMETypes Moose MooseXStrictConstructor MooseXTypesDateTimeMoreCoercions PathClass RegexpCommon TermEncoding TermProgressBarSimple URI XMLLibXML ]; + propagatedBuildInputs = [ DataStreamBulk DateTimeFormatHTTP DigestHMAC DigestMD5File FileFindRule HTTPDate HTTPMessage LWPUserAgentDetermined MIMETypes Moose MooseXStrictConstructor MooseXTypesDateTimeMoreCoercions PathClass RegexpCommon TermEncoding TermProgressBarSimple URI XMLLibXML JSON ]; + # See https://github.com/pfig/net-amazon-s3/pull/25 + patches = + [ ../development/perl-modules/net-amazon-s3-credentials-provider.patch ]; meta = { description = "Use the Amazon S3 - Simple Storage Service"; license = "perl";