AWS S3 presigning

Assume we have private buckets and objects, and we want them to remain private. But at some cases we also need to allow user access without security credentials or permissions. Presigned URLs can be used to access the buckets, when creating we associate it with a specific action. Then URL can be shared and anyone will be able to perform the action embedded into it.

Notes

Presigned URL will expire and no longer work when it reaches the expiration time provided during generation process.

Limiting capabilities

Presigned URL capabilities are limited by permissions of it’s creator therefore must be protected appropriately. So IAM principall that makes call should have precise set of policies or the S3 bucket, or event both parts.

Who can create

Must be created by someone with permissions to perform the operation that presigned URL is intended to allow.

Following credentials can be used:

Notes

To have URL valid for up to 7 days, it must be generated with access key & secret key of IAM user using AWS Signature V4.

Notes

When generated using temporary token, URL will expire at the same time token expires.

Notes

URL expiration is checked by S3 at the time of the HTTP request. At the same time if expiration happened during long running operation (huge object read) it will not be terminated. But all next attempts to use URL will fail.

Sharing

Presigning via AWS Cli with expiration time equal to 60 seconds.

> aws s3 presign s3://my-awesome-bucket/keyboard.png --expires-in 60

Presigned URL will look as following

https://my-awesome-bucket.s3.amazonaws.com/keyboard.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXXXX&X-Amz-Date=20220523T115133Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host&X-Amz-Security-Token=XXXXXXXXXX&X-Amz-Signature=XXXXXXXXXX

Now we can get/put/delete the object from S3, depending on policies creator of the URL had when generationg the link.

To view the content in the browser the only thing we need to do is just opend the link.

After presigned URL expiration, client will get response with code 403 and similar body as described below.

<Error>
  <Code>AccessDenied</Code>
  <Message>Request has expired</Message>
  <X-Amz-Expires>60</X-Amz-Expires>
  <Expires>2022-05-23T11:52:33Z</Expires>
  <ServerTime>2022-05-23T12:06:42Z</ServerTime>
  <RequestId>XXXXXXXXXX</RequestId>
  <HostId>XXXXXXXXXX</HostId>
</Error>

Presigning also can be done programmaticaly wia AWS SDK for language of choice.

Conclusion

Relatively simple and nice mechanism for granting temporary access to S3 objects with desired access level granularity. Great way for implemeting user files uppload/download/sharing while remaining private and cost efficient as client app interacts with S3 directly.