S3の署名付きURLを利用するとプライベートなS3コンテンツを有効期限付きで公開することが可能になります。
S3の署名付きURLを発行する際には、認証情報が必要になりますがやり方は以下のようにいくつかあります。
AWS Identity and Access Management (IAM) インスタンスプロファイル: 最大 6 時間有効
AWS Security Token Service (STS): 最大 36 時間有効 (AWS アカウントユーザーや IAM ユーザーの認証情報など、永続的認証情報を使用して署名した場合)
IAM ユーザー: 最大 7 日間有効 (AWS 署名バージョン 4 を使用した場合)
引用元:Amazon S3 バケットの署名付き URL が、指定した有効期限より前に失効するのはなぜでしょうか?
今回はS3の署名付きURL発行用のIAMユーザを作成し、
そのユーザの認証情報を利用して署名付きURLを発行してみます。
作業の流れ
- 署名付きURLを発行する対象のS3バケットとオブジェクトの作成
- 署名付きURLを発行するための専用ユーザの作成
- SecretManagerで「2」で作成したユーザのアクセスキーとシークレットキー値を保存
- 署名付きURLを発行するLambda関数の作成
1. 署名付きURLを発行する対象のS3バケットとオブジェクトの作成
こちらは任意のS3バケットとオブジェクトを作成するだけで
デフォルトのままプライベートにしておけば良いので詳細は割愛します。
2.署名付きURLを発行するための専用ユーザの作成
S3の署名付きURLを発行する専用ユーザを作成します。
・プログラムによるアクセスにチェック
・AWS マネジメントコンソールへのアクセスはチェックしない
・セキュリティを向上させるために、以下のように対象の操作とバケットは制限した
IAMポリシーをアタッチする
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
],
"Resource": [
"arn:aws:s3:::your-bucket-name/*"
]
}
]
}
3.SecretManagerで「2」で作成したユーザのアクセスキーとシークレットキー値を保存
Lambdaから署名付きURLを発行するために「2」で作成した専用ユーザの
アクセスキー/シークレットキーが必要になります。
SecretManagerで管理し、Lambdaから取得出来るようにします。
4.署名付きURLを発行するLambda関数の作成
LambdaにはSecretManagerへの読み取り権限を付与します。
import boto3
import json
from botocore.client import Config
def lambda_handler(event, context):
REGION_NAME = 'ap-northeast-1'
S3_BUCKET_NAME = 'private-data-20210717'
S3_OBJECT_NAME = 'hello.html'
DURATION_SECONDS = 60*60*37
secret_name = "IAM-User-S3-PresigedURL"
region_name = "ap-northeast-1"
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name='secretsmanager',
region_name=region_name
)
get_secret_value_response = client.get_secret_value(
SecretId=secret_name)
secret = get_secret_value_response['SecretString']
secret_dict = json.loads(secret)
aws_access_key = secret_dict['ACCESS_KEY']
aws_secret_key = secret_dict['SECRET_KEY']
s3 = boto3.client(
service_name='s3',
aws_access_key_id=aws_access_key,
aws_secret_access_key=aws_secret_key,
region_name=region_name,
config=Config(signature_version='s3v4')
)
url = s3.generate_presigned_url(ClientMethod = 'get_object',
Params = {'Bucket' : S3_BUCKET_NAME, 'Key' : S3_OBJECT_NAME},
ExpiresIn = DURATION_SECONDS,
HttpMethod = 'GET')
print(url)
return {
'statusCode': 200,
'statusDescription': '200 OK',
'isBase64Encoded': False,
'headers': {
'Content-Type': 'text/html; charset=utf-8'
},
'body': '{}\n'.format(url)
}
参考URL
・別の AWS アカウントからロールを引き受けるように Lambda 関数を設定するにはどうすれば良いですか?
以上