1 | data "aws_region" "current" { |
2 | } |
3 | |
4 | resource "aws_s3_bucket" "frontend_bucket" { |
5 | force_destroy = "true" |
6 | } |
7 | |
8 | locals { |
9 | |
10 | |
11 | mime_type_mappings = { |
12 | html = "text/html", |
13 | js = "text/javascript", |
14 | mjs = "text/javascript", |
15 | css = "text/css" |
16 | } |
17 | } |
18 | |
19 | resource "aws_s3_object" "frontend_object" { |
20 | for_each = fileset("${path.module}/frontend", "*") |
21 | key = each.value |
22 | source = "${path.module}/frontend/${each.value}" |
23 | bucket = aws_s3_bucket.frontend_bucket.bucket |
24 | |
25 | etag = filemd5("${path.module}/frontend/${each.value}") |
26 | content_type = local.mime_type_mappings[concat(regexall("\\.([^\\.]*)$", each.value), [[""]])[0][0]] |
27 | cache_control = "no-store, max-age=0" |
28 | } |
29 | |
30 | resource "aws_s3_object" "frontend_config" { |
31 | key = "config.mjs" |
32 | content = <<EOF |
33 | export const cognitoLoginUrl = "https://${aws_cognito_user_pool_domain.domain.domain}.auth.${data.aws_region.current.name}.amazoncognito.com"; |
34 | export const clientId = "${aws_cognito_user_pool_client.client.id}"; |
35 | export const APIURL = "${aws_appsync_graphql_api.appsync.uris["GRAPHQL"]}"; |
36 | EOF |
37 | bucket = aws_s3_bucket.frontend_bucket.bucket |
38 | |
39 | content_type = "text/javascript" |
40 | cache_control = "no-store, max-age=0" |
41 | } |
42 | |
43 | resource "aws_cloudfront_distribution" "distribution" { |
44 | origin { |
45 | domain_name = aws_s3_bucket.frontend_bucket.bucket_regional_domain_name |
46 | origin_id = "s3" |
47 | origin_access_control_id = aws_cloudfront_origin_access_control.oac.id |
48 | } |
49 | |
50 | enabled = true |
51 | default_root_object = "index.html" |
52 | is_ipv6_enabled = true |
53 | http_version = "http2and3" |
54 | |
55 | default_cache_behavior { |
56 | allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] |
57 | cached_methods = ["GET", "HEAD"] |
58 | target_origin_id = "s3" |
59 | |
60 | forwarded_values { |
61 | query_string = false |
62 | cookies { |
63 | forward = "none" |
64 | } |
65 | } |
66 | |
67 | viewer_protocol_policy = "redirect-to-https" |
68 | } |
69 | restrictions { |
70 | geo_restriction { |
71 | restriction_type = "none" |
72 | } |
73 | } |
74 | |
75 | custom_error_response { |
76 | error_code = "404" |
77 | response_code = "200" |
78 | response_page_path = "/" |
79 | } |
80 | |
81 | custom_error_response { |
82 | error_code = "403" |
83 | response_code = "200" |
84 | response_page_path = "/" |
85 | } |
86 | |
87 | viewer_certificate { |
88 | cloudfront_default_certificate = true |
89 | } |
90 | } |
91 | |
92 | resource "aws_s3_bucket_policy" "oac" { |
93 | bucket = aws_s3_bucket.frontend_bucket.id |
94 | policy = data.aws_iam_policy_document.s3_policy.json |
95 | } |
96 | |
97 | data "aws_iam_policy_document" "s3_policy" { |
98 | statement { |
99 | actions = ["s3:GetObject"] |
100 | |
101 | resources = ["${aws_s3_bucket.frontend_bucket.arn}/*"] |
102 | |
103 | principals { |
104 | type = "Service" |
105 | identifiers = ["cloudfront.amazonaws.com"] |
106 | } |
107 | condition { |
108 | test = "StringEquals" |
109 | variable = "AWS:SourceArn" |
110 | values = [aws_cloudfront_distribution.distribution.arn] |
111 | } |
112 | } |
113 | } |
114 | |
115 | resource "aws_cloudfront_origin_access_control" "oac" { |
116 | name = "oac-${random_id.id.hex}" |
117 | origin_access_control_origin_type = "s3" |
118 | signing_behavior = "always" |
119 | signing_protocol = "sigv4" |
120 | } |
121 | |
122 | output "domain" { |
123 | value = aws_cloudfront_distribution.distribution.domain_name |
124 | } |
125 | |
126 | |