python-boto3/docs/source/guide/s3-presigned-urls.rst
2021-09-22 09:34:33 -07:00

212 lines
8.4 KiB
ReStructuredText

.. Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0
International License (the "License"). You may not use this file except in compliance with the
License. A copy of the License is located at http://creativecommons.org/licenses/by-nc-sa/4.0/.
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the specific language governing permissions and
limitations under the License.
##############
Presigned URLs
##############
A user who does not have AWS credentials or permission to access an S3 object
can be granted temporary access by using a presigned URL.
A presigned URL is generated by an AWS user who has access to the object. The
generated URL is then given to the unauthorized user. The presigned URL can be
entered in a browser or used by a program or HTML webpage. The credentials
used by the presigned URL are those of the AWS user who generated the URL.
A presigned URL remains valid for a limited period of time which is specified
when the URL is generated.
.. code-block:: python
import logging
import boto3
from botocore.exceptions import ClientError
def create_presigned_url(bucket_name, object_name, expiration=3600):
"""Generate a presigned URL to share an S3 object
:param bucket_name: string
:param object_name: string
:param expiration: Time in seconds for the presigned URL to remain valid
:return: Presigned URL as string. If error, returns None.
"""
# Generate a presigned URL for the S3 object
s3_client = boto3.client('s3')
try:
response = s3_client.generate_presigned_url('get_object',
Params={'Bucket': bucket_name,
'Key': object_name},
ExpiresIn=expiration)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL
return response
The user can download the S3 object by entering the presigned URL in a browser.
A program or HTML page can download the S3 object by using the presigned URL
as part of an HTTP GET request.
The following code demonstrates using the Python ``requests`` package to
perform a GET request.
.. code-block:: python
import requests # To install: pip install requests
url = create_presigned_url('BUCKET_NAME', 'OBJECT_NAME')
if url is not None:
response = requests.get(url)
Using presigned URLs to perform other S3 operations
===================================================
The main purpose of presigned URLs is to grant a user temporary access to an
S3 object. However, presigned URLs can be used to grant permission to perform
additional operations on S3 buckets and objects.
The ``create_presigned_url_expanded`` method shown below generates a presigned
URL to perform a specified S3 operation. The method accepts the name of the S3
``Client`` method to perform, such as 'list_buckets' or 'get_bucket_location.'
The parameters to pass to the method are specified in the
``method_parameters`` dictionary argument. The HTTP method to use (GET, PUT,
etc.) can be specified, but the AWS SDK for Python will automatically select
the appropriate method so this argument is not normally required.
.. code-block:: python
import logging
import boto3
from botocore.exceptions import ClientError
def create_presigned_url_expanded(client_method_name, method_parameters=None,
expiration=3600, http_method=None):
"""Generate a presigned URL to invoke an S3.Client method
Not all the client methods provided in the AWS Python SDK are supported.
:param client_method_name: Name of the S3.Client method, e.g., 'list_buckets'
:param method_parameters: Dictionary of parameters to send to the method
:param expiration: Time in seconds for the presigned URL to remain valid
:param http_method: HTTP method to use (GET, etc.)
:return: Presigned URL as string. If error, returns None.
"""
# Generate a presigned URL for the S3 client method
s3_client = boto3.client('s3')
try:
response = s3_client.generate_presigned_url(ClientMethod=client_method_name,
Params=method_parameters,
ExpiresIn=expiration,
HttpMethod=http_method)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL
return response
Generating a presigned URL to upload a file
===========================================
A user who does not have AWS credentials to upload a file can use a
presigned URL to perform the upload. The upload operation makes an HTTP POST
request and requires additional parameters to be sent as part of the request.
.. code-block:: python
import logging
import boto3
from botocore.exceptions import ClientError
def create_presigned_post(bucket_name, object_name,
fields=None, conditions=None, expiration=3600):
"""Generate a presigned URL S3 POST request to upload a file
:param bucket_name: string
:param object_name: string
:param fields: Dictionary of prefilled form fields
:param conditions: List of conditions to include in the policy
:param expiration: Time in seconds for the presigned URL to remain valid
:return: Dictionary with the following keys:
url: URL to post to
fields: Dictionary of form fields and values to submit with the POST
:return: None if error.
"""
# Generate a presigned S3 POST URL
s3_client = boto3.client('s3')
try:
response = s3_client.generate_presigned_post(bucket_name,
object_name,
Fields=fields,
Conditions=conditions,
ExpiresIn=expiration)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL and required fields
return response
The generated presigned URL includes both a URL and additional fields that
must be passed as part of the subsequent HTTP POST request.
The following code demonstrates how to use the ``requests`` package with a
presigned POST URL to perform a POST request to upload a file to S3.
.. code-block:: python
import requests # To install: pip install requests
# Generate a presigned S3 POST URL
object_name = 'OBJECT_NAME'
response = create_presigned_post('BUCKET_NAME', object_name)
if response is None:
exit(1)
# Demonstrate how another Python program can use the presigned URL to upload a file
with open(object_name, 'rb') as f:
files = {'file': (object_name, f)}
http_response = requests.post(response['url'], data=response['fields'], files=files)
# If successful, returns HTTP status code 204
logging.info(f'File upload HTTP status code: {http_response.status_code}')
The presigned POST URL and fields values can also be used in an HTML page.
.. code-block:: html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<!-- Copy the 'url' value returned by S3Client.generate_presigned_post() -->
<form action="URL_VALUE" method="post" enctype="multipart/form-data">
<!-- Copy the 'fields' key:values returned by S3Client.generate_presigned_post() -->
<input type="hidden" name="key" value="VALUE" />
<input type="hidden" name="AWSAccessKeyId" value="VALUE" />
<input type="hidden" name="policy" value="VALUE" />
<input type="hidden" name="signature" value="VALUE" />
File:
<input type="file" name="file" /> <br />
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
</body>
</html>