AWS CloudFront와 S3로 Private Content 전달 방법 기술 이야기 2018.04.24 21:08

AWS S3CloudFront를 이용해서 허가된 사람에게만, 제한된 시간동안만 이미지나 미디어 파일을 웹 스토리지를 통해서 공유할 때 유용한 기술(?)을 정리해 본다.

내가 즐겨 사용하는 가장 간단한 방법은 signature를 포함하는 signed URL을 생성해서 공유하는 방식이고, 자세한 내용은 아래 가이드에 자세히 나와있다. 나의 글은 가이드에 나와있는 내용을 간략하게 요약하고, 경험을 곁들인 후기라고 보면 좋을 것 같다! :)

CloudFront를 통한 프라이빗 콘텐츠 제공


전체적인 그림

일단, 간략하게 구성을 소개하면 S3는 웹 스토리지이고, CloudFront는 글로벌 컨텐츠 전송 네트워크(CDN)이다. S3는 높은 신뢰성과 안정성을 제공하고, CloudFront는 전세계 어디서나 빠른 속도로 접속 할 수 있도록 해준다. 두 서비스를 함께 사용하는 것은 여러가지 측면에서 환상의 조합으로, 다양한 장점을 얻을 수 있다.


소개하려고 하는 Private Content 전달 방법도 S3CloudFront의 역할을 분리해서 원하는 목표를 달성하고 있다. 우선, 데이터는 S3에 저장하고, 그 데이터에 접속하는 권한은 CloudFront에게 할당하며, CloudFront는 URL 또는 쿠키에 달려있는 signature를 확인 후 데이터의 접근 여부를 결정하는 방식이다.

작업 내용

가이드에 나와있는 작업내용을 쭈욱 적고, 주의할 점이나 부가 설명을 추가해보겠다.

사전 작업

당연히, S3에 컨텐츠가 있어야하고, S3에서 컨텐츠에 접근 권한을 모두 제거한다. Public으로 해두면 아무나 접근 가능.

S3CloudFront에서 Origin으로 표시되고, Origin 탭에서 설정 변경이 가능한데, 여기에서 Restrict Bucket AccessYes로 선택해서 접근을 제한한다. S3에서도 접근 권한을 설정해주고, CloudFront에서도 해줘야 한다. Your Identities 항목이 중요한데, 내가 생성한 Cloudfront Distribution이 연결된S3에 접근하는 계정에 대한 설정이다. S3의 Bucket 설정에서도 반드시 권한을 추가해 줘야 Access Denied에러가 나지 않는다. 권한을 추가할 때는 Canonical User ID가 필요한데, Origin Access Identity 메뉴로 진입하면 계정별 ID를 확인 할 수 있다. 그 아래 버킷 정책 업데이트 부분이 있는데, 자동 업데이트로 설정해두는 것을 권장한다.

본 작업

사전 작업은 접근 권한에 대한 설정을 해둔 것이고, 본 작업에서는 제한된 접근을 어떤 방법으로 특정인에게만 허용할 것인가에 대한 내용이다. 나는 signed URL을 생성하는 방법을 사용했다. 이 방법은 접근하고자 하는 리소스 URL에 사전 등록된 RSA 키로 만들어진 signature를 쿼리파라미터에 붙여 넣는 것이다.

키페어 생성 / 등록

RSA 키 페어를 생성하여 CloudFront에 등록한다. 당연히 개인키는 signed URL을 만들때 사용되며, EC2SSH 접속할 때 사용하는 key와는 다르다. 웹서버나 ElasticBeanstalk 환경변수등에 저장하고 있어야 한다. 등록된 Key ID는 signed URL 마지막에 포함된다.

정책 선택

사전에 준비된(Canned) 정책을 사용하거나 직접 만들어서 사용할 수 있는데, 현재는 사전에 준비된 정책으로는 접근 만료 시간만 정할 수 있다. 정책의 구조는 다른 AWS에서와 비슷하다. 어렵지는 않지만 필요하지는 않아서 만들어 보지는 않았다.

//정책은 아래와 같은 JSON Format이다. AWS에서 익숙한 모양이다.
{
    "Statement": [
        {
            "Resource":"URL or stream name of the object",
            "Condition":{
                "DateLessThan":{"AWS:EpochTime":required ending date and time in Unix time format and UTC},
                "DateGreaterThan":{"AWS:EpochTime":optional beginning date and time in Unix time format and UTC},
                "IpAddress":{"AWS:SourceIp":"optional IP address"}
            }
        }
    ]
}

등록된 RSA 키로 정책을 서명해서 Signed URL 만들기

위에서 등록된 RSA 키로 정책의 해쉬를 서명하고 base64로 인코딩 하면 signature가 되어 쿼리파라미터에 &signature=로 추가된다. 사용한 서명키의 공개키 ID는 &Key-Pair-Id=로 추가된다.

canned policy를 사용하는 경우는 &Expires=항목에 접근 만료 시간을 넣어서 추가하고, custom policy를 사용하는 경우는 직접 생성한 정책을 &Policy=에 넣어서 추가하여 signed URL을 만들면 끝이다. 내용을 자세히 이해하려면 되게 복잡해 보이지만 SDK를 사용하면 아주 쉽게 만들수 있다!ㅎ

Tip!

ElasticBeanstalk에서 개인키를 환경변수에 저장해서 사용할 수 있다. code에 키가 들어가면 안되니까 file이나 S3를 사용하기도 하는데, ElasticBeanstalk 사용한다면 환경변수에 넣는게 짱 편하다. 이때 줄바꿈이 중요한데, nodejs 사용할 때는 \n을 넣어주고 실제 코드에서는 아래와 같이 처리해주면 된다!

Private Key in Environment Variable
Creating Amazon CloudFront Signed URLs in Node.js

후기

내용을 천천히, 꼼꼼히 읽으면 잘 만들어 놨다는 감탄과 함께 충분히 이해하는데 시간이 좀 걸리는데 막상 코드 작업과 콘솔에서의 설정을 직접 해보면 너무 간단하다!!! 너무 간단해서 허무할 정도다! AWS는 항상 그런식이다. 강력하고 다양한 기능을 제공하는데 막상 설정하는 거나 코드양이 너무 작아서 허무하다.ㅋㅋㅋ

티스토리 툴바