forked from cn-terraform/terraform-aws-s3-static-website
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebsite.tf
193 lines (157 loc) · 7.26 KB
/
website.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
#------------------------------------------------------------------------------
# CloudFront Origin Access Identity
#------------------------------------------------------------------------------
resource "aws_cloudfront_origin_access_identity" "cf_oai" {
provider = aws.main
comment = "OAI to restrict access to AWS S3 content"
}
#------------------------------------------------------------------------------
# Website S3 Bucket
#------------------------------------------------------------------------------
data "template_file" "website_bucket_policy" {
template = file("${path.module}/templates/s3_website_bucket_policy.json")
vars = {
bucket_name = local.website_bucket_name
cf_oai_arn = aws_cloudfront_origin_access_identity.cf_oai.iam_arn
}
}
# - AWS017: The bucket objects could be read if compromised. TODO, implement this.
resource "aws_s3_bucket" "website" { # tfsec:ignore:AWS017
provider = aws.main
bucket = local.website_bucket_name
acl = var.website_bucket_acl
policy = data.template_file.website_bucket_policy.rendered # tfsec:ignore:AWS001
force_destroy = var.website_bucket_force_destroy
website {
index_document = var.website_index_document
error_document = var.website_error_document
}
cors_rule {
allowed_headers = var.website_cors_allowed_headers
allowed_methods = var.website_cors_allowed_methods
allowed_origins = concat(["http://${var.website_domain_name}", "https://${var.website_domain_name}"], var.website_cors_additional_allowed_origins)
expose_headers = var.website_cors_expose_headers
max_age_seconds = var.website_cors_max_age_seconds
}
versioning {
enabled = var.website_versioning_enabled
mfa_delete = var.website_versioning_mfa_delete
}
logging {
target_bucket = aws_s3_bucket.log_bucket.id
target_prefix = "website/"
}
# TODO - Add Lifecyle rule parameters
# lifecycle_rule - (Optional) A configuration of object lifecycle management.
# TODO - Add replication configuration parameters
# replication_configuration - (Optional) A configuration of replication configuration.
# TODO - Review how to add server side encryption
# server_side_encryption_configuration {
# rule {
# apply_server_side_encryption_by_default {
# sse_algorithm = "aws:kms"
# }
# }
# }
# TODO - Add variables for S3 object locking
# object_lock_configuration - (Optional) A configuration of S3 object locking
tags = merge({
Name = "${var.name_prefix}-website"
}, var.tags)
}
resource "aws_s3_bucket_public_access_block" "website_bucket_public_access_block" {
provider = aws.main
bucket = aws_s3_bucket.website.id
ignore_public_acls = true
block_public_acls = true
restrict_public_buckets = true
block_public_policy = true
}
#------------------------------------------------------------------------------
# Cloudfront for S3 Bucket Website
#------------------------------------------------------------------------------
# tfsec issues ignored
# - AWS045: Enable WAF for the CloudFront distribution. Pending to implement.
resource "aws_cloudfront_distribution" "website" { # tfsec:ignore:AWS045
provider = aws.main
aliases = [
local.website_bucket_name,
local.www_website_bucket_name
]
comment = var.comment_for_cloudfront_website
# TODO - Add variable for Custom Error Responses
# custom_error_response (Optional) - One or more custom error response elements (multiples allowed).
# TODO - Add variables for cache and origin request policies.
default_cache_behavior {
cache_policy_id = "658327ea-f89d-4fab-a63d-7e88639e58f6" # Managed-CachingOptimized
origin_request_policy_id = "88a5eaf4-2fd4-4709-b370-b4c650ea3fcf" # Managed-CORS-S3Origin
allowed_methods = var.cloudfront_allowed_cached_methods
cached_methods = var.cloudfront_allowed_cached_methods
target_origin_id = local.website_bucket_name
viewer_protocol_policy = var.cloudfront_viewer_protocol_policy
}
default_root_object = var.cloudfront_default_root_object
enabled = true
is_ipv6_enabled = var.is_ipv6_enabled
http_version = var.cloudfront_http_version
logging_config {
include_cookies = false
bucket = aws_s3_bucket.log_bucket.bucket_domain_name
prefix = "cloudfront_website"
}
# TODO - Add variable to support ordered_cache_behavior
# ordered_cache_behavior (Optional) - An ordered list of cache behaviors resource for this distribution. List from top to bottom in order of precedence. The topmost cache behavior will have precedence 0.
origin {
domain_name = aws_s3_bucket.website.bucket_regional_domain_name
origin_id = local.website_bucket_name
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.cf_oai.cloudfront_access_identity_path
}
}
price_class = var.cloudfront_price_class
restrictions {
geo_restriction {
restriction_type = var.cloudfront_geo_restriction_type
locations = var.cloudfront_geo_restriction_locations
}
}
tags = merge({
Name = "${var.name_prefix}-website"
}, var.tags)
viewer_certificate {
acm_certificate_arn = var.create_acm_certificate ? aws_acm_certificate_validation.cert_validation[0].certificate_arn : var.acm_certificate_arn_to_use
cloudfront_default_certificate = false
minimum_protocol_version = "TLSv1.2_2021"
ssl_support_method = "sni-only"
}
# TODO - Work to add Web ACL variables
# web_acl_id (Optional) - A unique identifier that specifies the AWS WAF web ACL, if any, to associate with this distribution.
# To specify a web ACL created using the latest version of AWS WAF (WAFv2), use the ACL ARN, for example aws_wafv2_web_acl.example.arn. To specify a web ACL created using AWS WAF Classic, use the ACL ID, for example aws_waf_web_acl.example.id. The WAF Web ACL must exist in the WAF Global (CloudFront) region and the credentials configuring this argument must have waf:GetWebACL permissions assigned.
retain_on_delete = var.cloudfront_website_retain_on_delete
wait_for_deployment = var.cloudfront_website_wait_for_deployment
}
#------------------------------------------------------------------------------
# Cloudfront DNS Record (if CloudFront is enabled)
#------------------------------------------------------------------------------
resource "aws_route53_record" "website_cloudfront_record" {
provider = aws.main
zone_id = var.create_route53_hosted_zone ? aws_route53_zone.hosted_zone[0].zone_id : var.route53_hosted_zone_id
name = local.website_bucket_name
type = "A"
alias {
name = aws_cloudfront_distribution.website.domain_name
zone_id = aws_cloudfront_distribution.website.hosted_zone_id
evaluate_target_health = false
}
}
resource "aws_route53_record" "www_website_record" {
provider = aws.main
zone_id = var.create_route53_hosted_zone ? aws_route53_zone.hosted_zone[0].zone_id : var.route53_hosted_zone_id
name = local.www_website_bucket_name
type = "A"
alias {
name = aws_cloudfront_distribution.website.domain_name
zone_id = aws_cloudfront_distribution.website.hosted_zone_id
evaluate_target_health = false
}
}