AWS-Signature-V4
view release on metacpan or search on metacpan
eg/README.md view on Meta::CPAN
```shell
./eg/02-s3-get-object.pl my-bucket path/to/key.txt
AWS_REGION=eu-west-1 ./eg/02-s3-get-object.pl my-bucket photo%20one.jpg photo.jpg
```
Like 03, 04 and 05, this example puts the key in the URL as it is
written, so the key must be given as it appears there: ASCII,
percent-encoded (a space is `%20`, a percent sign `%25`, and so on).
Handing over a raw space makes `HTTP::Tiny` write an invalid request
line, and a raw `%`, `?` or `#` truncates the key or breaks the
signature.
These four examples also use the virtual-hosted URL, where the bucket is
part of the host name. That host does not match the
`*.s3.REGION.amazonaws.com` certificate when the bucket name contains a
dot, and the answer is not to turn TLS verification off: use the
path-style URL `https://s3.REGION.amazonaws.com/BUCKET/KEY` for those
buckets.
Because the bucket and `AWS_REGION` end up in the host name, they are
checked before use, as in 10: a `/` in either would move the host
somewhere else altogether (a bucket of `evil.example.com/x` gives
`https://evil.example.com/x.s3...`) and the request would be signed and
sent there, session token and all. The key needs no such check, since it
lands in the path: `sign` already refuses control characters in the URL,
and the rest is the encoding caveat above.
## 03-s3-put-object-from-file.pl
Upload a file to S3 without loading it in memory: the payload hash is
computed from a filehandle (`body_fh`, which is left where it was), and
`HTTP::Tiny` then reads the same file a piece at a time when sending.
```shell
./eg/03-s3-put-object-from-file.pl backup.tar.gz my-bucket backups/backup.tar.gz
DRY_RUN=1 ./eg/03-s3-put-object-from-file.pl big.iso my-bucket isos/big.iso
```
## 04-s3-presigned-urls.pl
Presigned URLs: the signature travels in the query string, so anyone
holding the URL can use it until it expires, with any client at all. It
prints one URL to read the object and one to write it.
```shell
./eg/04-s3-presigned-urls.pl my-bucket path/to/key.txt
./eg/04-s3-presigned-urls.pl my-bucket path/to/key.txt 600 # valid for 10 minutes
```
The output suggests how to use them with `curl`.
## 05-s3-chunked-upload.pl
Streaming upload to S3 (`aws-chunked`): the body is sent in signed
chunks, so the whole payload does not need to be hashed in advance nor
held in memory. The total size must be known, because the `Content-Length`
of the encoded body is computed with `encoded_length` and the chunker
checks that the data matches. In dry-run mode it also encodes the file and
reports how many bytes the body has, compared with the announced length.
To try a trailing checksum, set the `@checksum` variable in the script to
`(checksum => 'crc32c')`: it is passed to both `encoded_length` and
`sign`, because the announced length has to count the trailer too.
```shell
./eg/05-s3-chunked-upload.pl data.bin my-bucket uploads/data.bin
DRY_RUN=1 ./eg/05-s3-chunked-upload.pl data.bin my-bucket uploads/data.bin
```
## 06-dynamodb-json-api.pl
A JSON API, where the operation is chosen by a header
(`X-Amz-Target`), signed like all the others. It lists the DynamoDB tables
of a region.
```shell
./eg/06-dynamodb-json-api.pl
./eg/06-dynamodb-json-api.pl eu-west-1
```
## 07-rolesanywhere-x509.pl
The X.509 variant: instead of a secret key, the request is signed with
the private key of a certificate, as IAM Roles Anywhere wants, to get
temporary credentials. `KEY_TYPE` is `RSA` (default) or `ECDSA`;
`CHAIN_FILE` (a PEM bundle of intermediate CAs) and `KEY_PASSWORD` (for
encrypted keys) are optional. `TRUST_ANCHOR_ARN`, `PROFILE_ARN` and
`ROLE_ARN` are required, except with `DRY_RUN=1`, where placeholders
stand in just to show the shape of the request. Beside the
`Authorization` header, the request carries the certificate in
`X-Amz-X509` and the chain, if any, in `X-Amz-X509-Chain`.
```shell
CERT_FILE=cert.pem KEY_FILE=key.pem \
TRUST_ANCHOR_ARN=arn:aws:rolesanywhere:... PROFILE_ARN=arn:aws:rolesanywhere:... \
ROLE_ARN=arn:aws:iam::... ./eg/07-rolesanywhere-x509.pl
DRY_RUN=1 KEY_TYPE=ECDSA CERT_FILE=cert.pem KEY_FILE=key.enc.pem \
KEY_PASSWORD=secret CHAIN_FILE=ca-bundle.pem ./eg/07-rolesanywhere-x509.pl
```
The session JSON is the only thing on the standard output â the
algorithm, the status line, any error body and the `DRY_RUN=1` dump of
the request all go to the standard error â so the program can be used as
`> session.json` or piped into `jq`. A dry run obtains no session and so
writes nothing there either. A failed request prints nothing at all on
the standard output, rather than
an error body where a session was expected: `HTTP::Tiny` reports a
request that never reached AWS as status 599 with the reason, as plain
text, in the body, and that saved under the name of a session would be a
failure kept as if it were credentials. The exit status is non-zero
either way. Mind that what does get saved holds temporary credentials,
so the file deserves the same care as a private key.
`AWS_REGION` is checked here too, for the same reason as in 02 to 05 and
10: it lands in the host name, and a `/` would send the certificate and
its signature somewhere else, with whatever answered read back as a
session.
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
( run in 1.250 second using v1.01-cache-2.11-cpan-16aabcbfbcb )