Terraform + S3 + CloudFrontで静的サイトを簡単構築

AWSで静的サイトを構築する時は基本的にS3の静的Webサイトホスティング + CloudFrontを使って構成すると思います。
このときGUIでやると少し手間なのでTerraformで一気に構築できる手順をまとめました。

# 構成
今回は最も単純な構成で下記を構築します。

## S3
バケット名：test-static-web-site
静的Webサイトホスティング
インデックスドキュメント：index.html
エラードキュメント：index.html (実際はエラー用のページを用意するといいと思います)

## CloudFront
ディストリビューション名：test-static-web-site-dst
基本的な構成でオリジンをS3バケットに向ける
`OriginAccessIdentity` を使ってS3バケットへのアクセス権限をバケットポリシーに設定
今回SSLはCloudFrontデフォルトのもの。独自ドメインを持っている場合はACMの証明書もTerraformで作成することで `acm_certificate_arn` で指定でき、簡単です。

# Terraformを書く
実際のtfファイルで下記を作成します。

## S3
```s3.tf
# バケットの作成
resource "aws_s3_bucket" "test-static-web-site" {
    bucket = "test-static-web-site"
    acl    = "private"
    # バケットポリシーの指定
    policy = data.aws_iam_policy_document.test-static-web-site-bucket_policy.json

    versioning {
        enabled = true
    }
    
    website {
        index_document = "index.html"
        error_document = "index.html"
    }

}

# OriginTarget用の変数作成
locals {
    s3-origin-id-test-static-web-site = "s3-origin-id-test-static-web-site"
}

# バケットポリシー
data "aws_iam_policy_document" "test-static-web-site-bucket_policy" {
    statement {
        sid    = ""
        effect = "Allow"
        principals {
            type        = "AWS"
            # identifiersはCloudFrontのtfファイルからパス指定することでDistribution作成後にIDを調べてからでなくても指定できます
            identifiers = ["${aws_cloudfront_origin_access_identity.test-static-web-site-idntity.iam_arn}"]
        }

        actions = [
            "s3:GetObject"
        ]

        resources = [
            "arn:aws:s3:::test-static-web-site",
            "arn:aws:s3:::test-static-web-site/*"
        ]
    }
}
```

## CloudFront
```cloudfront.tf
# Distributionの作成
resource "aws_cloudfront_distribution" "test-static-web-site-dst" {
    # Originの作成。
    origin {
        domain_name = aws_s3_bucket.test-static-web-site.bucket_regional_domain_name
        origin_id   = local.s3-origin-id-test-static-web-site
        s3_origin_config {
            origin_access_identity = aws_cloudfront_origin_access_identity.test-static-web-site-idntity.cloudfront_access_identity_path
        }
    }

    enabled             = true
    # indexドキュメント
    default_root_object = "index.html"
    wait_for_deployment = true
    
    # 独自ドメインを使用する場合はaliasを指定することでドメインでのアクセスも可能です
    # aliases             = ["xxxxxx.com"]

    # SSL証明書。ACMを使用する場合はここで指定すると利用可能です
    viewer_certificate {
        acm_certificate_arn            = ""
        cloudfront_default_certificate = true
        ssl_support_method             = ""
    }
    
    # 404エラー時に返すファイル
    custom_error_response {
        error_code = "404"
        response_code = "200"
        response_page_path = "/index.html"
    }

    default_cache_behavior {
        allowed_methods  = ["GET", "HEAD"]
        cached_methods   = ["GET", "HEAD"]
        target_origin_id = local.s3-origin-id-test-static-web-site
        compress         = true
        viewer_protocol_policy = "allow-all"

        forwarded_values {
            query_string = false
            cookies {
                forward = "none"
            }
        }
    }

    restrictions {
        geo_restriction {
            restriction_type = "none"
        }
    }
}

# OriginAccessIdentityの作成
resource "aws_cloudfront_origin_access_identity" "test-static-web-site-idntity" {
    comment = "access-identity-test-static-web-site.s3.amazonaws.com"
}
```

# 実行
あとはTerraformを実行することでS3バケット、CloudFront Distributionが出来上がり、外からアクセス出来るようになります。

```bash
# 設定内容、更新内容を確認
$ terraform plan

# 問題なければ実行
$ terraform apply
```

今後同じような構成が増えた時はこの内容を使い回すことですぐに構築することができますね。