social-network
social-network/frontend.tf
1
data "aws_region" "current" {
2
}
3
4
resource "aws_s3_bucket" "frontend_bucket" {
5
  force_destroy = "true"
6
}
7
8
locals {
9
  # Maps file extensions to mime types
10
  # Need to add more if needed
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