There are many articles explaining how to do this, but most of the end in the dreaded
The request signature we calculated does not match the signature you provided. Check your key and signing method.
How to generate presigned URLs for S3 objects using python
This article just recommends that you give up and use generate_presigned_post instead of generate_presigned_url with put_object.
After reading many posts and stackoverflow articles
This works
The trick is specifying the signature version
from botocore.client import Config
import boto3
def gen_url(key):
"""
given the name of the file generates a signed download url for the file
:param key: filename in s3
:return: presigned URL that has AWS4-HMAC-SHA256
"""
expTime = 86400
s3 = boto3.resource(
"s3", region_name=REGION, config=Config(signature_version="s3v4")
)
return s3.meta.client.generate_presigned_url(
"put_object", Params={"Bucket": AIRFLOW_BUCKET, "Key": key}, ExpiresIn=expTime
)