概要
パブリックアクセスを無効化しているS3に保存しているオブジェクトに対して、一時的にアクセスを許可したい場合がある。
例えば、認証されたユーザーのみにファイルのダウンロードを許可したい場合など。
そんなときは、S3の署名付きURL(presigned URLs)を使用する。
署名付きURL(presigned URL)とは
署名済み URL は、セキュリティ認証情報を使用してオブジェクトをダウンロードするアクセス許可を期限付きで付与します。署名付き URL をブラウザに入力するか、プログラムで使用してオブジェクトをダウンロードできます。署名付き URL で使用される認証情報は、URL を生成した AWS ユーザーのものです。
boto3を使用して署名付きURLを生成する
generate_presigned_url
メソッドで署名付きURLを生成できる。
渡してるパラメーターは以下。
-
ClientMethod (string)
事前署名するクライアントメソッド。
get_object
を指定するとダウンロード用のURLになる。
put_object
を指定するとアップロード用のURLになる。 -
Params (dict)
ClientMethodに渡されるパラメータ。
ResponseContentDisposition
: ファイルをWEBページとして表示するか、ダウンロードさせるか等を指定するためのヘッダー。attachment; filename="{object_key}"
を指定することで、ブラウザに対してS3のオブジェクト名でファイルをダウンロードさせることができる。 -
ExpiresIn (int)
署名済みURLの有効期間を指定する。
以下のコードで署名付きURLを生成
import boto3
from botocore.exceptions import NoCredentialsError
def lambda_handler(event, context):
s3_client = boto3.client('s3')
bucket_name = 'xxxxxxxxxxxxxxxx'
object_key = 'xxx.txt'
# 署名付きURLを生成
try:
url = s3_client.generate_presigned_url(
'get_object',
Params = {
'Bucket': bucket_name,
'Key': object_key,
'ResponseContentDisposition': f'attachment; filename="{object_key}"' # object_keyをダウンロード時のファイル名として指定
},
ExpiresIn=3600
)
return {
'statusCode': 200,
'body': url
}
except NoCredentialsError:
return {
'statusCode': 403,
'body': 'Credentials are not available.'
}
except Exception as e:
return {
'statusCode': 500,
'body': str(e)
}
上記コードを実行すると以下のURLが生成される。
(AWSAccessKeyId等は伏字にしてます)
https://bucket-name.s3.amazonaws.com/xxx.txt?response-content-disposition=attachment%3B%20filename%3D%22xxx.txt%22&AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&x-amz-security-token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&Expires=1741614318
見やすいように改行したものが以下。
https://bucket-name.s3.amazonaws.com/xxx.txt?
response-content-disposition=attachment%3B%20filename%3D%22xxx.txt%22
&AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX
&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&x-amz-security-token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&Expires=1741614318
generate_presigned_urlメソッドで指定したresponse-content-disposition
やExpires
がクエリパラメーターとして含まれていることが分かる。
署名付きURLが持つ権限について
署名付きURLが持つ権限は、署名付きURLを発行したIAMロール・IAMユーザーに依存する。
上記のPythonコードはLambdaで実行しているので、LambdaにアタッチしたロールがS3バケットに対する権限を持たない場合は、署名付きURLにアクセスしてもAccessDeniedとなる。
バケットポリシーでIP制限など、細かなアクセス制御が可能。