본문 바로가기

Newb/AWS

S3 미리 서명된 URL(Pre-signed url) 사용하기

반응형
CloudNet@ AHSS 스터디 1주차 (S3 보안) 진행 후 일부를 정리한 글 입니다.


AWS에서 S3를 사용하다 보면 사용자들이 외부에서 S3에 있는 파일들을 다운로드 받거나, 업로드를 하는 등 외부에서 S3를 이용해야하는 상황들이 발생합니다.
 

이때, 외부에서 S3에 있는 파일에 접근 해야할 때 보통 아래와 같은 방법들을 이용할 수 있습니다.

  1. S3를 외부에서 접근 하능하도록 퍼블릭 상태로 변경 한 후에 접근하기
  2. AWS SDK 이용하기 (IAM 권한 필요)
  3. AWS CLI 이용하기 (IAM 권한 필요)
  4. S3 웹사이트 호스팅
  5. CloudFront를 S3에 연결하여 CloudFront로 접근하는 방법
  6. Pre-signed URL 생성하여 접근하기
 1번의 경우에는 모든 사람들이 S3에 접근을 할 수 있기 때문에 웹사이트 같이 모두 접근이 필요한 경우가 아닌 경우에는 모든 것이 노출되므로 보안이 매우 취약해집니다.

 2번, 3번의 경우에는 IAM 권한을 이용하여 S3에 있는 파일들을 관리가 가능해지기 때문에 모든 사람들이 접근 가능한 1번과는 달리, 권한을 부여받은 사람들만 컨트롤이 가능해집니다.

 4번의 경우에는 정적인 웹사이트를 S3를 이용하여 웹 호스팅을 이용할 때 많이 사용하는 방법입니다.

 5번의 경우에는 4번의 환경에서 조금 더 나아가 CloudFront(CDN)의 OAC, OAI를 이용하여 보안을 강화한 구성이며, S3는 설정한 CloudFront에서는 연결이 가능하지만, S3에 다이렉트 연결은 불가하도록 설정하는 방법입니다.

마지막으로 6번의 경우에는 말 그대로 S3에 접근을 위한 미리 서명된 URL을 생성하여 S3에 접근을 할 수 있도록 하는 방법이며, URL 생성 시 버킷 이름, 객체키, HTTP 메서드, 만료 시간을 지정하여 생성하게 됩니다.

테스트 진행 할 S3 버킷 생성

테스트를 진행할 버킷을 생성합니다.
저는 테스트 버킷의 이름을 bucket-pre-test로 생성하였습니다.
 

테스트 파일 생성

## S3에 업로드 할 test.txt 파일 생성
echo "Pre-signed URL Test File" > test.txt

## test.txt 파일 내용 확인
cat test.txt
Pre-signed URL Test File

테스트 파일 S3 버킷에 업로드

업로드 버튼을 클릭하여 생성한 test.txt 파일을 업로드 합니다.
 

업로드 한 파일 접속 해보기

 
업로드한 파일을 클릭하면 업로드한 파일의 객체 URL을 확인 할 수 있으며, 권한이 있다면 이 URL로 업로드 한 파일에 접근이 가능합니다.

하지만 현재 아무 권한을 주지 않았기 때문에 접근 시 AccessDenied가 뜨며 접근이 불가능한 것을 확인 할 수 있습니다.

Pre-signed URL 생성

Pri-Signed URL을 생성하는 방법에도 여러가지 방법이 있습니다.
 
그중 가장 간단한 방법은 AWS S3 Console에서 진행하는 방법입니다.
 

방법 1.  AWS S3 Console

 
S3 버킷에 업로드한 파일을 클릭하여 오른쪽 상단의 "객체 작업" 메뉴를 클릭 -> "미리 서명된 URL과 공유"를 클릭하여 미리 서명된 URL을 생성합니다.

"미리 서명된 URL과 공유" 버튼을 클릭하게 되면 위와 같은 창이 뜨며, 만료 시간 설정이 필요 합니다.
저는 테스트이므로 30분으로 세팅해보겠습니다.
 
생성 된 미리 서명된 URL 주소

