view release on metacpan or search on metacpan
* release-notes/release-notes-1.2.2.md: new
* release-notes.md: updated
* VERSION: bump
* lib/Amazon/S3/Lite.pm.in
(new)
- allow ref or list
- make us-east-1 default region
(init_logger)
- set default log level to warn
- set log_level
(_init_credentials): refactored
(log_level): new
(_create_noitification_configuration)
- use new filters template
- set filter to q{} if no filter
(__DATA__): +:filters
* lib/Amazon/S3/Lite/Logger.pm.in
(new)
- accept log_level option
- refactored
(_log_level): new
* release-notes-1.0.1.md: new
* README.md: generated
* VERSION: bump
* .gitignore: CPAN::Maker::Bootstrapper build refactor
* Makefile: likewise
* docker-compose.yml: +logs
* lib/Amazon/S3/Lite.pm.in
- pod updates
(_init_logger)
- don't rain on someone's logger
(_init_credentials)
- awkward attempt reconcile Amazon::Credentials methods
(_signer): ditto
(_request): add x-amz-content-sha256 header
* lib/Amazon/S3/Lite/Credentials.pm.in
(session_token): alias for token()
* requires
- +IO::Socket::SSL, Net::SSLeay
* test-requires
+ JSON:PP, -Test::More
* test-requires.skip: new
lib/Amazon/S3/Lite.pm view on Meta::CPAN
my $options = ref $args[0] ? $args[0] : {@args};
my $self = bless $options, $class;
$self->{host} //= 's3.amazonaws.com';
$self->{secure} //= $TRUE;
$self->{timeout} //= 30;
$self->{region} //= 'us-east-1';
$self->_init_logger;
$self->_init_credentials;
$self->_init_ua;
return $self;
}
########################################################################
# Logger setup
# Priority: caller-supplied object -> Log::Log4perl (if available) ->
# minimal STDERR logger
########################################################################
lib/Amazon/S3/Lite.pm view on Meta::CPAN
}
# Fall back to minimal STDERR logger
$self->{logger} = Amazon::S3::Lite::Logger->new( log_level => $log_level );
return;
}
########################################################################
# Credential resolution
# Priority: explicit credentials object -> constructor args ->
# environment variables -> Amazon::Credentials (if available)
########################################################################
sub _init_credentials {
########################################################################
my ($self) = @_;
# 1. Caller-supplied credentials object (duck-typed)
if ( my $creds = $self->{credentials} ) {
croak "credential object is not blessed.\n"
if !blessed $creds;
foreach (qw(aws_access_key_id aws_secret_access_key token)) {
my $sub = $creds->can($_) // $creds->can("get_$_");
croak "credentials object must implement $_ or get_$_\n"
if !$sub;
}
$self->{credentials} = $creds;
return;
}
# 2. Explicit constructor args
if ( $self->{aws_access_key_id} && $self->{aws_secret_access_key} ) {
$self->{credentials} = Amazon::S3::Lite::Credentials->new(
aws_access_key_id => delete $self->{aws_access_key_id},
aws_secret_access_key => delete $self->{aws_secret_access_key},
token => delete $self->{token},
);
return;
}
# 3. Environment variables
if ( $ENV{AWS_ACCESS_KEY_ID} && $ENV{AWS_SECRET_ACCESS_KEY} ) {
$self->{credentials} = Amazon::S3::Lite::Credentials->new(
aws_access_key_id => $ENV{AWS_ACCESS_KEY_ID},
aws_secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY},
token => $ENV{AWS_SESSION_TOKEN},
);
return;
}
# 4. Amazon::Credentials (covers IAM roles, ECS task roles,
# ~/.aws/credentials, etc.)
if ( eval { require Amazon::Credentials; 1 } ) {
$self->{credentials} = Amazon::Credentials->new;
return;
}
croak 'No AWS credentials found. Supply aws_access_key_id/'
. 'aws_secret_access_key, set AWS_ACCESS_KEY_ID/'
. 'AWS_SECRET_ACCESS_KEY environment variables, '
. 'or install Amazon::Credentials for IAM role support.';
}
########################################################################
# HTTP::Tiny instance - one per object, keep-alive enabled
########################################################################
sub _init_ua {
########################################################################
lib/Amazon/S3/Lite.pm view on Meta::CPAN
}
########################################################################
# Accessors
########################################################################
sub logger { return $_[0]->{logger} }
sub log_level { return $_[0]->{log_level}; }
sub ua { return $_[0]->{ua} }
sub region { return $_[0]->{region} }
sub host { return $_[0]->{host} }
sub credentials { return $_[0]->{credentials} }
########################################################################
# Build a fresh signer from current credentials.
# Called per-request so that rotating credentials (Lambda IAM roles)
# are always current.
########################################################################
sub _signer {
########################################################################
my ( $self, $region ) = @_;
my $creds = $self->credentials;
my $access_key
= $creds->can('get_aws_access_key_id')
? $creds->get_aws_access_key_id
: $creds->aws_access_key_id;
my $secret_key
= $creds->can('get_aws_secret_access_key')
? $creds->get_aws_secret_access_key
: $creds->aws_secret_access_key;
lib/Amazon/S3/Lite.pm view on Meta::CPAN
Amazon::S3::Lite - A lightweight Amazon S3 client for common
operations
=head1 SYNOPSIS
use Amazon::S3::Lite;
# Credentials from environment or IAM role automatically
my $s3 = Amazon::S3::Lite->new({ region => 'us-east-1' });
# Explicit credentials
my $s3 = Amazon::S3::Lite->new({
region => 'us-east-1',
aws_access_key_id => $key,
aws_secret_access_key => $secret,
token => $session_token, # optional, for STS/Lambda roles
});
# Pass any credentials object with standard getters
my $s3 = Amazon::S3::Lite->new({
region => 'us-east-1',
credentials => $creds_obj,
});
# List objects in a bucket
my $result = $s3->list_objects_v2('my-bucket', prefix => 'logs/');
foreach my $obj ( @{ $result->{objects} } ) {
printf "%s %d bytes\n", $obj->{key}, $obj->{size};
}
# Paginate
lib/Amazon/S3/Lite.pm view on Meta::CPAN
Returns a new C<Amazon::S3::Lite> object. Options:
=over 4
=item region (options, default: us-east-1)
The AWS region for your bucket, e.g. C<us-east-1>.
=item aws_access_key_id / aws_secret_access_key
Static credentials. C<token> may also be supplied for STS temporary
credentials (as used by Lambda execution roles).
These are only consulted if no C<credentials> object is provided.
=item token
Optional STS session token, used alongside static credentials for
temporary credential sets.
=item credentials
An object providing credential getters. The object must respond to:
$creds->aws_access_key_id
$creds->aws_secret_access_key
$creds->token # may return undef
Any object that satisfies this interface is accepted -
L<Amazon::Credentials>, L<Paws::Credential::*>, or your own. The
getters are called at request time, so objects that refresh expiring
credentials transparently are supported.
=item logger
An object providing the standard log methods:
$logger->trace(...)
$logger->debug(...)
$logger->info(...)
$logger->warn(...)
$logger->error(...)
lib/Amazon/S3/Lite.pm view on Meta::CPAN
local S3-compatible endpoints.
=item timeout
HTTP request timeout in seconds. Default is 30.
=back
=head2 Credential resolution order
When no C<credentials> object is passed, credentials are resolved in
this order:
=over 4
=item 1.
Constructor arguments C<aws_access_key_id> and C<aws_secret_access_key>.
=item 2.
Environment variables C<AWS_ACCESS_KEY_ID>, C<AWS_SECRET_ACCESS_KEY>,
and optionally C<AWS_SESSION_TOKEN>.
=item 3.
L<Amazon::Credentials>, if installed. This covers IAM instance roles,
Lambda execution roles, ECS task roles, and C<~/.aws/credentials>
profiles.
=item 4.
If none of the above yield credentials, the constructor croaks.
=back
=head1 METHODS
All methods croak on unrecoverable errors (network failure, HTTP 5xx).
HTTP 404 is not an exception - methods that can meaningfully return
C<undef> for a missing resource do so.
=head2 list_objects_v2
lib/Amazon/S3/Lite.pm view on Meta::CPAN
=item * L<Carp> (core)
=back
Optional:
=over 4
=item * L<Amazon::Credentials> - automatic credential discovery from IAM
roles, ECS task roles, ~/.aws/credentials, and environment.
=item * L<Log::Log4perl> - structured logging; if present, used in
preference to the built-in minimal logger.
=back
=head1 LAMBDA USAGE NOTES
In a Lambda container, credentials come from the execution role via
the ECS credential provider endpoint (indicated by
C<AWS_CONTAINER_CREDENTIALS_RELATIVE_URI> in the environment).
L<Amazon::Credentials> handles this automatically when installed and
is the recommended approach. If you prefer not to take that
dependency, the Lambda runtime also populates C<AWS_ACCESS_KEY_ID>,
C<AWS_SECRET_ACCESS_KEY>, and C<AWS_SESSION_TOKEN> directly, which
this module picks up automatically from the environment.
B<Region note:> The C<list_buckets> method is a global S3 operation
and is always signed against C<us-east-1>, regardless of the region
lib/Amazon/S3/Lite/Credentials.pm view on Meta::CPAN
########################################################################
# Simple immutable credentials object â used when caller passes
# raw key/secret/token rather than a credentials object
########################################################################
package Amazon::S3::Lite::Credentials;
use strict;
use warnings;
use Carp qw(croak);
our $VERSION = '1.2.2';
share/README.md view on Meta::CPAN
Amazon::S3::Lite - A lightweight Amazon S3 client for common
operations
# SYNOPSIS
use Amazon::S3::Lite;
# Credentials from environment or IAM role automatically
my $s3 = Amazon::S3::Lite->new({ region => 'us-east-1' });
# Explicit credentials
my $s3 = Amazon::S3::Lite->new({
region => 'us-east-1',
aws_access_key_id => $key,
aws_secret_access_key => $secret,
token => $session_token, # optional, for STS/Lambda roles
});
# Pass any credentials object with standard getters
my $s3 = Amazon::S3::Lite->new({
region => 'us-east-1',
credentials => $creds_obj,
});
# List objects in a bucket
my $result = $s3->list_objects_v2('my-bucket', prefix => 'logs/');
foreach my $obj ( @{ $result->{objects} } ) {
printf "%s %d bytes\n", $obj->{key}, $obj->{size};
}
# Paginate
share/README.md view on Meta::CPAN
my $s3 = Amazon::S3::Lite->new(\%options);
Returns a new `Amazon::S3::Lite` object. Options:
- region (options, default: us-east-1)
The AWS region for your bucket, e.g. `us-east-1`.
- aws\_access\_key\_id / aws\_secret\_access\_key
Static credentials. `token` may also be supplied for STS temporary
credentials (as used by Lambda execution roles).
These are only consulted if no `credentials` object is provided.
- token
Optional STS session token, used alongside static credentials for
temporary credential sets.
- credentials
An object providing credential getters. The object must respond to:
$creds->aws_access_key_id
$creds->aws_secret_access_key
$creds->token # may return undef
Any object that satisfies this interface is accepted -
[Amazon::Credentials](https://metacpan.org/pod/Amazon%3A%3ACredentials), [Paws::Credential::\*](https://metacpan.org/pod/Paws%3A%3ACredential%3A%3A%2A), or your own. The
getters are called at request time, so objects that refresh expiring
credentials transparently are supported.
- logger
An object providing the standard log methods:
$logger->trace(...)
$logger->debug(...)
$logger->info(...)
$logger->warn(...)
$logger->error(...)
share/README.md view on Meta::CPAN
Use HTTPS. Default is 1 (true). Set to 0 only for testing against
local S3-compatible endpoints.
- timeout
HTTP request timeout in seconds. Default is 30.
## Credential resolution order
When no `credentials` object is passed, credentials are resolved in
this order:
1. Constructor arguments `aws_access_key_id` and `aws_secret_access_key`.
2. Environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`,
and optionally `AWS_SESSION_TOKEN`.
3. [Amazon::Credentials](https://metacpan.org/pod/Amazon%3A%3ACredentials), if installed. This covers IAM instance roles,
Lambda execution roles, ECS task roles, and `~/.aws/credentials`
profiles.
4. If none of the above yield credentials, the constructor croaks.
# METHODS
All methods croak on unrecoverable errors (network failure, HTTP 5xx).
HTTP 404 is not an exception - methods that can meaningfully return
`undef` for a missing resource do so.
## list\_objects\_v2
my $result = $s3->list_objects_v2($bucket, %options);
share/README.md view on Meta::CPAN
- [Amazon::Signature4::Lite](https://metacpan.org/pod/Amazon%3A%3ASignature4%3A%3ALite)
- [XML::Twig](https://metacpan.org/pod/XML%3A%3ATwig) (for parsing list and copy responses)
- [Digest::MD5](https://metacpan.org/pod/Digest%3A%3AMD5) (core, for Content-MD5 headers)
- [MIME::Base64](https://metacpan.org/pod/MIME%3A%3ABase64) (core)
- [URI::Escape](https://metacpan.org/pod/URI%3A%3AEscape)
- [Carp](https://metacpan.org/pod/Carp) (core)
Optional:
- [Amazon::Credentials](https://metacpan.org/pod/Amazon%3A%3ACredentials) - automatic credential discovery from IAM
roles, ECS task roles, ~/.aws/credentials, and environment.
- [Log::Log4perl](https://metacpan.org/pod/Log%3A%3ALog4perl) - structured logging; if present, used in
preference to the built-in minimal logger.
# LAMBDA USAGE NOTES
In a Lambda container, credentials come from the execution role via
the ECS credential provider endpoint (indicated by
`AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` in the environment).
[Amazon::Credentials](https://metacpan.org/pod/Amazon%3A%3ACredentials) handles this automatically when installed and
is the recommended approach. If you prefer not to take that
dependency, the Lambda runtime also populates `AWS_ACCESS_KEY_ID`,
`AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` directly, which
this module picks up automatically from the environment.
**Region note:** The `list_buckets` method is a global S3 operation
and is always signed against `us-east-1`, regardless of the region
t/01-s3-lite.t view on Meta::CPAN
};
};
}
########################################################################
# Unit tests â no network required
########################################################################
subtest 'constructor' => sub {
# no credentials â stub _init_credentials so the test is immune to whether
# Amazon::Credentials is installed or finds real creds (e.g. on an EC2 instance)
{
local $ENV{AWS_ACCESS_KEY_ID} = undef;
local $ENV{AWS_SECRET_ACCESS_KEY} = undef;
no warnings 'redefine';
local *Amazon::S3::Lite::_init_credentials = sub {
my ( $self, $args ) = @_;
Carp::croak 'No AWS credentials found.'
if !$args->{credentials}
&& !$args->{aws_access_key_id}
&& !$ENV{AWS_ACCESS_KEY_ID};
};
eval { Amazon::S3::Lite->new( { region => 'us-east-1' } ) };
like $@, qr/No AWS credentials/, 'croaks without credentials';
}
# explicit credentials
my $s3 = new_s3();
isa_ok $s3, 'Amazon::S3::Lite';
is $s3->region, 'us-east-1', 'region set';
is $s3->host, 's3.amazonaws.com', 'default host';
# env credentials
{
local $ENV{AWS_ACCESS_KEY_ID} = 'envkey';
local $ENV{AWS_SECRET_ACCESS_KEY} = 'envsecret';
local $ENV{AWS_SESSION_TOKEN} = 'envtoken';
my $s3e = Amazon::S3::Lite->new( { region => 'us-east-1' } );
is $s3e->credentials->aws_access_key_id, 'envkey', 'env key';
is $s3e->credentials->token, 'envtoken', 'env token';
}
# duck-typed credentials object
{
package MyCreds;
sub new { bless {}, shift }
sub aws_access_key_id {'duckkey'}
sub aws_secret_access_key {'ducksecret'}
sub token {undef}
package main;
my $s3d = Amazon::S3::Lite->new(
{ region => 'us-east-1',
credentials => MyCreds->new,
}
);
is $s3d->credentials->aws_access_key_id, 'duckkey', 'duck-type creds';
}
# bad credentials object
{
package BadCreds;
sub new { bless {}, shift }
sub aws_access_key_id {'key'}
package main;
eval { Amazon::S3::Lite->new( { region => 'us-east-1', credentials => BadCreds->new } ) };
like $@, qr/must implement aws_secret_access_key/, 'bad creds object croaks';
}
# custom logger
{
my $warned = 0;
my $logger = bless {}, 'MyLogger';
{
no strict 'refs';
for my $m (qw(trace debug info error)) {