S3 signed URLs via the CLI for PUT using CURL?

0

The documentation says that the CLI command aws s3 presign returns a URL for a GET. Numerous posts on the web claim that they've been able to upload (PUT) using curl with these URLs. I've been unable to duplicate this. Documentation is sometimes out of date. Can anyone confirm that PUTs are NOT possible using a signed URL generated by the CLI. Or, can someone provide a canonical, recent, example of being able to do so.

1 Answer
0
Accepted Answer

Per the CLI's documentation, the generated presigned URLs are only usable for GETs.

I have this recipe saved for when I need to POST; if you need to PUT, you should be able to modify it to use generate_presigned_url() instead of generate_presigned_post(). Note that this uses the boto3 library with Python, so you will need to arrange to have that available for your Python install to access (e.g. pip install boto3). The output includes values formatted for both curl and httpie, which I hope will be useful.

Python script to get presigned POST URL:

import boto3
client = boto3.client("s3")

# get presigned info
# note other params can be passed here, including expiration
# see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_post
info = client.generate_presigned_post(Bucket="some-bucket", Key="filename.txt")

# print the "fields" out in the right format to feed to httpie
print(" ".join(f"{k}='{v}'" for (k, v) in info["fields"].items()))

# for curl, use this
print(" ".join(f"-F {k}='{v}'" for (k, v) in info["fields"].items()))

# confirm the URL
print(info["url"])

Below are examples of using the returned values. You will may need to remove the comment lines for your shell to be happy.

Use with httpie:

http --form -v \
  # this the the URL from Python output
  https://some-bucket.s3.amazonaws.com/ \
  # these are the copy/pasted fields from Python output
  key='filename.txt' AWSAccessKeyId='AKIA...EWS3' policy='eyJl...dfQ==' signature='RcU...XLw=' \
  # this is the file to upload
  file@local-filename.txt

Use with curl:

curl -X POST \
  # the copy/pasted fields
  -F key='filename.txt' -F AWSAccessKeyId='AKIA...EWS3' -F policy='eyJle...dfQ==' -F signature='RcU9...XLw=' \
  # the file to upload
  -F file=@local-filename.txt \
  # the URL
  https://some-bucket.s3.amazonaws.com/
profile pictureAWS
EXPERT
James_S
answered a year ago
  • Wow, thanks for the detailed and prompt response! I figured I might need to use an SDK to generate one for PUT. Seems like a shortcoming in the CLI to me, though.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions