-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatic.tf
223 lines (184 loc) · 5.87 KB
/
static.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
variable "hostname" {
description = <<EOS
Base hostname for the static site.
Used for the name of the S3 bucket and cloudfront subdomain.
Example: www.example.com
EOS
}
variable "ssl_cert_arn" {
description = <<EOS
ARN for cert created with AWS cli/gui
You'll first need to provision an SSL cert and make it available to the AWS
Certificate Manager. To request a free cert, visit https://console.aws.amazon.com/acm/home.
This process will take some time as you'll need to prove domain ownership.
Docs: https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request.html
Example: arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
EOS
}
variable "logging_bucket" {
description = <<EOS
S3 Bucket for log storage
Logs will be added in a directory named after the hostname, so you can have a single logging bucket for multiple sites.
To disable logging, set this to "" and remove the "logging_config" resource in the static.tf config for cloudfront
Example: mycompanylogs
EOS
}
variable "aws_region" {
default = "us-east-1"
description = "S3 buckets are region-specific"
}
variable "aws_cli_profile" {
default = "default"
description = "Profile name in .aws/credentials"
}
variable "environment_name" {
default = "production"
description = "For tagging"
}
# DNS config: short times for initial development
variable "use_short_ttl" {
default = true
type = bool
description = "Probably set to false once initial development stabilizes"
}
# gzip for Cloudfront
variable "enable_gzip" {
default = true
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
region = var.aws_region
# load creds from ~/.aws/credentials, and use ${profile} profile
profile = var.aws_cli_profile
}
# S3 Static Site
# The bucket policy allows read access to contents, even with the private ACL.
# Changing the ACL to "public-read" would also allow anyone to list the bucket contents.
resource "aws_s3_bucket" "website" {
bucket = var.hostname
acl = "private"
policy = <<POLICY
{
"Version":"2012-10-17",
"Statement":[{
"Sid":"PublicReadForGetBucketObjects",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::${var.hostname}/*"]
}]
}
POLICY
tags = {
Environment = var.environment_name
}
website {
index_document = "index.html"
error_document = "404.html"
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
# S3 logs
# Note: If you don't want logging, you'll also need to remove logging_config from the cloudfront resource.
resource "aws_s3_bucket" "websitelogs" {
bucket = var.logging_bucket
acl = "log-delivery-write"
tags = {
Environment = var.environment_name
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
# Cloudfront CDN for site
# See also https://www.terraform.io/docs/providers/aws/r/cloudfront_distribution.html#logging-config-arguments
# - SSL from edge to clients
# - http internally
# - support index documents at all levels (subdirectories)
resource "aws_cloudfront_distribution" "cdn" {
depends_on = [aws_s3_bucket.website]
origin {
origin_id = "website_bucket_origin"
# Configure this origin as a web site, not an S3 bucket, so that we get support for
# index objects at all levels. Use the region-specific URL to support this.
domain_name = "${var.hostname}.s3-website-${var.aws_region}.amazonaws.com"
# And this is all required since we're telling cloudfront to use the origin as a website
# (again, not as an S3 bucket)
# See https://groups.google.com/forum/#!topic/terraform-tool/JSOhKDXNaYI
custom_origin_config {
# s3-as-website only supports "http-only"
# http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesOriginProtocolPolicy
origin_protocol_policy = "http-only"
http_port = 80
https_port = 443
origin_ssl_protocols = ["TLSv1.2", "TLSv1.1"]
}
}
enabled = true
is_ipv6_enabled = true
comment = var.hostname
# Probably don't need this with origin in web backend (not s3) mode
default_root_object = "index.html"
# Probably don't need this with origin in web backend (not s3) mode
custom_error_response {
error_code = 404
response_page_path = "/404.html"
response_code = 404
}
logging_config {
include_cookies = false
bucket = aws_s3_bucket.websitelogs.bucket_domain_name
prefix = var.hostname
}
aliases = [var.hostname]
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "website_bucket_origin"
compress = var.enable_gzip
# Static site: forward nothing
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = var.use_short_ttl ? 0 : 0
default_ttl = var.use_short_ttl ? 300 : 3600
max_ttl = var.use_short_ttl ? 300 : 86400
}
# [cheapest pricing is 100](https://aws.amazon.com/cloudfront/pricing/)
price_class = "PriceClass_100"
restrictions {
geo_restriction {
restriction_type = "none"
}
}
tags = {
Environment = var.environment_name
}
viewer_certificate {
# Created in web console; no terraform support yet
acm_certificate_arn = var.ssl_cert_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.1_2016"
}
}