mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-02 03:53:24 +00:00
Add import-only dev and staging state with least-privilege HCP authentication and plan safety guards.
215 lines
6.2 KiB
HCL
215 lines
6.2 KiB
HCL
locals {
|
|
live_certificate_arn = "arn:aws:acm:${var.aws_region}:${local.account_id}:certificate/2b78e74f-7b65-4b82-a413-7a498b102f00"
|
|
live_github_oidc_arn = "arn:aws:iam::${local.account_id}:oidc-provider/token.actions.githubusercontent.com"
|
|
live_rds_arn = "arn:aws:rds:${var.aws_region}:${local.account_id}:db:shoc-sqlserver-shared"
|
|
|
|
live_environments = {
|
|
dev = {
|
|
workspace = "shoc-backend-dev"
|
|
deploy_role_name = "githubdeploy-shoc-backend-dev"
|
|
runtime_role_name = "shoc-backend-dev"
|
|
instance_profile_name = "shoc-backend-dev"
|
|
hosted_zone_id = "Z07671212N75U4YLPWZR8"
|
|
}
|
|
staging = {
|
|
workspace = "shoc-backend-staging"
|
|
deploy_role_name = "githubdeploy-shoc-backend-staging"
|
|
runtime_role_name = "shoc-backend-staging"
|
|
instance_profile_name = "shoc-backend-staging"
|
|
hosted_zone_id = "Z02602739VQWBWCAGXP4"
|
|
}
|
|
}
|
|
}
|
|
|
|
data "aws_iam_policy_document" "live_plan_assume" {
|
|
for_each = local.live_environments
|
|
|
|
statement {
|
|
effect = "Allow"
|
|
actions = ["sts:AssumeRoleWithWebIdentity"]
|
|
|
|
principals {
|
|
type = "Federated"
|
|
identifiers = [local.tfc_oidc_arn]
|
|
}
|
|
|
|
condition {
|
|
test = "StringEquals"
|
|
variable = "app.terraform.io:aud"
|
|
values = ["aws.workload.identity"]
|
|
}
|
|
|
|
condition {
|
|
test = "StringEquals"
|
|
variable = "app.terraform.io:sub"
|
|
values = ["organization:${var.hcp_organization}:project:${var.hcp_project}:workspace:${each.value.workspace}:run_phase:plan"]
|
|
}
|
|
}
|
|
}
|
|
|
|
data "aws_iam_policy_document" "live_apply_assume" {
|
|
for_each = local.live_environments
|
|
|
|
statement {
|
|
effect = "Allow"
|
|
actions = ["sts:AssumeRoleWithWebIdentity"]
|
|
|
|
principals {
|
|
type = "Federated"
|
|
identifiers = [local.tfc_oidc_arn]
|
|
}
|
|
|
|
condition {
|
|
test = "StringEquals"
|
|
variable = "app.terraform.io:aud"
|
|
values = ["aws.workload.identity"]
|
|
}
|
|
|
|
condition {
|
|
test = "StringEquals"
|
|
variable = "app.terraform.io:sub"
|
|
values = ["organization:${var.hcp_organization}:project:${var.hcp_project}:workspace:${each.value.workspace}:run_phase:apply"]
|
|
}
|
|
}
|
|
}
|
|
|
|
data "aws_iam_policy_document" "live_plan" {
|
|
for_each = local.live_environments
|
|
|
|
statement {
|
|
sid = "CallerIdentity"
|
|
effect = "Allow"
|
|
actions = ["sts:GetCallerIdentity"]
|
|
resources = ["*"]
|
|
}
|
|
|
|
statement {
|
|
sid = "ReadExactIamResources"
|
|
effect = "Allow"
|
|
actions = [
|
|
"iam:GetInstanceProfile",
|
|
"iam:GetRole",
|
|
"iam:GetRolePolicy",
|
|
"iam:ListAttachedRolePolicies",
|
|
"iam:ListInstanceProfileTags",
|
|
"iam:ListInstanceProfilesForRole",
|
|
"iam:ListRolePolicies",
|
|
"iam:ListRoleTags",
|
|
]
|
|
resources = [
|
|
"arn:aws:iam::${local.account_id}:role/${each.value.deploy_role_name}",
|
|
"arn:aws:iam::${local.account_id}:role/${each.value.runtime_role_name}",
|
|
"arn:aws:iam::${local.account_id}:instance-profile/${each.value.instance_profile_name}",
|
|
local.eb_service_role_arn,
|
|
]
|
|
}
|
|
|
|
statement {
|
|
sid = "ReadGithubOidc"
|
|
effect = "Allow"
|
|
actions = ["iam:GetOpenIDConnectProvider"]
|
|
resources = [local.live_github_oidc_arn]
|
|
}
|
|
|
|
statement {
|
|
sid = "ReadSharedInventory"
|
|
effect = "Allow"
|
|
actions = [
|
|
"acm:ListCertificates",
|
|
"ec2:DescribeSecurityGroups",
|
|
"ec2:DescribeSubnets",
|
|
"ec2:DescribeVpcs",
|
|
"iam:ListOpenIDConnectProviders",
|
|
"rds:DescribeDBInstances",
|
|
"route53:ListHostedZonesByName",
|
|
]
|
|
# These AWS read APIs do not support resource-level permissions.
|
|
resources = ["*"]
|
|
}
|
|
|
|
statement {
|
|
sid = "ReadPinnedCertificate"
|
|
effect = "Allow"
|
|
actions = ["acm:DescribeCertificate", "acm:ListTagsForCertificate"]
|
|
resources = [local.live_certificate_arn]
|
|
}
|
|
|
|
statement {
|
|
sid = "ReadSharedRdsTags"
|
|
effect = "Allow"
|
|
actions = ["rds:ListTagsForResource"]
|
|
resources = [local.live_rds_arn]
|
|
}
|
|
|
|
statement {
|
|
sid = "ReadPinnedHostedZone"
|
|
effect = "Allow"
|
|
actions = ["route53:GetHostedZone", "route53:ListResourceRecordSets", "route53:ListTagsForResource"]
|
|
resources = ["arn:aws:route53:::hostedzone/${each.value.hosted_zone_id}"]
|
|
}
|
|
}
|
|
|
|
data "aws_iam_policy_document" "live_apply" {
|
|
for_each = local.live_environments
|
|
source_policy_documents = [data.aws_iam_policy_document.live_plan[each.key].json]
|
|
|
|
statement {
|
|
sid = "UpdateImportedDeployRole"
|
|
effect = "Allow"
|
|
actions = [
|
|
"iam:PutRolePolicy",
|
|
"iam:TagRole",
|
|
"iam:UntagRole",
|
|
"iam:UpdateRole",
|
|
]
|
|
resources = ["arn:aws:iam::${local.account_id}:role/${each.value.deploy_role_name}"]
|
|
}
|
|
}
|
|
|
|
resource "aws_iam_role" "live_plan" {
|
|
for_each = local.live_environments
|
|
|
|
name = "hcptf-shoc-backend-${each.key}-plan"
|
|
description = "Import/read-only HCP Terraform plan role for shoc-backend ${each.key}."
|
|
assume_role_policy = data.aws_iam_policy_document.live_plan_assume[each.key].json
|
|
max_session_duration = 3600
|
|
permissions_boundary = var.execution_boundary_arn
|
|
|
|
depends_on = [terraform_data.account_guard]
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_iam_role_policy" "live_plan" {
|
|
for_each = local.live_environments
|
|
|
|
name = "shoc-backend-${each.key}-import-plan"
|
|
role = aws_iam_role.live_plan[each.key].id
|
|
policy = data.aws_iam_policy_document.live_plan[each.key].json
|
|
}
|
|
|
|
resource "aws_iam_role" "live_apply" {
|
|
for_each = local.live_environments
|
|
|
|
name = "hcptf-shoc-backend-${each.key}"
|
|
description = "Import/update-only HCP Terraform apply role for shoc-backend ${each.key}."
|
|
assume_role_policy = data.aws_iam_policy_document.live_apply_assume[each.key].json
|
|
max_session_duration = 3600
|
|
permissions_boundary = var.execution_boundary_arn
|
|
|
|
depends_on = [terraform_data.account_guard]
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_iam_role_policy" "live_apply" {
|
|
for_each = local.live_environments
|
|
|
|
name = "shoc-backend-${each.key}-import-apply"
|
|
role = aws_iam_role.live_apply[each.key].id
|
|
policy = data.aws_iam_policy_document.live_apply[each.key].json
|
|
}
|