2017년 6월 12일 월요일

[AWS] AWS S3를 이용한 static website hosting에서 Custom Domain과 HTTPS(SSL) 사용하기

AWS S3를 이용한 static website hosting에서 Custom Domain과 HTTPS(SSL) 사용하기


지금은 많은 사람들이 알고 있듯이, AWS S3를 이용하면 단순 파일 저장뿐 아니라 정적 웹호스팅(static website hosting)이 가능합니다.
그런데, 한가지 아쉬운 점은 S3에 업로드한 객체들 각각의 endpoint는 https가 기본지원되는 반면에, web hosting의 endpoint는 http만 지원하고 있습니다.
하지만 AWS CloudFront를 이용하면 S3의 web hosting에도 https를 사용하게 할 수 있습니다.
이번 포스팅에서는 S3를 이용한 static website hosting에서 Custom Domain과 HTTPS(SSL) 사용하는 방법을 정리해보겠습니다.

0. 사용하는 AWS 서비스

이번 포스팅에서는 4가지 AWS 서비스를 사용합니다.
  • Certificate Manager
    • SSL 인증서 생성.
  • S3
    • 웹호스팅 Origin.
  • CloudFront
    • 웹호스팅 파일들을 CDN에 올리고 SSL을 적용. 그리고 Custom Domain 설정.
  • Route53
    • CloudFront에 배포한 웹호스팅 도메인과 Custom Domain을 연결.

1. SSL 인증서 준비

본 포스팅에서는 HTTPS를 위한 SSL 인증서를 AWS Certificate Manager 서비스에서 만듭니다.
절차는 쉽지만 알아둬야할 사항이 있어서 글로 정리합니다.
(참고로, AWS Certificate Manager에서 만드는 SSL인증서는 무료입니다!)
우선, Certificate Manager 서비스에 들어갑니다.
가장 먼저 해줘야할 작업은 리전을 US East (N. Virginia)로 변경하는 것입니다.
왜냐하면, CloudFront에서 Custom SSL Certificate를 사용하려면 반드시 Virginia 리전에서 생성된 인증서만 허용되기 때문입니다.


리전을 바꿨으면 시작하기를 선택합니다.



도메인 이름은 인증서를 발급 받고 싶은 도메인 주소를 입력합니다.
ssltest.example.com 처럼 서브도메인을 포함한 주소를 입력해도 되고, *.example.com 처럼 서브도메인을 와일드카드로 입력해도 됩니다.
입력하고나면 검토 및 요청을 클릭합니다.



다음화면에서는 도메인 관리자에게 인증서 승인을 위한 메일을 보낸다는 안내가 됩니다.
확인 및 요청을 클릭합니다.



다음화면에서는 어떤 메일로 승인 요청을 보냈는지 나타납니다.(도메인 부분을 클릭하면 펼쳐집니다.)



계속 버튼까지 눌러줍니다.
(생성한 인증서 목록이 보일텐데 방금 만든 인증서의 상태가 '검증 보류'라고 나타날 겁니다.)
사실 승인 요청을 메일로 보내기 전에 위의 메일 주소들 중에 하나라도 생성되어 있어야하는게 맞는데...
제 경우에는 도메인을 Route53에서 만들었었더니, whoisprivacyservice.org 계정 3개로 보내진 인증서 승인 메일이 제 개인 메일로 전달(forwarding)되어져 왔습니다.
아래 그림 처럼 메일이 왔습니다.
가운데 쯤의 Amazon Certificate Approvals 링크를 누릅니다.



그러면 새창이 또 뜹니다. 여기서 I Approve 버튼을 누르면 인증서 승인이 완료됩니다.



승인이 완료되고 다시 Certificate Manager로 돌아와서 새로고침을 한번 해주면 상태가 '발급 완료'로 변경됩니다.
인증서 준비는 끝났습니다~!

2. S3 준비

S3에 버킷을 생성하고 파일들을 업로드 하고 버킷의 Properties에서 Static website hosting 기능을 활성화합니다.


