전 세계에 콘텐츠를 배포하는 CDN 서비스인 CloudFront

이재홍 http://www.pyrasis.com 2014.03.24 ~ 2014.06.30

Signed URL로 CloudFront 콘텐츠 사용 제한하기

Signed URL은 CloudFront로 배포되는 파일의 사용을 제한하는 기능입니다. Signed URL은 특정 날짜가 지나면 파일을 받지 못하게 하고 싶을 때, 특정 날짜 이후에 파일을 받게 하고 싶을 때, 특정 IP에서만 파일을 받을 수 있도록 할 때 사용합니다.

Signed URL은 크게 2가지가 있습니다.

  • Canned Policy를 사용한 Signed URL: 파일 1개의 사용을 제한합니다. 또한, 특정 날짜가 지나면 파일을 받지 못하게 하는 기능만 사용할 수 있습니다. 정책(Policy)의 내용이 URL에 포함되어 있지 않아 URL의 길이가 짧습니다.
  • Custom Policy를 사용한 Signed URL: 파일 여러 개의 사용을 제한합니다. 특정 날짜가 지나면 파일을 받지 못하게 하는 기능, 특정 날짜 이후에 파일을 받을 수 있도록 하는 기능, 특정 IP 혹은 IP대역에서만 파일을 받을 수 있도록 하는 기능을 사용할 수 있습니다. 정책(Policy)의 내용이 URL에 포함되어 있어 URL의 길이가 깁니다.

다음은 Canned Policy를 사용한 Signed URL의 구조입니다.

http://d39hltbb812jpd.cloudfront.net/index.html?Expires=1399721576&Signature=MgYk5FP4wQHHrdSwgcLjrlpo4DoDX-4CbwmtUR3eRRwdyj-OLTZDfBplGlkMBTd5o8CAuvkAf3G5I5ip5tE4qK--zIFa-ufZsJqpdWsk9tr2nRFO8BBa3IYLRyUgyh0PeMlPx1sIAlJDiVSiCDF7SL4GAeSDKccoVayDbxAbknUhcV6vHbRBAJPqkw2H0aozEBtIUQEiIEX79pCoRfP6gFQA4yXf-GJxk3Lbwl0TgdWkSWramF1vAB06eoqDqOrq0koRAZDbTRiYloxm9a0DXI~hzQv7cdOrKYVTHpVGzqWueCLpDT~F9vIly6sOHyeynuT-POgAbBZ~fZC3CfTqSw__&Key-Pair-Id=APKAJERVTR4A7EO47UYA
  • http://d39hltbb812jpd.cloudfront.net: CloudFront 배포 URL입니다.
  • index.html: CloudFront로 배포되는 파일입니다. 여기서는 index.html 파일을 예로 들었습니다. JPG, PNG 등의 그림 파일과 ZIP 등의 압축 파일을 비롯한 모든 파일에 적용 가능합니다.
  • Expires: 이 파일의 사용이 만료되는 날짜와 시간입니다. 이 날짜와 시간 규칙은 UTC(Coordinated Universal Time, 협정 세계 표준시)를 사용합니다. 이 UTC는 1970년 1월 1일 자정을 0으로 시작하여 특정 시간까지 밀리초(1000분의 1초)로 계산한 것입니다. 이 값은 사람이 직접 알아내기는 힘들며 프로그래밍 언어에서 간단하게 얻을 수 있습니다.
  • Signature: 파일 사용 제한을 정의하는 정책(Policy Statement) 파일의 내용을 CloudFront 개인 키(Private Key)로 서명한 해시 값입니다. 이 값은 BASE64로 인코딩 되어 있으며 +는 -로, =는 _로 /는 ~로 바뀌어져 있습니다.
  • Key-Pair-Id: CloudFront 전용 키 쌍(Key Pair)의 액세스 키(Access Key) 입니다. 이 액세스 키는 AWS 계정의 액세스 키와는 별개입니다.

다음은 Canned Policy 파일의 내용입니다. 이 파일에 정의한 대로 파일의 사용을 제한합니다. 그리고 이 정책 파일의 내용을 CloudFront 개인 키로 서명한 해시 값이 위에서 말한 Signature 값입니다.

{
  "Statement": [{
    "Resource": "http://d39hltbb812jpd.cloudfront.net/index.html",
    "Condition": {
      "DateLessThan": {
        "AWS:EpochTime": 1399721576
      }
    }
  }]
}
  • Resource: 파일의 경로입니다. 꼭 http://, https://, http*://로 시작해야 합니다. 쿼리 문자열(Query String)도 붙을 수 있습니다(예: hello.jpg?size=large&license=yes). 쿼리 문자열이 없을 경우 맨 뒤 ?는 삭제해야 합니다. 또한, Expires, Signature, Key-Pair-Id는 쿼리 문자열에 사용할 수 없습니다.
  • Condition: Signed URL이 동작할 조건을 지정합니다. Canned URL에서는 DateLessThan만 사용할 수 있습니다.
    • DateLessThan: 특정 날짜와 시간 이전에만 파일을 사용할 수 있도록 하는 조건입니다. AWS:EpochTime으로 설정하며 값은 UTC 형식입니다. Signed URL에서 Expires 파라미터의 값과 이곳에 설정한 값이 동일해야 Signed URL이 동작합니다. 이 조건은 필수입니다.

