Cloudfront와 s3를 연결한 환경에서 CORS를 설정하는 방법을 알아본다.


Index

  1. Intro
  2. s3 CORS 구성
  3. Cloudfront 캐시 정책
  4. 간단한 CORS 요청을 위한 설정
  5. CORS 요청을 위한 설정

Intro

30분 투자로 CORS 전문가로 성장하기 세미나에서 사용했던 발표 자료를 정리해서 포스팅한다. 해당 포스트에서는 발표의 두번째 꼭지 였던 Cloudfront와 s3를 연결한 환경에서 CORS 설정 방법을 알아본다. 처음에는 s3의 CORS 구성, Cloudfront의 캐시 정책을 알아보고 간단한 CORS 요청과 CORS 요청을 위한 설정 방법을 알아본다.

현재 s3를 오리진 서버로 쓰고 있고 cloudfront를 CDN 서버, 즉 캐시 서버로 사용하고 있다. 이럴 경우 CORS를 위한 설정을 s3와 cloudfront 두 곳에서 해줘야 한다. best practice로 들어가기 전에 두 서비스의 설정에 대해 알아보겠다.


s3 CORS 구성

CORS 구성은 s3 버킷에 엑세스 할 수 있도록 허용할 오리진과 각 오리진에 대해 지원되는 HTTP 메서드 및 기타 작업별 정보를 식별하는 규칙이 포함된 문서이다.

예시 4) 모든 것을 허용하는 CORS 구성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[
    {
        "AllowedMethods": [
            "*"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "AllowedHeaders": [
            "*"
        ],
        "ExposeHeaders": [
            "*"
        ]
    }
]


AllowedMethods

CORS 요청에서 허용되는 HTTP 메서드를 설정한다. 응답 헤더의 Access-Control-Allow-Method에 들어가는 값을 관리한다. Support 하는 HTTP 메서드는 아래와 같다.

  • GET
  • PUT
  • POST
  • DELETE
  • HEAD

OPTIONS가 없어서 의아할 수 있다. AllowedMethods 는 리소스를 위한 실제 요청을 보낼 때 사용할 수 있는 Method를 설정하는 것이기 때문에 여기서는 prefligjt를 위한 설정을 하지 않는다.


AllowedOrigins

Cross-Origin 요청을 허용하는 오리진을 지정한다. AllowedOrigins 가 응답 헤더의 Access-Control-Allow-Origin에 들어가는 값을 관리한다. 여기처럼 와일드카드를 넣으면 Access-Control-Allow-Origin에 항상 와일드카드가 들어간다.


AllowedHeaders

요청에 허용되는 헤더를 지정한다. AllowedHeaders 가 응답 헤더의 Access-Control-Allow-Header에 들어가는 값을 관리한다.


ExposeHeaders

응답 헤더의 Access-Control-Expose-Headers에 들어가는 값을 관리한다.


s3 버킷이 브라우저 요청의 CORS 구성을 평가하는 방법

브라우저에서 보낸 요청이 s3의 CORS 구성에 적합해야 Cross-Origin 요청이 허용될 수 있다. s3 버킷은 아래의 방법으로 브라우저 요청의 CORS 구성을 평가한다.

[Picture 1] 비교 표

Cloudfront 캐시 정책

캐시 정책

CORS와 큰 관련이 없다.

cloudfront 엣지 로케이션에 캐싱되는 객체의 캐시 키를 제어할 수 있다. 캐시 키는 캐시에 있는 모든 객체의 고유 식별자로, 최종 사용자(가장 최근에 요청을 보낸 사용자) 요청이 캐시 적중이 될 것인지 여부를 결정한다.

캐시 적중은 최종 사용자의 요청이 이전 요청과 동일한 캐시 키를 생성하고, 해당 캐시 키의 객체가 엣지 로케이션 캐시에 있으며, 그 캐시가 유효한 상태일 때 발생한다.

캐시 정책에서는 cloudfront 캐시의 객체가 유효한 상태를 유지하는 기간을 결정하는 TTL과 캐시 키 설정을 설정할 수 있다.


오리진 요청 정책

여기서 오리진은 Origin 헤더의 오리진이 아니다. AWS 에서 cloudfront에 연결이 되어있는 원본 서버를 오리진이라고 한다.

cloudfront에서 최종 사용자 요청이 miss 되면 cloudfront는 오리진에 요청을 보내 객체를 검색한다. 여기서 오리진은 s3이고, 이런 요청을 오리진 요청이라고 한다. 오리진 요청에는 URL 경로, 요청 본문, cloudfront에서 오리진 요청을 보낼 때 자동으로 포함하는 X-Ams-Cf-Id 등의 정보가 항상 포함된다. HTTP 헤더 및 쿠기와 같은 최종 사용자의 기타 정보는 오리진 요청에 포함되지 않는다.

오리진 요청에 커스텀 헤더 등의 특정 헤더를 포함해서 보내고 싶다면 오리진 요청 정책을 설정하면 된다. 간단한 요청의 경우 preflight를 보내지 않기 때문에 오리진 요청 정책을 설정하지 않아도 된다. 하지만 AWS에서는 간단한 요청일 때도 설정하는 것을 권장하고 있다.


[Picture 2] AWS 관리현 오리진 요청 정책

응답 헤더 정책

응답 헤더 정책을 사용해서 사용자에게 보내는 응답에 HTTP 헤더를 수정할 수 있다. 이를 통해 cloudfront는 최종 사용자에게 응답을 보내기 전에 서버에서 수신한 헤더를 제거하거나 헤더를 추가할 수 있다. 아래의 값들을 응답 헤더 정책을 통해 조작할 수 있다.

  • 메타 데이터 - 이름, 설명 등을 포함한다.
  • CORS 헤더
  • 보안 헤더
  • 사용자 지정 헤더
  • Server-Timing - cloudfront 지표를 만들기 위한 용도이다.

한가지 주의할 점은 cloudfront 응답 헤더 정책에 있는 Access-Control-Allow-Origin은 s3에 설정한 CORS 구성과 맞추는 게 좋다. 예를 들어 cloudfront 응답 헤더에는 *가 있고, s3 CORS에서는 *가 없다면 클라이언트는 어떤 응답 헤더를 받게 될까?

[Picture 3] Cloudfront 응답 헤더 정책과 CORS 구성이 다를 때

access-control-allow-origin이 *로 설정되어 응답헤더가 내려갔다. 오리진인 s3의 CORS 구성과 다른 헤더가 내려간 것이다. cloudfront에 응답 헤더 정책을 설정하지 않았다면 s3 CORS 정책에 설정한 대로 응답 헤더가 만들어지지만 cloudfront 응답 헤더 정책을 설정했다면 cloudfront의 응답 헤더 정책을 우선시 하게 된다.


cloudfront와 s3 정책이 다를 때의 문제

  1. cloudfront에 캐시가 되어있을 때는 s3까지 가지 않기 때문에 허용이 안된 Origin도 리소스를 가져간다.
  2. cloudfront 캐시가 만료되면 오리진인 s3에 다녀오고, 허용하지 않은 Origin이라서 CORS error가 발생한다.

결과적으로 CORS error가 발생했다, 발생하지 않았다하는 이상한 버그를 만들게 된다.


간단한 CORS 요청을 위한 설정

간단한 요청의 경우, preflight를 날리지 않기 때문에 이 부분에 대한 설정을 별도로 해주지 않아도 된다. 때문에 설정이 비교적 간단해진다.

s3

Step 1: CORS 정책을 추가해준다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "http://exchange.staging.kasa.sg",
            "https://exchange.staging.kasa.sg",
            "http://*.exchange.staging.kasa.sg",
            "https://*.exchange.staging.kasa.sg",
            "*"
        ],
        "ExposeHeaders": []
    }
]

