S3에 파일을 업로드/다운로드 하기 위한 방법으로는 여러가지가 있다. 그 중에서도 Presigned Url(미리 서명된 URL)을 사용하면, S3버킷이 있는 계정의 IAM User/Role정보를 갖고 있지 않아도 버킷에 접근하도록 할 수 있다.
아래는 AWS 공식문서의 설명이다.
모든 객체 및 버킷은 기본적으로 프라이빗입니다. 그러나 미리 서명된 URL을 사용하여 선택적으로 객체를 공유하거나 고객/사용자가 AWS 보안 자격 증명이나 권한 없이 버킷에 객체를 업로드하는 것을 허용할 수 있습니다.
미리 서명된 URL을 사용하면 Amazon S3 버킷에 액세스하는 데 사용할 수 있는 URL을 생성할 수 있습니다. 미리 서명된 URL을 생성하면 특정 작업과 연결됩니다. URL을 공유할 수 있으며 URL에 액세스할 수 있는 모든 사용자는 원래 서명 사용자인 것처럼 URL에 포함된 작업을 수행할 수 있습니다. URL이 만료되어 만료 시간에 도달하면 더 이상 작동하지 않습니다.
Presigned URL은 작업 수행 권한을 가진 사용자가 생성해야 한다. 아래의 세개 자격증명 중 하나를 사용하면 된다.
- IAM 인스턴스 프로파일: 최대 6시간 동안 유효함.
- AWS Security Token Service: AWS 계정 계정 루트 사용자 또는 IAM 사용자의 자격 증명과 같은 영구 자격 증명을 통해 서명된 경우 최대 36시간 동안 유효함.
- IAM 사용자: AWS 서명 버전 4를 사용할 경우 최대 7일 동안 유효함.
최대 7일 동안 유효한 Presigned URL을 만들려면 사용 중인 SDK에 IAM 사용자 자격 증명(액세스 키 및 보안 키)을 먼저 지정합니다. 그런 다음 AWS 서명 버전 4를 사용하여 Presigned URL을 생성합니다.
여기서는 권한이 부여된 IAM Role을 가진 Lambda에서 AWS SDK를 이용해 URL을 생성한다.
💡 S3 버킷은 기존의 것을 사용한다.
AWS CLI를 이용하여 Lambda함수에서 사용할 S3 접근권한이 부여된 IAM Role을 생성한다.
- Lambda 서비스에 대한 신뢰정책 파일 작성
#trustpolicyforlambda.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
}
}
]
}
- 리소스 접근을 위한 권한 정책 파일 작성
#permissionpolicyforlambda2s3.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*",
"s3-object-lambda:*"
],
"Resource": "arn:aws:s3:::da-bucket-for-test"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
AWS CLI 명령어로 Role을 생성한다.
#신뢰정책으로 role 생성
aws iam create-role --role-name lambda-role-to-access-s3 --assume-role file://./role/trustpolicyforlambda.json
#권한정책을 role에 추가
aws iam put-role-policy --role-name lambda-role-to-access-s3 --policy-name lambda-policy-to-access-s3 --policy-document file://./policy/permissionpolicyforlambda2s3.json
이제 생성한 Role을 가지고 Presigned Url을 생성해 줄 Lambda함수를 만들어준다.
콘솔에서 람다함수 생성할 때, 실행 역할에 위에서 생성한 role을 선택해 준다.
이번에는 객체 업로드를 위한 Presigned Url을 생성하는 코드를 작성한다.
아래 작성된 코드는 Api Gateway를 트리거로 지정하고 Post API를 사용하여 람다에 파라미터를 전달하며 호출하도록 하도록 구성되어 있다.
import json
import os
import boto3
from botocore.exceptions import ClientError
def generate_presigned_url(s3_bucket_name,filename):
s3_client = boto3.client('s3')
client_action = 'put_object'
method_parameters = {'Bucket': s3_bucket_name, 'Key': filename}
try:
presigned_url = s3_client.generate_presigned_url(
clientMethod=client_action,
Params=method_parameters
#[optional]The number of seconds the presigned URL is valid for.
ExpiresIn=3600
)
except ClientError:
raise ClientError("Couldn't get a presigned URL for s3 bucket '%s'.", s3_bucket_name)
return presigned_url
def lambda_handler(event, context):
s3_bucket_name = os.environ['s3_bucket_name']
params_array = event['params']
path_array = params_array['path']
filename = path_array['filename']
model_name = path_array['model-name']
presigned_url = generate_presigned_url(s3_bucket_name,filename)
# TODO implement
return {
"upload_url": presigned_url
}
'Amazon AWS > S3' 카테고리의 다른 글
Amazon S3 스토리지 클래스 정리 (0) | 2023.05.21 |
---|---|
S3의 불필요한 객체들을 정리하도록 Lambda 작성 (0) | 2023.03.13 |
AWS Athena를 사용해서 S3의 데이터에 쿼리 쓰기 (0) | 2022.11.20 |
Cloudwatch의 로그 S3 백업을 자동화 하기(w/ AWS Lambda) (0) | 2022.10.08 |