https://bucket-pre-test.s3.ap-northeast-2.amazonaws.com/test.txt?response-content-disposition=inline&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEMX%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDmFwLW5vcnRoZWFzdC0yIkcwRQIhAMyNV4Ir5OBIJqncwX2tjc4nxnUMFGAzQx4v3rR2KILDAiBQrcCMnxFMgQn4l522ngFTDzvdlS4XSwwV6jL31uhZWSrxAgiO%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAQaDDA5MjM0ODAzMzM4NSIML%2FfOpP6FeKz94MtcKsUCeql5HmxBOOAzX5KNO0RFqC2A6A33Nj5oVGQv4fAn3eyoczSQK0t%2B%2FAbcjUukskp%2FHXWPmq9eRbsWHrjf2t8phDXer%2FyIM3w0mXUPUmckwicqBZrffLm9zMxadh7IX7BV%2FxJx2VjYfHmxCb%2BszKuVGAqHl%2BEzVBZa1As%2BMvBpgAsL%2FR09336jkUN%2BBuhhLxFPk08XefO91ooRZMFa%2BQuil4K6HJ37CQYtigimZjaMcAV2lCo1hFzIXdn5pGH2m1Q84LbKoFo3V0ecKsBRTR5cL1K7nsmuZoigrQXTseoRv1omAX%2BjcsFRAXXyL9rcKjW5nmy9llQh88BYBTt4dAK6mcKk4bNEz1WMp6deEREOpXfG7hd7p%2BzTfFKfd9lkszvRroVnK%2FhSgwN%2BHisfCnxRSwRxl%2BK4IyDKJiaDKccIda5o13UReDD5pLKnBjqzAkdbhrVXuNINzwUByFwON7FWK75IH%2BzsJGd8E8%2Fn37Z7x1LB%2BRHxTyei4o56hcfQWxzM76T5ubHAqLc53XjUh%2FzwLb2fMxG6a5%2BKmaM0%2FQAgV4UIVIPYKJHsZp2VPNgcNVx78OF7pY5S%2F9Tn47FWdPEdf78kwdRbbpj7hh6GpC0zAazLjayWB9BF65G1xBiYXskfWC3p5vE5MLgKhZ4vbrMHsQe9ZcRmGp2q0yeXpq89G240m9UjQlfAxxW026gXrydENUGtK%2B382k6c8jg17IGLr4tRYIwWigOyVKheQugOiijhcyOyQO6rN7CBp%2F5xyVhZlS2fCRtvIOaUfr0mW4l4gyvRC1xCp%2FuJxD8tTEL678kVt8bqYekFtELeH%2BhQxEK%2BFvb3cbGF2cgQCBuanlOruCc%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20230828T133435Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1800&X-Amz-Credential=ASIARLAC7FFU4R4CIEHK%2F20230828%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Signature=fc91c99bf6a72308a58adb3f79449351c8e5b87a0a72d2f89e40ae96323ecb73

 
위의 주소로 접속을 하게 되면 접속이 불가하던 아까와는 다르게 접속이 가능해 진 것을 확인 할 수 있습니다.

 
미리 서명된 URL을 생성 할 때 만료 시간을 30분으로 세팅하였으니 30분 이후에는 AccessDenied가 뜨며 다시 접근이 불가능해 집니다.

 

방법 2. AWS CLI를 이용하여 Pre-signed URL 생성

이 방법은 서버에 AWS CLI를 설치하여 CLI를 이용한 방법이며, AWS CLI를 사용하기 위해서는 S3에 대해 권한이 있는 IAM 계정이 필요합니다.

AWS CLI 설치

AWS CLI는 아래의 문서에서 설치 방법을 확인 할 수 있습니다.
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html

최신 버전의 AWS CLI 설치 또는 업데이트 - AWS Command Line Interface

이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이

docs.aws.amazon.com

저는 Linux 환경이므로 아래의 명령어를 이용하여 AWS CLI를 설치해주겠습니다.

## AWS CLI 파일 다운로드
[root@localhost aws]# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

## AWS CLI 파일 압축 해제
[root@localhost aws]# unzip awscliv2.zip

## AWS CLI Install
[root@localhost aws]# ./install
You can now run: /usr/local/bin/aws --version

## AWS CLI Version Check
[root@localhost aws]# /usr/local/bin/aws --version
aws-cli/2.13.13 Python/3.11.4 Linux/5.14.0-162.6.1.el9_1.x86_64 exe/x86_64.rocky.9 prompt/off

## AWS CLI Configure Setting // IAM 계정 생성 후 진행
[root@localhost aws]# aws configure
AWS Access Key ID [None]:*********
AWS Secret Access Key [None]:********
Default region name [None]:ap-northeast-2
Default output format [None]:json

위에서 AWS configure 부분은 아래 IAM 계정을 생성 후 진행하시면 됩니다.

IAM 계정 생성

IAM -> 사용자 -> 사용자 생성을 클릭하여 사용자를 생성합니다.

 
생성한 IAM 계정을 이용하여 Pre-signed URL을 생성하려면 S3에 대한 권한이 필요합니다.
저는 테스트 이기 때문에 S3에 대한 Full Aceess 권한을 주었지만, 필요한 권한만 설정하는 것이 보안에는 더욱 바람직합니다.
 

 
IAM 계정에서 "보안 자격 증명" -> "액세스 키" -> "액세스 키 만들기"를 클릭하여 AWS CLI에서 사용할 액세스 키를 생성합니다.

 
액세스 키를 생성하게 되면 위의 창에서 액세스 키 / 비밀 액세스 키 확인이 가능합니다.
주의할 점으로 비밀 액세스 키의 경우 분실하거나, 잊어버리게 되면 확인이 불가하므로 csv파일 다운로드를 하여 보관하거나, 정보를 잘 정리해 놓는 것이 좋습니다.
 