Cloudfront

Step 1: 응답 헤더 정책을 설정한다.

Cloudfront의 응답 헤더 정책은 Cloudfront가 캐시된 응답에 추가적인 헤더를 포함시키는 역할을 한다. 여기서 조작한대로 클라이언트가 응답 헤더를 받게 된다.

[Picture 4] Response Header Policy in Cloudfront behavior

[Picture 5] Response Header Policy

cloudfront 응답 헤더 정책에 Access-Control-Allow-Origin과 cache-control 등의 응답 헤더 값을 설정해줬다.


CORS 요청을 위한 설정

s3

간단한 CORS 요청인 경우와 동일하게 설정한다.


Cloudfront

Step 1: 응답 헤더 정책을 설정한다.

간단한 CORS 요청인 경우와 동일하게 설정한다.


Step 2: cloudfront 동작에서 Allowed HTTP methods를 수정해준다.

preflight는 HTTP Method OPTIONS로 보내지기 때문에 Allowed HTTP methods를 OPTIONS이 포함된 선택지로 변경해야 한다.

[Picture 6] Allow Method in Cloudfront Behavior

step 3: 오리진 요청 정책을 설정한다.

CORS 관련 요청 헤더를 오리진 요청을 보낼 때도 넘겨줄 수 있도록 오리진 요청 정책을 설정한다.

[Picture 7]Origin Request Policy in Cloudfront Behavior

[Picture 8] Origin Requset Policy