버킷을 생성할 때 주의할 점이 하나 있습니다.
HTTPS 지원없이 Custom Domain만 사용하려면 Route53에서 S3를 바로 연결시키면 되는데, 이때는 버킷 이름이 Custom Domain이름과 같아야합니다. (ex. ssltest.example.com 으로 버킷 이름도 설정하고 도메인도 똑같은 이름으로 만들어야합니다.)
그런데 CloudFront를 S3와 Route53 사이에 껴넣을때는 버킷이름이 도메인 이름이랑 같으면 오히려 HTTPS 지원이 정상적으로 안됩니다. 제가 이 문제 때문에 하루를 버렸네요..ㅠㅠ
다시 본론으로.. 버킷의 Properties에서 Permissions에 가셔서 Bucket Policy에 아래 내용을 입력하고 Save합니다. Resource의 값 부분에 있는 [YOUR_BUCKET_NAME]을 본인의 버킷 이름으로 대체하시면 됩니다.
아래 Bucket Policy는 버킷으로 웹호스팅 할 때 전체 파일에 대해서 모든 사용자한테 Get을 허용하는 유용한 Policy입니다.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[YOUR_BUCKET_NAME]/*"
        }
    ]
}

3. CloudFront 준비

CloudFront는 AWS의 CDN 서비스입니다.
AWS CloudFront 서비스에 들어가서 Create Distribution을 선택합니다.



다음 화면(Select delivery method)에서는 배포할 컨텐츠의 타입이 무엇인지 선택합니다.
여기서는 Web부분의 Get Started를 클릭합니다.



다음 화면(Create distribution)에서는 갖가지 설정들을 하게되는데, 필수적인 사항만 정리하겠습니다. 다른 설정들은 상황에 따라 알맞게 손 보시면 됩니다.
Origin Settings에서 Origin Domain Name을 입력합니다.
마우스로 선택하면 S3 버킷 목록이 나오는데, 목록에서 선택하시지 말고,
위의 S3에서 웹호스팅 기능을 활성화 했을 때 생성되는 Endpoint(URL)을 직접 복사해서 넣으시길 권장드립니다.
목록에서 버킷을 선택해도 일반적인 static 웹호스팅은 문제가 없으나, SPA(Single Page Application)을 웹호스팅 할 경우를 대비한다면 Endpoint(URL)을 직접 입력해야합니다.
(If you want to host SPA(Single Page Application) on S3, insert Web hosing Endpoint(URL) of S3 into 'Origin Domain Name'. Don't select one of the dropdown list.)



Distribution Setting에서 Alternate Domain Names에 사용할 Custom Domain을 입력합니다. 이 이름은 나중에 Route53에 생성할 도메인과 동일해야합니다.
SSL Certificate는 Custom SSL Certificate를 선택합니다.
Default로 선택해도 동작에는 문제가 없지만 아래 그림처럼 경고가 뜹니다. 도메인 이름과 인증서 이름이 같지 않아서 발생하는 경고입니다.
노력해서 HTTPS를 쓰려고하는데 이런게 보이면 영 꺼림직 하지요..
그래서 Custom SSL Certificate를 선택하고 1번 단계에서 생성한 인증서를 선택해줍니다.

!!주의!! 1번 단계에서 생성한 인증서가 목록에 보임에도 불구하고 Custom SSL Certificate가 선택이 불가능하게 비활성화 되어 있을 수 있습니다.
찾아보니 이게 활성화 되는데는 인증서 생성 이후에 하루 정도가 걸릴 수 있다고 하네요... 저도 자고 일어나니 선택이 가능했습니다.

그리고 Default Root Object에는 도메인만 입력했을 때 바로 보여줄 파일이 무엇인지 설정하는 것입니다. 다들 아시는 index.html 로 입력하게 되실 것 같네요 ㅎㅎ



딱 4가지만 설정했습니다. 이렇게 설정하고 완료하면 생성한 Distribution의 General 속성에서 Distribution Status가 InProgress가 됩니다. 이 때가 각 엣지로 배포되는 중이라고 하네요.(조금 오래 걸립니다..)
배포가 완료되면 Deployed가 됩니다. 자동으로 되는게 아니니깐 새로고침 간간히 해서 확인해주세요~



Deployed를 기다리는 동안 Route53을 준비합니다.

4. Route53 준비

본 포스팅을 참고하시는 분들은 아마 자체 도메인을 이미 가지고 계실 것 같습니다.
그래서 Route53에 이미 기존에 사용하는 Hosted Zone이 있다는 가정하에 정리하겠습니다.


Route53의 Hosted zones에 가셔서 사용하실 도메인에서 Create Record Set을 선택합니다.
우측에 나타나는 입력창의 Name 입력칸에 CloudFront에서 Alternate Domain Names에 입력했던 서브도메인을 입력합니다.
(ex. Alternate Domain Names에 ssltest.example.com 이라고 입력했따면 Name 입력칸에 ssltest를 입력합니다.)
Type은 A - IPv4 address를 선택합니다.
그리고 Alias를 Yes로 선택합니다. 왜냐하면 CloudFront와 Route53을 연결할 때 별칭 리소스 레코드 세트를 사용하면 DNS 쿼리에 대한 요금이 지불되지 않는다고 합니다~!
Alias Target 입력칸을 클릭하면 CloudFront distribution에 위에서 생성한 distribution이 알아서 나타나있을 것입니다. 그걸 선택합니다. (Name을 입력해야 나타납니다.)
Create를 누르면 끝납니다.

5. 확인

이제 모든 절차가 끝났습니다. DNS에 도메인이 등록되는 시간을 잠시 기다리고나면 아래처럼 S3로 웹호스팅한 웹페이지가 HTTPS가 지원되는 걸 보실 수 있습니다!
수고하셨습니다~



* 내용 추가!
> S3에 업로드한 파일을 수정해서 다시 올렸을 때 어떻게 CloudFront에 갱신시키는지에 대한 내용을 아래 링크에 정리했습니다. 함께 보시면 좋을 것 같습니다~!
(링크 : https://walkinpcm.blogspot.kr/2017/06/aws-aws-s3-origin-cloudfront.html)

참고링크

댓글 13개:

  1. Awesome post presented by you..your writing style is fabulous and keep update with your

    blogs AWS Online Course

    답글삭제
  2. 먼저 좋은 글 감사합니다!

    CloudFront를 S3와 Route53 사이에 껴넣을때는 버킷이름이 도메인 이름이랑 같으면 오히려 HTTPS 지원이 정상적으로 안됩니다. < 이 부분 조금 더 자세한 설명 부탁드려도 될까요? 저도 지금 이것 때문에 하루를 버리고 있어서요ㅠ 제가 만든 s3 버킷은 총 3개인데, example.com(index.html 있음), www.example.com(example.com으로 redirect), bucket-for-redirection(cloudfront를 위한 버킷/example.com으로 redirect/https 프로토콜) 이렇습니다.

    CloudFront의 Origin Domain Name에는 bucket-for-redirect S3의 엔드포인트 URL을 직접 복사해 붙여넣었습니다. Route 53 설정도 자습서에서 하란대로 다 했고...인증서도 문제 없습니다.

    근데 ERR_TOO_MANY_REDIRECTS가 떠서ㅠㅠ 아무래도 CloudFront와 S3 사이에서 redirection loop가 생긴 것 같은데 뭘 고쳐야 할지 잘 모르겠습니다.
    (S3와 Route 53만으로는 https로 웹사이트 연결이 잘됐었습니다.)

    답글삭제
    답글
    1. 먼저, 버킷을 3개나 두신 이유가 있을까요?

      삭제
    2. 헉...빠른 답변 감사합니다.

      일단 Route 53과 S3로만 웹사이트를 올릴 때 example.com, www.example.com을 만들었는데 그 뒤 http에서 https로 리다이렉트하는 자습서를 따라하면서 CloudFront를 위한 버킷을 하나 더 만들었습니다.

      뭔가 좀 많다고 생각하긴 했는데 뭘 지워야 할지 몰라서요...@.@

      삭제
    3. 제 생각에는,, 버킷은 하나면 될것 같습니다. 먼저, 도메인 명과 동일하지 않은 아무 이름으로 버킷을 두시고(이미 만드신 bucket-for-redirection 도 괜찮습니다.) 본 게시물대로 이행하시면서 Cloud Front 의 도메인 설정에 example.com을 사용해보세요. 다 하시면 example.com으로는 https를 이용하실수 있을것 같아요. 그 다음에 www.example.com은 route53에서 cname으로 example.com을 추가하시면 어떨까 싶습니다.

      삭제
    4. 감사합니다. 지금 해보겠습니다! 결과가 나오면 여기 적을게요!

      삭제
    5. 만세!!!! 됐어요!!!! 정말 감사합니다ㅠㅠㅠㅠ
      제가 라우팅이나 리디렉션 개념을 잘 안 잡고 무작정 따라해서 이 사단이 벌어진 듯 합니다.
      커피 기프티콘이라도 드리고 싶은데 프로필에 있는 지메일로 보내도 될까요?? (이미!! 샀어요!!!)

      삭제
    6. 제 글이 도움이 되었다면 그걸로 만족합니다~
      기프티콘은 마음만 감사히 받겠습니다 ㅎㅎ 이미 사신건, 문제가 해결된 이 시점에 기분 좋게 쉴겸 먹고오세요 ㅎㅎㅎ
      aws에 대해서 더 쉽게 알아가실거면 awskrug(aws 한국 사용자 모임) 의 소모임들에 참여해보시면 좋습니다 :) 페이스북에서 awskrug를 검색해보세요~

      삭제
    7. 흑흑 감동입니다ㅠ 머리 식힐 겸 나갔다와야겠네요.
      AWSKRUG는 사실 가입돼있긴 한데 소모임은 안 가봐서요! 추천 감사합니다!

      삭제
  3. 먼저 이렇게 험난한 길을 걸어주시고, 발생할 수 있는 예외를 상세히 설명해주셔서 감사합니다.
    덕분에 어려움없이 cloud front를 적용할 수 있었습니다 :)

    답글삭제
    답글
    1. 도움이 되었다니 다행입니다! 댓글 남겨주셔서 기분이 좋고 힘이 납니다! 감사합니다~

      삭제
  4. 이 글 덕분에 작년 1년 프로젝트 무사히 할 수 있었고
    올해 리뉴얼때도 이글을 참고하며 적용하고 있습니다, 좋은 글 정말 감사합니다

    답글삭제
    답글
    1. 댓글을 달아주셔서 정말 너무 뿌듯합니다 :) 댓글 감사합니다!! 앞으로 더 열심히 공부해서 공유하고 개발 생태계의 선순환에 기여하겠습니다~!!
      (앞으로는 새로운 블로그에서 정리합니다. blog.walkinpcm.com , 본 블로그도 닫지는 않습니다.)

      삭제