AWS-Signature-V4

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

      signed as /admin/delete, and that is what AWS executes. If your
      application decides whether a caller may have a request signed by
      looking at the URL, it must look at the normalized path (see the
      second line of canonical_request), not at the raw URL, or it can be
      bypassed. For those same services, dot segments that are
      percent-encoded (e.g. %2e%2e) are an error, as it is not certain how
      AWS reads them; S3 does not normalize at all, so there they are
      ordinary characters of the key and /public/%2e%2e/admin is signed as
      it is.

      * Do not log the results. headers and authorization can be used to
      replay the request for up to 15 minutes; a presigned URL is a bearer
      token until it expires; headers, canonical_request and presigned URLs
      include the session token, if there is one. Treat them as secrets.

      * Secrets in memory. The signer keeps the credentials (the secret
      access key included) as long as it lives, and ->credentials gives
      them back. The text of an X.509 private key and its password are
      dropped once the key is loaded. The key derived for signed chunks,
      which could sign any request for the same service, region and day, is
      kept by the chunker in a closure: no accessor gives back its bytes
      and dumping the chunker does not show them, but whoever holds the
      chunker can still sign with it through its internals. Do not hand the
      chunker, let alone the signer, to code that you would not trust with
      the credentials.

      * Error messages may include values that the caller provided, with
      non-printable characters escaped (e.g. \x{A}), so that they cannot
      forge lines in a log.

      * Dependencies are listed with their versions in cpanfile.snapshot;
      check them regularly against published advisories, e.g. with
      CPAN::Audit.

BUGS AND LIMITATIONS

    Minimum perl version 5.24.

    Only Signature Version 4 is supported, not Version 4A (asymmetric,

eg/08-x509-custom-signer.pl  view on Meta::CPAN

#!/usr/bin/env perl
# With the X.509 variant the private key does not have to be given to the
# module: a "signer" function receives the bytes to sign and returns the
# signature. That is how to use keys that cannot leave an HSM or a KMS.
# Here the function just uses CryptX by itself, and logs what it does.
#
#    CERT_FILE=cert.pem KEY_FILE=key.pem ./08-x509-custom-signer.pl
use v5.24;
use warnings;
use experimental 'signatures';
use FindBin '$Bin';
use lib "$Bin/../lib";
use AWS::Signature::V4;
use Crypt::PK::RSA;

eg/README.md  view on Meta::CPAN

Check the shape of the `CreateSession` request (path and body) against
the current IAM Roles Anywhere API reference before relying on it: it was
written from memory and has not been tried against AWS.


## 08-x509-custom-signer.pl

With the X.509 variant the private key does not have to be given to the
module: a `signer` function receives the bytes to sign and returns the
signature. That is how to use keys that cannot leave an HSM or a KMS. Here
the function just uses CryptX by itself and logs what it does, to show
where the hook is.

```shell
CERT_FILE=cert.pem KEY_FILE=key.pem ./eg/08-x509-custom-signer.pl
```


## 09-inspect-a-signature.pl

No network, no secrets: it reproduces the example of the AWS documentation

lib/AWS/Signature/V4.pod  view on Meta::CPAN

application decides whether a caller may have a request signed by
looking at the URL, it must look at the normalized path (see the second
line of C<canonical_request>), not at the raw URL, or it can be bypassed.
For those same services, dot segments that are percent-encoded (e.g.
C<%2e%2e>) are an error, as it is not certain how AWS reads them; S3 does
not normalize at all, so there they are ordinary characters of the key and
C</public/%2e%2e/admin> is signed as it is.

=item *

B<Do not log the results.> C<headers> and C<authorization> can be used to
replay the request for up to 15 minutes; a presigned URL is a bearer token
until it expires; C<headers>, C<canonical_request> and presigned URLs
include the session token, if there is one. Treat them as secrets.

=item *

B<Secrets in memory.> The signer keeps the credentials (the secret access
key included) as long as it lives, and C<< ->credentials >> gives them
back. The text of an X.509 private key and its password are dropped once
the key is loaded. The key derived for signed chunks, which could sign
any request for the same service, region and day, is kept by the chunker
in a closure: no accessor gives back its bytes and dumping the chunker
does not show them, but whoever holds the chunker can still sign with it
through its internals. Do not hand the chunker, let alone the signer, to
code that you would not trust with the credentials.

=item *

B<Error messages> may include values that the caller provided, with
non-printable characters escaped (e.g. C<\x{A}>), so that they cannot
forge lines in a log.

=item *

B<Dependencies> are listed with their versions in F<cpanfile.snapshot>;
check them regularly against published advisories, e.g. with
L<CPAN::Audit>.

=back


lib/AWS/Signature/V4/Error.pm  view on Meta::CPAN


# 400 for what the caller provided, 500 for problems inside the module;
# everything is passed down to ouch(), the optional third argument included.
# No "goto": it would drop the "local" before ouch() gets to build the trace.
sub fail {
   local $Carp::MaxArgNums = -1;    # the trace must not hold secrets
   Ouch::ouch(@_);
}

# caller input, made safe to put in a message: anything that is not printable
# ASCII is escaped, so that it cannot forge lines in a log
sub shown {
   my ($value) = @_;
   return 'undef' unless defined $value;
   return $value =~ s{([^\x20-\x7E])}{sprintf '\\x{%X}', ord $1}ger;
}

1;

lib/AWS/Signature/V4/Error.pod  view on Meta::CPAN


This module is part of the L<AWS::Signature::V4> distribution and shares
its version.


=head1 SYNOPSIS

   use AWS::Signature::V4::Error qw< fail shown >;

   fail 400, 'missing parameter "url"';
   fail 400, 'bad option', {option => 'foo', got => $value};    # data for logs


=head1 DESCRIPTION

B<This module is internal: you are not supposed to use it.> It is what the
modules of the distribution use to throw L<Ouch> exceptions, see
L<AWS::Signature::V4/ERRORS> for what the callers can expect.

It exists to do two things that a bare C<ouch> would not do: report the
error at the line of the caller, like C<croak>, and keep the arguments of

lib/AWS/Signature/V4/Error.pod  view on Meta::CPAN

   fail $code, $message, $data;

Throw an L<Ouch> exception. All arguments go to C<ouch> as they are.

The code is C<400> when the problem is in what the caller provided, C<500>
when it is in the module itself.

The optional C<$data> is kept by the exception and is available with
C<< $@->data >> (and C<< $@->hashref >>), but it is not part of the
message, so it is not shown by just printing the error. Use it for the
details that are useful in a log, e.g. what was received, and keep it
out of what is shown to end users. It is also kept out of the backtrace:
the exception stores C<$data> itself, but the arguments of the calls are
not recorded in C<< $@->trace >>, so they can safely carry secrets.

Nothing in the distribution passes C<$data> at the moment, but it is part
of the interface and you can rely on it being passed through.


=head2 shown

   fail 400, 'unknown checksum ' . shown($name);

Return a value provided by the caller in a form that is safe to put in a
message: every character that is not printable ASCII is escaped as
C<\x{...}>, so that the message cannot forge lines in a log; C<undef>
becomes the string C<undef>.


=head1 AUTHOR

Flavio Poletti <flavio@polettix.it>

=head1 COPYRIGHT AND LICENSE

Copyright 2026 by Flavio Poletti <flavio@polettix.it>



( run in 0.693 second using v1.01-cache-2.11-cpan-eca53f54451 )