이제 발급 된 액세스 키와 비밀 액세스 키를 AWS CLI에 등록하여 줍니다.
 

AWS CLI를 이용하여 Pre-signed URL 생성

AWS S3 presign 문서에서 조금 더 자세한 내용을 확인 할 수 있으며, 아래와 같이 Pre-signed URL을 생성합니다.

presign — AWS CLI 1.29.35 Command Reference

Note: You are viewing the documentation for an older major version of the AWS CLI (version 1). AWS CLI version 2, the latest major version of AWS CLI, is now stable and recommended for general use. To view this page for the AWS CLI version 2, click here. F

docs.aws.amazon.com

## AWS CLI Pre-signed URL 생성 방법
aws s3 presign s3://"버킷 이름"/"파일명" --expires-in 만료 값(초)

aws s3 presign s3://bucket-pre-test/test.txt --expires-in 300
https://bucket-pre-test.s3.ap-northeast-2.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIARLAC7FFUWRMRKHW3%2F20230828%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20230828T141252Z&X-Amz-Expires=300&X-Amz-SignedHeaders=host&X-Amz-Signature=9d32c27dbddf9fb7a4a61973c19cfabcd53743f803b1e88c9af59e44b61b60d7

생성 된 URL로 접속 시 정상적으로 S3 파일에 접근이 되는 것을 확인 할 수 있습니다.

방법 3. AWS SDK 이용하여 Pre-signed URL 생성

마지막으로는 AWS SDK를 이용하여 Pre-signed URL을 생성하는 방법입니다.
 
AWS SDK를 이용하여 .NET, Go, Java 등 다양한 언어를 이용하여 Pre-signed URL 생성이 가능하며,
이에 대한 정보는 Create a presigned URL for Amazon S3 using an AWS SDK 에서 확인이 가능합니다.
 
저는 파이썬을 이용하여 Pre-signed URL을 생성해보겠습니다.
파이썬을 이용하려면 파이썬용 AWS SDK인 Boto3 설치가 필요합니다.

Boto3 설치

[root@localhost aws]# pip install boto3

파이썬 파일 생성

[root@localhost aws]# cat <<EOF > pre-signed.py
> import argparse
import logging
import boto3
from botocore.exceptions import ClientError
import requests

logger = logging.getLogger(__name__)


def generate_presigned_url(s3_client, client_method, method_parameters, expires_in):
    """
    Generate a presigned Amazon S3 URL that can be used to perform an action.

    :param s3_client: A Boto3 Amazon S3 client.
    :param client_method: The name of the client method that the URL performs.
    :param method_parameters: The parameters of the specified client method.
    :param expires_in: The number of seconds the presigned URL is valid for.
    :return: The presigned URL.
    """
    try:
        url = s3_client.generate_presigned_url(
            ClientMethod=client_method,
            Params=method_parameters,
            ExpiresIn=expires_in
        )
        logger.info("Got presigned URL: %s", url)
    except ClientError:
        logger.exception(
            "Couldn't get a presigned URL for client method '%s'.", client_method)
        raise
    return url


def usage_demo():
    logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

    print('-'*88)
    print("Welcome to the Amazon S3 presigned URL demo.")
    print('-'*88)

    parser = argparse.ArgumentParser()
    parser.add_argument('bucket', help="The name of the bucket.")
    parser.add_argument(
        'key', help="For a GET operation, the key of the object in Amazon S3. For a "
                    "PUT operation, the name of a file to upload.")
    parser.add_argument(
        'action', choices=('get', 'put'), help="The action to perform.")
    args = parser.parse_args()

    s3_client = boto3.client('s3')
    usage_demo()__main__':t)ponse.status_code}")n your computer.") the key must be the "
> EOF

파이썬으로 Pre-signed URL 생성

python3 pre-signed.py "버킷명" "파일 이름" "메소드"

[root@localhost aws]# python3 pre-signed.py bucket-pre-test test.txt get
----------------------------------------------------------------------------------------
Welcome to the Amazon S3 presigned URL demo.
----------------------------------------------------------------------------------------
INFO: Found credentials in shared credentials file: ~/.aws/credentials
INFO: Got presigned URL: https://bucket-pre-test.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIARLAC7FFUWRMRKHW3%2F20230828%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20230828T144537Z&X-Amz-Expires=1000&X-Amz-SignedHeaders=host&X-Amz-Signature=b515a16263ca3a2287273b45869451798c57f9439996609376db6002f985a215
Using the Requests package to send a request to the URL.
Got response:
Status: 200
Pre-signed URL Test File

----------------------------------------------------------------------------------------

 
위의 생성된 URL로 접속을 하면 정상적으로 접근이 되는 것을 확인 할 수 있습니다.

 

참고 자료

  1. 미리 서명된 URL을 사용하여 요청자별 Amazon S3 사용량 식별
  2. S3에서 pre-signed url(미리 서명된 url) 만들기

 
 

반응형