
【速報】TerraformがCloudFrontに対応しました
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは、中山です。
先程Terraformのv0.6.15がリリースされましたね!
CHANGELOGはこちらです。さまざまなアップデートが含まれるのですが、やはりCloudFrontへの対応に目を引かれました。aws_cloudfront_distribution とaws_cloudfront_origin_access_identity がCloudFront用のリソースです。以前のバージョンでもaws_cloudformation_stackリソースを使用すればCloudFrontの作成も可能でしたが、やはりリソースという形で対応してくれるとうれしいですね。
という訳で、早速使ってみたのでレポートしてみます。
インストール
まずはTerraformをインストールしましょう。
$ brew update$ brew cask install terraform
バージョンを確認します。
$ terraform versionTerraform v0.6.15
TerraformでCache Distributionパターンを実装する
S3にオリジンの静的コンテンツを置いてCloudFrontでそのキャッシュを配信してみましょう。
コード
以下のコードを作成してください。
main.tf
variable "name" { default = "ap-northeast-1-cloudfront-resource-demo" }variable "region" { default = "ap-northeast-1" }variable "access_key" { }variable "secret_key" { }variable "acl" { default = "public-read" }variable "policy_file" { default = "policy.json.tpl" }variable "index" { default = "index.html" }provider "aws" { region = "${var.region}" access_key = "${var.access_key}" secret_key = "${var.secret_key}"}resource "aws_cloudfront_origin_access_identity" "origin_access_identity" { comment = "${var.name}"}resource "template_file" "s3_policy" { template = "${file(concat(path.module, "/", var.policy_file))}" vars { bucket_name = "${var.name}" origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access_identity.id}" }}resource "aws_s3_bucket" "s3" { bucket = "${var.name}" acl = "${var.acl}" force_destroy = true policy = "${template_file.s3_policy.rendered}" website { index_document = "${var.index}" }}resource "aws_s3_bucket_object" "s3" { bucket = "${aws_s3_bucket.s3.bucket}" key = "${var.index}" source = "${concat(path.module, "/", var.index)}" content_type = "text/html"}resource "aws_cloudfront_distribution" "cf" { enabled = true comment = "${var.name}" default_root_object = "${var.index}" price_class = "PriceClass_200" retain_on_delete = true origin { domain_name = "${concat(aws_s3_bucket.s3.id, ".s3.amazonaws.com")}" origin_id = "${var.name}" s3_origin_config { origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path}" } } default_cache_behavior { allowed_methods = ["GET", "HEAD"] cached_methods = ["GET", "HEAD"] target_origin_id = "${aws_s3_bucket.s3.id}" forwarded_values { query_string = false cookies { forward = "none" } } viewer_protocol_policy = "allow-all" min_ttl = 0 default_ttl = 3600 max_ttl = 86400 } restrictions { geo_restriction { restriction_type = "whitelist" locations = ["US", "CA", "GB", "DE", "JP"] } } viewer_certificate { cloudfront_default_certificate = true }}output "s3_website_endpoint" { value = "${aws_s3_bucket.s3.website_endpoint}" }output "cloudfront_domain_name" { value = "${aws_cloudfront_distribution.cf.domain_name}" }policy.json.tpl
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadForGetBucketObjets", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${origin_access_identity}" }, "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::${bucket_name}/*"] } ]}コードの解説
1.aws_cloudfront_origin_access_identity
今回はS3のエンドポイントへ直接アクセスさせない設定にするので、オリジンアクセスアイデンティティを作成します。オリジンアクセスアイデンティティを利用したS3バケットへのアクセス制限は、弊社甲木が書いた以下のエントリが参考になります。
2.template_file
バケットポリシーをテンプレートから作成しています。Terraform上の変数を${variable} という形式でテンプレートに埋め込み、それをレンダリングすることで変数の展開が可能です。
3.aws_s3_bucket
S3にバケットを作成します。Static Website Hosting機能を有効にさせ、ACLはpublic-read に、バケットポリシーは作成するバケットに対してs3:GetObject を許可させます。CloudFrontからのみコンテンツにアクセスさせたいのでPrincipleにはオリジンアクセスアイデンティティのIDを指定します。
4.aws_s3_bucket_object
作成したバケットにindex.htmlをアップロードします。
5.aws_cloudfront_distribution
最後にCloudFrontを作成します。詳細はドキュメントに詳しいですが、マネジメントコンソールでCloudFrontを作成した場合との対応表を以下に記述します。
| Terraform上の設定 | Terraform上の値 | マネジメントコンソール上の設定 | マネジメントコンソール上の値 |
|---|---|---|---|
enabled | true | Distribution State | Enabled |
comment | ap-northeast-1-cloudfront-resource-demo | Comment | ap-northeast-1-cloudfront-resource-demo |
default_root_object | index.html | Default Root Object | index.html |
price_class | PriceClass_200 | Price Class | Use Only US, Europe and Asia |
retain_on_delete | true | N/A(Terraform固有の機能) | N/A |
origin - domain_name | ap-northeast-1-cloudfront-resource-demo.s3.amazonaws.com | Origin Domain Name | ap-northeast-1-cloudfront-resource-demo.s3.amazonaws.com |
origin - origin_id | ap-northeast-1-cloudfront-resource-demo | Origin ID | ap-northeast-1-cloudfront-resource-demo |
origin - s3_origin_config - origin_access_identity | origin-access-identity/cloudfront/ABC123 | Origin Access Identity | origin-access-identity/cloudfront/ABC123 |
default_cache_behavior - allowed_methods | ["GET", "HEAD"] | Allowed HTTP Methods | GET, HEAD |
default_cache_behavior - cached_methods | ["GET", "HEAD"] | Cached HTTP Methods | GET, HEAD (Cached by default) |
default_cache_behavior - target_origin_id | ap-northeast-1-cloudfront-resource-demo | Origin | ap-northeast-1-cloudfront-resource-demo |
default_cache_behavior - forwarded_values - query_string | false | Forward Headers | None (Improves Caching) |
default_cache_behavior - forwarded_values - cookies - forward | none | Forward Cookies | None (Improves Caching) |
default_cache_behavior - viewer_protocol_policy | allow-all | Viewer Protocol Policy | HTTP and HTTPS |
default_cache_behavior - min_ttl | 0 | Minimum TTL | 0 |
default_cache_behavior - default_ttl | 3600 | Default TTL | 3600 |
default_cache_behavior - max_ttl | 86400 | Maximum TTL | 86400 |
restrictions - geo_restriction - restriction_type | whitelist | Restriction Type | Whitelist |
restrictions - geo_restriction - locations | ["US", "CA", "GB", "DE", "JP"] | Countries | CA -- CANADA DE -- GERMANY JP -- JAPAN GB -- UNITED KINGDOM US -- UNITED STATES |
viewer_certificate - cloudfront_default_certificate | true | SSL Certificate | Default CloudFront Certificate (*.cloudfront.net) |
実行する
まずオリジンコンテンツを設置します。今回はテスト目的なので簡易的なHTMLを設置するだけにします。
$ echo 'Hello, World!' > index.html
Terraformを実行します。<access_key> と<secret_key> に自分のAWSクレデンシャルを指定してください。
$ terraform plan -var access_key=<access_key> -var secret_key=<secret_key>$ terraform apply -var access_key=<access_key> -var secret_key=<secret_key>
CloudFrontのStateがdeployedになるまで15分程度時間が掛かります。deployedになったらCloudFrontのドメインにアクセスしてみましょう。<cloudfront-domain-name> は自分の環境に合うよう修正してください。以下のようにHTTP/HTTPS両方でアクセスできたら成功です。
$ curl http://<cloudfront-domain-name>Hello World!$ curl https://<cloudfront-domain-name>Hello World!
逆に、以下のようにS3のエンドポイントへ直接アクセスして403が返ったら、バケットポリシーが意図したとおりに動作していると確認できます。
$ curl <s3-website-endpoint><html><head><title>403 Forbidden</title></head><body><h1>403 Forbidden</h1><ul><li>Code: AccessDenied</li><li>Message: Access Denied</li><li>RequestId: ABC123</li><li>HostId: ABC123</li></ul><hr/></body></html>
まとめ
いかがだったでしょうか。
Terraformがどんどん便利になってうれしいですね。今後もアップデートを追いかけて行こうと思います。
本エントリがみなさんの参考になったら幸いに思います。









