mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-04 21:52:08 +00:00
365 lines
8.8 KiB
HCL
365 lines
8.8 KiB
HCL
locals {
|
|
bucket_arn = "arn:aws:s3:::${var.bucket_name}"
|
|
distribution_arn = "arn:aws:cloudfront::${var.aws_account_id}:distribution/${var.distribution_id}"
|
|
resource_tags = var.adoption_complete ? var.ownership_tags : var.pre_adoption_tags
|
|
bucket_tags = var.adoption_complete ? var.ownership_tags : var.pre_adoption_bucket_tags
|
|
deploy_role_tags = var.adoption_complete ? var.post_adoption_deploy_role_tags : var.pre_adoption_deploy_role_tags
|
|
github_subject_operator = var.pre_adoption_github_subject_operator
|
|
|
|
spa_rewrite_code = join("\n", [
|
|
"function handler(event) {",
|
|
" var request = event.request;",
|
|
" var uri = request.uri;",
|
|
" // No file extension after the last slash -> a client-side route.",
|
|
" if (uri.lastIndexOf('.') <= uri.lastIndexOf('/')) {",
|
|
" request.uri = '/index.html';",
|
|
" }",
|
|
" return request;",
|
|
"}",
|
|
])
|
|
}
|
|
|
|
data "aws_iam_policy_document" "site_bucket" {
|
|
dynamic "statement" {
|
|
for_each = var.adoption_complete ? [] : [1]
|
|
|
|
content {
|
|
effect = "Allow"
|
|
|
|
principals {
|
|
type = "AWS"
|
|
identifiers = [var.bucket_auto_delete_helper_role_arn]
|
|
}
|
|
|
|
actions = [
|
|
"s3:DeleteObject*",
|
|
"s3:GetBucket*",
|
|
"s3:List*",
|
|
"s3:PutBucketPolicy",
|
|
]
|
|
resources = [
|
|
local.bucket_arn,
|
|
"${local.bucket_arn}/*",
|
|
]
|
|
}
|
|
}
|
|
|
|
statement {
|
|
effect = "Allow"
|
|
|
|
principals {
|
|
type = "Service"
|
|
identifiers = ["cloudfront.amazonaws.com"]
|
|
}
|
|
|
|
actions = ["s3:GetObject"]
|
|
resources = ["${local.bucket_arn}/*"]
|
|
|
|
condition {
|
|
test = "StringEquals"
|
|
variable = "AWS:SourceArn"
|
|
values = [local.distribution_arn]
|
|
}
|
|
}
|
|
|
|
statement {
|
|
effect = "Deny"
|
|
|
|
principals {
|
|
type = "AWS"
|
|
identifiers = ["*"]
|
|
}
|
|
|
|
actions = ["s3:*"]
|
|
resources = [
|
|
local.bucket_arn,
|
|
"${local.bucket_arn}/*",
|
|
]
|
|
|
|
condition {
|
|
test = "Bool"
|
|
variable = "aws:SecureTransport"
|
|
values = ["false"]
|
|
}
|
|
}
|
|
}
|
|
|
|
data "aws_iam_policy_document" "github_deploy_assume" {
|
|
statement {
|
|
effect = "Allow"
|
|
actions = ["sts:AssumeRoleWithWebIdentity"]
|
|
|
|
principals {
|
|
type = "Federated"
|
|
identifiers = [var.github_oidc_provider_arn]
|
|
}
|
|
|
|
condition {
|
|
test = "StringEquals"
|
|
variable = "token.actions.githubusercontent.com:aud"
|
|
values = ["sts.amazonaws.com"]
|
|
}
|
|
|
|
condition {
|
|
test = local.github_subject_operator
|
|
variable = "token.actions.githubusercontent.com:sub"
|
|
values = [var.github_subject]
|
|
}
|
|
}
|
|
}
|
|
|
|
data "aws_iam_policy_document" "github_deploy" {
|
|
# Byte-identical to the live GitHub content policy through Phase 2 so
|
|
# aws_iam_role_policy.github_deploy stays no-op. Phase 3 replaces this
|
|
# with the release-prefix policy.
|
|
dynamic "statement" {
|
|
for_each = var.environment == "dev" ? [1] : []
|
|
|
|
content {
|
|
sid = "AssumeCdkBootstrapRoles"
|
|
effect = "Allow"
|
|
actions = ["sts:AssumeRole"]
|
|
resources = ["arn:aws:iam::${var.aws_account_id}:role/cdk-hnb659fds-*"]
|
|
}
|
|
}
|
|
|
|
statement {
|
|
sid = "DescribeStack"
|
|
effect = "Allow"
|
|
actions = ["cloudformation:DescribeStacks"]
|
|
resources = ["arn:aws:cloudformation:${var.aws_region}:${var.aws_account_id}:stack/${var.cloudformation_stack_name}/*"]
|
|
}
|
|
|
|
statement {
|
|
effect = "Allow"
|
|
actions = [
|
|
"s3:Abort*",
|
|
"s3:DeleteObject*",
|
|
"s3:GetBucket*",
|
|
"s3:GetObject*",
|
|
"s3:List*",
|
|
"s3:PutObject",
|
|
"s3:PutObjectLegalHold",
|
|
"s3:PutObjectRetention",
|
|
"s3:PutObjectTagging",
|
|
"s3:PutObjectVersionTagging",
|
|
]
|
|
resources = [
|
|
local.bucket_arn,
|
|
"${local.bucket_arn}/*",
|
|
]
|
|
}
|
|
|
|
statement {
|
|
sid = "InvalidateDistribution"
|
|
effect = "Allow"
|
|
actions = [
|
|
"cloudfront:CreateInvalidation",
|
|
"cloudfront:GetInvalidation",
|
|
]
|
|
resources = [local.distribution_arn]
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket" "site" {
|
|
bucket = var.bucket_name
|
|
force_destroy = false
|
|
tags = local.bucket_tags
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_public_access_block" "site" {
|
|
bucket = aws_s3_bucket.site.id
|
|
|
|
block_public_acls = true
|
|
block_public_policy = true
|
|
ignore_public_acls = true
|
|
restrict_public_buckets = true
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_ownership_controls" "site" {
|
|
bucket = aws_s3_bucket.site.id
|
|
|
|
rule {
|
|
object_ownership = "BucketOwnerEnforced"
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_server_side_encryption_configuration" "site" {
|
|
bucket = aws_s3_bucket.site.id
|
|
|
|
rule {
|
|
apply_server_side_encryption_by_default {
|
|
sse_algorithm = "AES256"
|
|
}
|
|
|
|
bucket_key_enabled = false
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_versioning" "site" {
|
|
bucket = aws_s3_bucket.site.id
|
|
|
|
versioning_configuration {
|
|
status = "Enabled"
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_policy" "site" {
|
|
bucket = aws_s3_bucket.site.id
|
|
policy = data.aws_iam_policy_document.site_bucket.json
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_cloudfront_origin_access_control" "site" {
|
|
name = var.origin_access_control_name
|
|
description = var.origin_access_control_description
|
|
origin_access_control_origin_type = "s3"
|
|
signing_behavior = "always"
|
|
signing_protocol = "sigv4"
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_cloudfront_function" "spa_rewrite" {
|
|
name = var.function_name
|
|
runtime = "cloudfront-js-1.0"
|
|
comment = "SPA routing: rewrite extensionless paths to /index.html"
|
|
publish = true
|
|
code = local.spa_rewrite_code
|
|
tags = local.resource_tags
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
ignore_changes = [publish]
|
|
}
|
|
}
|
|
|
|
resource "aws_cloudfront_distribution" "site" {
|
|
aliases = [var.domain_name]
|
|
comment = "SeaHaven SHOC frontend (${var.environment})"
|
|
default_root_object = "index.html"
|
|
enabled = true
|
|
http_version = "http2and3"
|
|
is_ipv6_enabled = true
|
|
price_class = "PriceClass_100"
|
|
tags = local.resource_tags
|
|
|
|
origin {
|
|
connection_attempts = 3
|
|
connection_timeout = 10
|
|
domain_name = aws_s3_bucket.site.bucket_regional_domain_name
|
|
origin_access_control_id = aws_cloudfront_origin_access_control.site.id
|
|
origin_id = var.origin_id
|
|
}
|
|
|
|
default_cache_behavior {
|
|
allowed_methods = ["GET", "HEAD", "OPTIONS"]
|
|
cache_policy_id = var.cache_policy_id
|
|
cached_methods = ["GET", "HEAD"]
|
|
compress = true
|
|
target_origin_id = var.origin_id
|
|
viewer_protocol_policy = "redirect-to-https"
|
|
|
|
function_association {
|
|
event_type = "viewer-request"
|
|
function_arn = aws_cloudfront_function.spa_rewrite.arn
|
|
}
|
|
}
|
|
|
|
restrictions {
|
|
geo_restriction {
|
|
restriction_type = "none"
|
|
}
|
|
}
|
|
|
|
viewer_certificate {
|
|
acm_certificate_arn = var.certificate_arn
|
|
minimum_protocol_version = "TLSv1.2_2021"
|
|
ssl_support_method = "sni-only"
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_route53_record" "site_a" {
|
|
zone_id = var.hosted_zone_id
|
|
name = var.domain_name
|
|
type = "A"
|
|
|
|
alias {
|
|
name = aws_cloudfront_distribution.site.domain_name
|
|
zone_id = aws_cloudfront_distribution.site.hosted_zone_id
|
|
evaluate_target_health = false
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_route53_record" "site_aaaa" {
|
|
zone_id = var.hosted_zone_id
|
|
name = var.domain_name
|
|
type = "AAAA"
|
|
|
|
alias {
|
|
name = aws_cloudfront_distribution.site.domain_name
|
|
zone_id = aws_cloudfront_distribution.site.hosted_zone_id
|
|
evaluate_target_health = false
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_iam_role" "github_deploy" {
|
|
name = var.deploy_role_name
|
|
path = "/"
|
|
description = "GitHub Actions deploy role for Sea-Haven-Industries/shoc-frontend-new@${var.deploy_branch}"
|
|
assume_role_policy = data.aws_iam_policy_document.github_deploy_assume.json
|
|
max_session_duration = 3600
|
|
permissions_boundary = var.deploy_permissions_boundary_arn
|
|
tags = local.deploy_role_tags
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_iam_role_policy" "github_deploy" {
|
|
name = var.deploy_inline_policy_name
|
|
role = aws_iam_role.github_deploy.id
|
|
policy = data.aws_iam_policy_document.github_deploy.json
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|