CloudFront 키 쌍과 AWS 키 쌍
CloudFront는 Signed URL을 위해 전용 키 쌍(Key Pair)과 액세스 키(Access Key) 필요합니다. Signed URL을 생성할 때 개인 키 사용하는데 이 개인 키는 서비스 환경이나 애플리케이션의 구현 방식에 따라 외부에 노출될 수 있습니다. 따라서 AWS 키 쌍과 분리된 별도의 키와 액세스 키를 사용하는 것입니다.

AWS 키 쌍은 절대 노출이 되어서는 안됩니다. 이 키 쌍이 외부에 노출되면 EC2 인스턴스에 자유롭게 접근할 수 있게 되기 때문에 매우 위험합니다.

다음은 Custom Policy를 사용한 Signed URL의 구조입니다.

http://d39hltbb812jpd.cloudfront.net/index.html?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovLyoiLCJDb25kaXRpb24iOnsiSXBBZGRyZXNzIjp7IkFXUzpTb3VyY2VJcCI6IjE4My45OC4zOC4yNDQifSwiRGF0ZUdyZWF0ZXJUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjEzOTg2ODg0ODZ9LCJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTM5OTcyMTU3Nn19fV19&Signature=C5DhUjOWy88Nbnb5s9XZiZtvR1GdP3jYYRzbnRQGtsbqi6wj8v2wdASOJv5GZ2dycTwS5Ld1~3h4JWfUo1afj5PBhqzQYlz~JxwK~IoimjiknBiurKU2H273064e4bkbr~VhLIDMTkIwNgE75UxiZCevtTttCVls7oPMAVOeBU656zu8dAfoTc1cSAP7BMTRzZn9xCqN9lIc9BTMGxH~Qu49yN4zMDJaQac0PNR60VWpDQQhtg1bPRgskN4XU7uM2DuzuHgSIua85HuzYEXJLOLnjEXQMdxQo-uK-zTk2QG72SmQ1PCHd8vs7y4Cm7RyRlo3JNtUT~VMUJTy04kduA__&Key-Pair-Id=APKAJERVTR4A7EO47UYA
  • http://d39hltbb812jpd.cloudfront.net: CloudFront 배포 URL입니다.
  • index.html: CloudFront로 배포되는 파일입니다. 여기서는 index.html 파일을 예로 들었습니다. JPG, PNG 등의 그림 파일과 ZIP 등의 압축 파일을 비롯한 모든 파일에 적용 가능합니다.
  • Policy: 파일 사용 제한을 정의하는 정책(Policy Statement) 파일의 내용을 BASE64로 인코딩한 값입니다. +는 -로, =는 _로 /는 ~로 바뀌어져 있습니다.
  • Signature: 파일 사용 제한을 정의하는 정책(Policy Statement) 파일의 내용을 CloudFront 개인 키(Private Key)로 서명한 해시 값입니다. 이 값은 BASE64로 인코딩 되어 있으며 +는 -로, =는 _로 /는 ~로 바뀌어져 있습니다.
  • Key-Pair-Id: CloudFront 전용 키 쌍(Key Pair)의 액세스 키(Access Key) 입니다. 이 액세스 키는 AWS 계정의 액세스 키와는 별개입니다.

다음은 Custom Policy 파일의 내용입니다. 이 파일에 정의한 대로 파일의 사용을 제한합니다. 그리고 이 정책 파일의 내용을 CloudFront 개인 키로 서명한 해시 값이 위에서 말한 Signature 값입니다.

{ 
  "Statement": [{ 
    "Resource":"http://*",
    "Condition":{ 
      "IpAddress":{"AWS:SourceIp":"192.0.2.10/32"},
      "DateGreaterThan":{"AWS:EpochTime":1398688486},
      "DateLessThan":{"AWS:EpochTime":1399721576}
    } 
  }] 
}
  • Resource: 파일의 경로입니다. 꼭 http://, https://, http*://로 시작해야 합니다. http://* 처럼 모든 파일을 지정할 수도 있고, http://*.pdf 처럼 확장자를 지정할 수도 있습니다. 또한, 쿼리 문자열(Query String)도 붙을 수 있습니다(예: hello.jpg?size=large&license=yes). 쿼리 문자열이 없을 경우 맨 뒤 ?는 삭제해야 합니다. 또한, Expires, Signature, Key-Pair-Id는 쿼리 문자열에 사용할 수 없습니다.
  • Condition: Signed URL이 동작할 조건을 지정합니다. Custom URL에서는 DateLessThan, DateGreaterThan, IpAddress를 사용할 수 있습니다.
    • DateLessThan: 특정 날짜와 시간 이전에만 파일을 사용할 수 있도록 하는 조건입니다. AWS:EpochTime으로 설정하며 값은 UTC 형식입니다. Signed URL에서 Expires 파라미터의 값과 이곳에 설정한 값이 동일해야 Signed URL이 동작합니다. 이 조건은 필수입니다.
    • DateGreaterThan: 특정 날짜와 시간 이후에 파일을 사용할 수 있도록 하는 조건입니다. AWS:EpochTime으로 설정하며 값은 UTC 형식입니다.
    • IpAddress: 특정 IP 주소에서 파일을 사용할 수 있도록 하는 조건입니다. AWS:SourceIp로 설정하며 공인 IP를 지정해야 합니다. CIDR 형식으로 IP 대역을 지정할 수도 있습니다.

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.