Skip to content

Commit 4050370

Browse files
CCM-9873: Add cloudfront distribution to download bucket (#464)
Co-authored-by: Alex Nuttall <[email protected]>
1 parent 2c0c7f5 commit 4050370

22 files changed

+10196
-9826
lines changed

infrastructure/terraform/components/acct/module_sandbox_kms.tf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,3 @@ module "kms_sandbox" {
1414
alias = "alias/${local.csi}-sandbox"
1515
iam_delegation = true
1616
}
17-

infrastructure/terraform/components/acct/outputs.tf

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,11 @@ output "github_pat_ssm_param_name" {
1212

1313
output "s3_buckets" {
1414
value = {
15-
access_logs = {
16-
arn = module.s3bucket_access_logs.arn
17-
bucket = module.s3bucket_access_logs.bucket
18-
id = module.s3bucket_access_logs.id
19-
}
2015
backup_reports = {
2116
arn = module.s3bucket_backup_reports.arn
2217
bucket = module.s3bucket_backup_reports.bucket
2318
id = module.s3bucket_backup_reports.id
24-
},
19+
}
2520
}
2621
}
2722

infrastructure/terraform/components/app/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
| <a name="module_eventpub"></a> [eventpub](#module\_eventpub) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/eventpub | v1.0.13 |
5555
| <a name="module_kms"></a> [kms](#module\_kms) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/kms | v1.0.8 |
5656
| <a name="module_nhse_backup_vault"></a> [nhse\_backup\_vault](#module\_nhse\_backup\_vault) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/aws-backup-source | v1.0.8 |
57+
| <a name="module_s3bucket_cf_logs"></a> [s3bucket\_cf\_logs](#module\_s3bucket\_cf\_logs) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket | v2.0.2 |
5758
## Outputs
5859

5960
| Name | Description |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
resource "aws_acm_certificate" "files" {
2+
provider = aws.us-east-1
3+
4+
domain_name = local.cloudfront_files_domain_name
5+
validation_method = "DNS"
6+
7+
lifecycle {
8+
create_before_destroy = true
9+
}
10+
}
11+
12+
resource "aws_acm_certificate_validation" "files" {
13+
provider = aws.us-east-1
14+
15+
certificate_arn = aws_acm_certificate.files.arn
16+
17+
validation_record_fqdns = [for record in aws_route53_record.acm_validation_files : record.fqdn]
18+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
resource "aws_cloudfront_distribution" "main" {
2+
provider = aws.us-east-1
3+
4+
enabled = true
5+
is_ipv6_enabled = true
6+
comment = "NHS Notify templates files CDN (${local.csi})"
7+
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-distributionconfig.html#cfn-cloudfront-distribution-distributionconfig-priceclass
8+
price_class = "PriceClass_100"
9+
10+
restrictions {
11+
geo_restriction {
12+
restriction_type = "none"
13+
locations = []
14+
}
15+
}
16+
17+
aliases = [
18+
local.cloudfront_files_domain_name
19+
]
20+
21+
viewer_certificate {
22+
acm_certificate_arn = aws_acm_certificate_validation.files.certificate_arn
23+
# Supports 1.2 & 1.3 - https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html
24+
minimum_protocol_version = "TLSv1.2_2021"
25+
ssl_support_method = "sni-only"
26+
}
27+
28+
logging_config {
29+
bucket = module.s3bucket_cf_logs.bucket_regional_domain_name
30+
include_cookies = false
31+
}
32+
33+
origin {
34+
domain_name = module.backend_api.download_bucket_regional_domain_name
35+
origin_access_control_id = aws_cloudfront_origin_access_control.s3.id
36+
origin_id = "S3-${local.csi}-download"
37+
}
38+
39+
default_cache_behavior {
40+
allowed_methods = [
41+
"GET",
42+
"HEAD",
43+
"OPTIONS",
44+
]
45+
cached_methods = [
46+
"GET",
47+
"HEAD",
48+
]
49+
target_origin_id = "S3-${local.csi}-download"
50+
51+
forwarded_values {
52+
query_string = true
53+
headers = ["Origin"]
54+
55+
cookies {
56+
forward = "all"
57+
}
58+
}
59+
60+
viewer_protocol_policy = "redirect-to-https"
61+
min_ttl = 0
62+
default_ttl = 3600
63+
max_ttl = 86400
64+
compress = true
65+
}
66+
}
67+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "aws_cloudfront_origin_access_control" "s3" {
2+
provider = aws.us-east-1
3+
4+
name = "${local.csi}-s3bucket-download"
5+
description = "Origin Access Control for ${module.backend_api.download_bucket_name}"
6+
origin_access_control_origin_type = "s3"
7+
signing_behavior = "always"
8+
signing_protocol = "sigv4"
9+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
locals {
2-
root_domain_name = "${var.environment}.${local.acct.dns_zone["name"]}"
2+
cloudfront_files_domain_name = "files.${local.root_domain_name}"
3+
root_domain_name = "${var.environment}.${local.acct.dns_zone["name"]}"
34
}

infrastructure/terraform/components/app/module_backend_api.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ module "backend_api" {
1414
kms_key_arn = module.kms.key_arn
1515
parent_acct_environment = var.parent_acct_environment
1616

17+
cloudfront_distribution_arn = aws_cloudfront_distribution.main.arn
18+
1719
cognito_config = jsondecode(aws_ssm_parameter.cognito_config.value)
1820

1921
enable_backup = var.destination_vault_arn != null ? true : false

infrastructure/terraform/components/app/module_kms.tf

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,36 @@ data "aws_iam_policy_document" "kms" {
4343
"*",
4444
]
4545
}
46+
47+
statement {
48+
sid = "AllowCloudFrontServicePrincipalSSE-KMS"
49+
effect = "Allow"
50+
51+
principals {
52+
type = "Service"
53+
54+
identifiers = [
55+
"cloudfront.amazonaws.com",
56+
]
57+
}
58+
59+
actions = [
60+
"kms:Decrypt",
61+
"kms:Encrypt",
62+
"kms:GenerateDataKey*"
63+
]
64+
65+
resources = [
66+
"*",
67+
]
68+
69+
condition {
70+
test = "StringEquals"
71+
variable = "AWS:SourceArn"
72+
73+
values = [
74+
aws_cloudfront_distribution.main.arn,
75+
]
76+
}
77+
}
4678
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
module "s3bucket_cf_logs" {
2+
source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket?ref=v2.0.2"
3+
providers = {
4+
aws = aws.us-east-1
5+
}
6+
7+
name = "cf-logs"
8+
9+
aws_account_id = var.aws_account_id
10+
region = "us-east-1"
11+
project = var.project
12+
environment = var.environment
13+
component = var.component
14+
15+
acl = "private"
16+
force_destroy = false
17+
versioning = true
18+
19+
object_ownership = "ObjectWriter"
20+
21+
lifecycle_rules = [
22+
{
23+
prefix = ""
24+
enabled = true
25+
26+
transition = [
27+
{
28+
days = "90"
29+
storage_class = "STANDARD_IA"
30+
},
31+
{
32+
days = "180"
33+
storage_class = "GLACIER"
34+
}
35+
]
36+
37+
expiration = {
38+
days = "365"
39+
}
40+
41+
42+
noncurrent_version_transition = [
43+
{
44+
noncurrent_days = "30"
45+
storage_class = "STANDARD_IA"
46+
},
47+
{
48+
noncurrent_days = "180"
49+
storage_class = "GLACIER"
50+
}
51+
52+
]
53+
54+
noncurrent_version_expiration = {
55+
noncurrent_days = "365"
56+
}
57+
58+
abort_incomplete_multipart_upload = {
59+
days = "1"
60+
}
61+
}
62+
]
63+
64+
policy_documents = [
65+
data.aws_iam_policy_document.s3bucket_cf_logs.json
66+
]
67+
68+
public_access = {
69+
block_public_acls = true
70+
block_public_policy = true
71+
ignore_public_acls = true
72+
restrict_public_buckets = true
73+
}
74+
75+
default_tags = {
76+
Name = "Cloudfront Logs"
77+
}
78+
}
79+
80+
data "aws_iam_policy_document" "s3bucket_cf_logs" {
81+
statement {
82+
sid = "DontAllowNonSecureConnection"
83+
effect = "Deny"
84+
85+
actions = [
86+
"s3:*",
87+
]
88+
89+
resources = [
90+
module.s3bucket_cf_logs.arn,
91+
"${module.s3bucket_cf_logs.arn}/*",
92+
]
93+
94+
principals {
95+
type = "AWS"
96+
97+
identifiers = [
98+
"*",
99+
]
100+
}
101+
102+
condition {
103+
test = "Bool"
104+
variable = "aws:SecureTransport"
105+
106+
values = [
107+
"false",
108+
]
109+
}
110+
}
111+
112+
statement {
113+
effect = "Allow"
114+
actions = ["s3:PutObject"]
115+
resources = [
116+
"${module.s3bucket_cf_logs.arn}/*",
117+
]
118+
119+
principals {
120+
type = "Service"
121+
identifiers = ["logging.s3.amazonaws.com"]
122+
}
123+
condition {
124+
test = "StringEquals"
125+
variable = "aws:SourceAccount"
126+
values = [
127+
var.aws_account_id
128+
]
129+
}
130+
}
131+
132+
statement {
133+
sid = "AllowManagedAccountsToList"
134+
effect = "Allow"
135+
136+
actions = [
137+
"s3:ListBucket",
138+
]
139+
140+
resources = [
141+
module.s3bucket_cf_logs.arn,
142+
]
143+
144+
principals {
145+
type = "AWS"
146+
identifiers = [
147+
"arn:aws:iam::${var.aws_account_id}:root"
148+
]
149+
}
150+
}
151+
152+
statement {
153+
sid = "AllowManagedAccountsToGet"
154+
effect = "Allow"
155+
156+
actions = [
157+
"s3:GetObject",
158+
]
159+
160+
resources = [
161+
"${module.s3bucket_cf_logs.arn}/*",
162+
]
163+
164+
principals {
165+
type = "AWS"
166+
identifiers = [
167+
"arn:aws:iam::${var.aws_account_id}:root"
168+
]
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)