Cloud Front에서 특정 S3 버킷의 이미지에 액세스할 수 있도록 허용(cache distribution 패턴)

하고 싶었던 일



s3에 업로드한 이미지를 cache distribution 패턴에서 관리하고 액세스할 수 있도록 하고 싶습니다.
Infrastructure as Code100%를 목표로 하고 있으므로, 자원의 작성은 terraform에서!
※ 독자 도메인으로 액세스 할 수 있도록 하고 싶기 때문에 route53의 설정도 합니다만, SSL 증명서는 발행하고 있는 전제입니다. Cloud Front는 us-east로 발행하지 않으면 작성할 수 없기 때문에 요주의입니다! (함정)

구성





작성 절차



위의 구성도 아래에서 순서대로 만들어 가고 싶습니다 👍
모든 terraform 코드가 실려 있습니다.

S3 만들기



s3.tf
resource "aws_s3_bucket" "image-bucket" {
  bucket = "image-bucket"
  acl    = "private"
  region = "ap-northeast-1"
}

우선 위의 코드만 apply 해 봅시다.
그런 다음 콘솔에서 image-bucket으로 image를 업로드하고 https://s3-ap-northeast-1.amazonaws.com/image-bucket/image.png에 액세스합니다.
private 버킷이므로 액세스 할 수 없을 것입니다.


Origin Access Identity 만들기



위와 같이 S3에 직접 액세스할 수는 없지만 Cloud Front에서 액세스할 수 있도록 Origin Access Identity를 만듭니다. 나중에 S3의 Policy에 연결하여 Cloud Front에서 액세스를 허용할 수 있습니다.

cloudfront.tf
resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
  comment = "origin access identity for s3"
}

S3의 정책 만들기



principals identifiers에서 방금 만든 Origin Access Identity를 지정하여 Cloud Front → S3 bucket의 일부 작업을 허용합니다.

iam.tf
data "aws_iam_policy_document" "cf_to_s3_policy" {
  statement {
    actions = ["s3:GetObject", "s3:ListBucket"]

    resources = [
      "${aws_s3_bucket.image-bucket.arn}",
      "${aws_s3_bucket.image-bucket.arn}/*",
    ]

    principals {
      type        = "AWS"
      identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
    }
  }
}

그리고 이 policy를 s3에 연결해 줍니다.

iam.tf
resource "aws_s3_bucket_policy" "cf-to-s3" {
  bucket = "${aws_s3_bucket.image-bucket.id}"
  policy = "${data.aws_iam_policy_document.cf_to_s3_policy.json}"
}

Cloud Front 만들기



잘 지정하는 장소


  • origin/domain_name
  • S3 버킷의 도메인 이름

  • s3_origin_config/origin_access_identity
  • Origin Access Identity 경로

  • aliases
  • 이름 확인하려는 고유 도메인 이름

  • viewer_certificate/acm_certificate_arn
  • 자신의 도메인을 발급 한 acm arn (us-east이어야합니다)


  • 기타 파라미터 보충


  • default_cache_behavior
  • cache 서버의 세부 설정

  • price_class
  • cache 서버로 사용할 지역 클래스 선택

  • restrictions
  • 사용자 요청에 대한 지역 제한을 설정하고 화이트리스트와 블랙리스트를 등록 할 수 있습니다


  • cloudfront.tf
    resource "aws_cloudfront_distribution" "s3_distribution" {
      origin {
        domain_name = "${aws_s3_bucket.image-bucket.bucket_regional_domain_name}"
        origin_id   = "${aws_s3_bucket.image-bucket.id}"
    
        s3_origin_config {
          origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path}"
        }
      }
    
      enabled         = true
      is_ipv6_enabled = false
      comment         = "comment"
    
      logging_config {
        include_cookies = false
        bucket          = "${aws_s3_bucket.image-bucket.bucket_domain_name}"
        prefix          = "prefix"
      }
    
      aliases = ["sample.com"]
    
      default_cache_behavior {
        allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
        cached_methods   = ["GET", "HEAD"]
        target_origin_id = "${aws_s3_bucket.image-bucket.id}"
    
        forwarded_values {
          query_string = false
    
          cookies {
            forward = "none"
          }
        }
    
        viewer_protocol_policy = "allow-all"
        min_ttl                = 0
        default_ttl            = 3600
        max_ttl                = 86400
      }
    
      price_class = "PriceClass_200"
    
      restrictions {
        geo_restriction {
          restriction_type = "none"
        }
      }
    
      tags = {
        Environment = "dev"
      }
    
      viewer_certificate {
        acm_certificate_arn = "arn:aws:acm:us-east-1:xxx:certificate/xxx"
        ssl_support_method  = "vip"
      }
    }
    

    Cloud Front의 설정은, us-east 밖에 받아들이지 않는 문제로부터 시작되어, restrictions를 서버의 이야기일까 생각해 white list에 일본(JP)을 넣지 않고 설정해 버리거나(자신도 액세스 할 수 없게 되는 w) 조금 막힘 했습니다・・・.

    그런데, Cloud Front→S3까지는 할 수 있었으므로 apply 해 봅시다.
    (Cloud Front의 작성은 30min 정도 걸립니다 😓)

    Cloud Front가 성공적으로 생성되면 도메인 이름을 확인하고 액세스해 봅시다. 요청이 성공하여 S3에 업로드한 이미지를 볼 수 있었습니다 🎉


    route53의 Record 만들기



    마지막으로 자신의 도메인에서도 액세스할 수 있습니다.

    잘 지정하는 장소


  • zone_id
  • HostedZone ID

  • 이름
  • 액세스할 수 있는 도메인 이름

  • records
  • cname 값 = 방금 만든 Cloud Front Distribution 도메인 이름 (xxx.cloudfront.net)


  • route53.tf
    resource "aws_route53_record" "cname" {
      zone_id = "xxx"
      name    = "sample.com"
      type    = "CNAME"
      ttl     = "300"
      records = ["${aws_cloudfront_distribution.s3_distribution.domain_name}"]
    }
    

    이제 apply 해보자!sample.com/image.png로 이동하여 이미지가 표시되었습니다 🎉

    좋은 웹페이지 즐겨찾기