この記事は公開されてから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 version
Terraform 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がどんどん便利になってうれしいですね。今後もアップデートを追いかけて行こうと思います。
本エントリがみなさんの参考になったら幸いに思います。