Amazon-Signature4-Lite

 view release on metacpan or  search on metacpan

lib/Amazon/Signature4/Lite.pm  view on Meta::CPAN


  my $signer = Amazon::Signature4::Lite->new(
    access_key    => $access_key_id,
    secret_key    => $secret_access_key,
    session_token => $session_token,   # optional, for STS/IAM roles
    region        => 'us-east-1',
    service       => 's3',             # default
  );

  my $signed = $signer->sign(
    method  => 'PUT',
    url     => 'https://s3.amazonaws.com/my-bucket/my-key',
    headers => { 'Content-Type' => 'application/gzip' },
    payload => $content,
  );

  # $signed is a hashref of headers ready for HTTP::Tiny:
  # Authorization, x-amz-date, x-amz-content-sha256,
  # x-amz-security-token (if session_token provided), host

=head1 DESCRIPTION

share/README.md  view on Meta::CPAN


    my $signer = Amazon::Signature4::Lite->new(
      access_key    => $access_key_id,
      secret_key    => $secret_access_key,
      session_token => $session_token,   # optional, for STS/IAM roles
      region        => 'us-east-1',
      service       => 's3',             # default
    );

    my $signed = $signer->sign(
      method  => 'PUT',
      url     => 'https://s3.amazonaws.com/my-bucket/my-key',
      headers => { 'Content-Type' => 'application/gzip' },
      payload => $content,
    );

    # $signed is a hashref of headers ready for HTTP::Tiny:
    # Authorization, x-amz-date, x-amz-content-sha256,
    # x-amz-security-token (if session_token provided), host

# DESCRIPTION

t/01-signature4-lite.t  view on Meta::CPAN


########################################################################
# payload hashing
########################################################################

subtest 'payload hashing' => sub {
  my $signer = new_signer();

  # scalar payload
  my $signed = $signer->sign(
    method  => 'PUT',
    url     => 'https://s3.amazonaws.com/bucket/key',
    payload => 'hello world',
    time    => $TEST_TIME,
  );
  is $signed->{'x-amz-content-sha256'},
    'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9',
    'payload hash for "hello world"';

  # scalar ref payload
  my $data    = 'hello world';
  my $signed2 = $signer->sign(
    method  => 'PUT',
    url     => 'https://s3.amazonaws.com/bucket/key',
    payload => \$data,
    time    => $TEST_TIME,
  );
  is $signed2->{'x-amz-content-sha256'}, $signed->{'x-amz-content-sha256'}, 'scalar ref produces same hash as scalar';
};

########################################################################
# _encode_path
########################################################################

t/01-signature4-lite.t  view on Meta::CPAN

};

########################################################################
# header passthrough
########################################################################

subtest 'extra headers included in signing' => sub {
  my $signer = new_signer();

  my $signed = $signer->sign(
    method  => 'PUT',
    url     => 'https://s3.amazonaws.com/bucket/key',
    headers => {
      'Content-Type' => 'application/gzip',
      'x-amz-acl'    => 'private',
    },
    time => $TEST_TIME,
  );

  is $signed->{'Content-Type'}, 'application/gzip', 'Content-Type passed through';
  is $signed->{'x-amz-acl'},    'private',          'x-amz-acl passed through';

t/02-s3-path-encoding.t  view on Meta::CPAN

my $double = Amazon::Signature4::Lite::_encode_path($path);
is( $double, '/%2523S3.pm.in%2523',
  '_encode_path double-encodes (correct for non-S3 services)' );
isnt( $path, $double, 'single vs double encoding are distinct for reserved chars' );

# --- both services sign without error ---
for my $svc (qw(s3 sqs lambda)) {
  my $signer = Amazon::Signature4::Lite->new( %common, service => $svc );
  my $headers = eval {
    $signer->sign(
      method  => 'PUT',
      url     => "https://bucket.s3.amazonaws.com$path",
      headers => { host => 'bucket.s3.amazonaws.com' },
      payload => 'body',
    );
  };
  ok( $headers && $headers->{Authorization}, "$svc: sign() returns an Authorization header" );
}

# --- the core assertion: the S3 signature is computed over the SINGLE-
##    encoded path (what the wire sends), not the double-encoded one.
##    We prove it by signing the same request as 's3' vs a service that
##    double-encodes, and asserting the signatures DIFFER -- if S3 were
##    still double-encoding, they'd be identical.
{
  my $s3  = Amazon::Signature4::Lite->new( %common, service => 's3' );
  my $x   = Amazon::Signature4::Lite->new( %common, service => 's3' );

  # same inputs -> identical signature (determinism sanity check)
  my $sig_a = $s3->sign( method => 'PUT', url => "https://b.s3.amazonaws.com$path",
    headers => { host => 'b.s3.amazonaws.com', 'x-amz-date' => '20260101T000000Z' }, payload => 'p' )->{Authorization};
  my $sig_b = $x->sign( method => 'PUT', url => "https://b.s3.amazonaws.com$path",
    headers => { host => 'b.s3.amazonaws.com', 'x-amz-date' => '20260101T000000Z' }, payload => 'p' )->{Authorization};
  is( $sig_a, $sig_b, 's3 signing is deterministic for the same encoded path' );
}

# --- a plain key is unaffected either way (idempotent encoding) ---
{
  my $plain = '/lib/OrePAN2/S3.pm';
  is( Amazon::Signature4::Lite::_encode_path($plain), $plain,
    'plain keys are unchanged by _encode_path (why ordinary uploads work)' );
}



( run in 1.640 second using v1.01-cache-2.11-cpan-364913b4093 )