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 }