|
| 1 | +data "aws_caller_identity" "current" {} |
| 2 | + |
| 3 | +data "aws_partition" "current" {} |
| 4 | + |
| 5 | +locals { |
| 6 | + account_id = data.aws_caller_identity.current.account_id |
| 7 | + effective_bucket = var.state_bucket_name != "" ? var.state_bucket_name : "terraform-state-${local.account_id}" |
| 8 | + backend_repo_name = "${var.project_name}/backend" |
| 9 | + frontend_repo_name = "${var.project_name}/frontend" |
| 10 | +} |
| 11 | + |
| 12 | +resource "aws_s3_bucket" "terraform_state" { |
| 13 | + bucket = local.effective_bucket |
| 14 | + |
| 15 | + tags = { |
| 16 | + Name = local.effective_bucket |
| 17 | + Purpose = "terraform-state" |
| 18 | + } |
| 19 | +} |
| 20 | + |
| 21 | +resource "aws_s3_bucket_versioning" "terraform_state" { |
| 22 | + bucket = aws_s3_bucket.terraform_state.id |
| 23 | + |
| 24 | + versioning_configuration { |
| 25 | + status = "Enabled" |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" { |
| 30 | + bucket = aws_s3_bucket.terraform_state.id |
| 31 | + |
| 32 | + rule { |
| 33 | + apply_server_side_encryption_by_default { |
| 34 | + sse_algorithm = "AES256" |
| 35 | + } |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +resource "aws_s3_bucket_public_access_block" "terraform_state" { |
| 40 | + bucket = aws_s3_bucket.terraform_state.id |
| 41 | + |
| 42 | + block_public_acls = true |
| 43 | + block_public_policy = true |
| 44 | + ignore_public_acls = true |
| 45 | + restrict_public_buckets = true |
| 46 | +} |
| 47 | + |
| 48 | +resource "aws_dynamodb_table" "terraform_lock" { |
| 49 | + count = var.create_lock_table ? 1 : 0 |
| 50 | + name = var.lock_table_name |
| 51 | + billing_mode = "PAY_PER_REQUEST" |
| 52 | + hash_key = "LockID" |
| 53 | + |
| 54 | + attribute { |
| 55 | + name = "LockID" |
| 56 | + type = "S" |
| 57 | + } |
| 58 | + |
| 59 | + tags = { |
| 60 | + Name = var.lock_table_name |
| 61 | + Purpose = "terraform-lock-legacy" |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +resource "aws_ecr_repository" "backend" { |
| 66 | + name = local.backend_repo_name |
| 67 | + image_tag_mutability = "MUTABLE" |
| 68 | + |
| 69 | + image_scanning_configuration { |
| 70 | + scan_on_push = true |
| 71 | + } |
| 72 | + |
| 73 | + encryption_configuration { |
| 74 | + encryption_type = "AES256" |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +resource "aws_ecr_repository" "frontend" { |
| 79 | + name = local.frontend_repo_name |
| 80 | + image_tag_mutability = "MUTABLE" |
| 81 | + |
| 82 | + image_scanning_configuration { |
| 83 | + scan_on_push = true |
| 84 | + } |
| 85 | + |
| 86 | + encryption_configuration { |
| 87 | + encryption_type = "AES256" |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +resource "aws_iam_openid_connect_provider" "github" { |
| 92 | + url = "https://token.actions.githubusercontent.com" |
| 93 | + client_id_list = ["sts.amazonaws.com"] |
| 94 | + thumbprint_list = var.oidc_thumbprints |
| 95 | +} |
| 96 | + |
| 97 | +data "aws_iam_policy_document" "github_actions_trust" { |
| 98 | + statement { |
| 99 | + effect = "Allow" |
| 100 | + |
| 101 | + actions = ["sts:AssumeRoleWithWebIdentity"] |
| 102 | + |
| 103 | + principals { |
| 104 | + type = "Federated" |
| 105 | + identifiers = [aws_iam_openid_connect_provider.github.arn] |
| 106 | + } |
| 107 | + |
| 108 | + condition { |
| 109 | + test = "StringEquals" |
| 110 | + variable = "token.actions.githubusercontent.com:aud" |
| 111 | + values = ["sts.amazonaws.com"] |
| 112 | + } |
| 113 | + |
| 114 | + condition { |
| 115 | + test = "StringLike" |
| 116 | + variable = "token.actions.githubusercontent.com:sub" |
| 117 | + values = [ |
| 118 | + for env in var.github_environments : |
| 119 | + "repo:${var.github_org}/${var.github_repo}:environment:${env}" |
| 120 | + ] |
| 121 | + } |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +resource "aws_iam_role" "github_actions" { |
| 126 | + name = var.github_actions_role_name |
| 127 | + assume_role_policy = data.aws_iam_policy_document.github_actions_trust.json |
| 128 | +} |
| 129 | + |
| 130 | +data "aws_iam_policy_document" "github_actions_permissions" { |
| 131 | + statement { |
| 132 | + sid = "ECR" |
| 133 | + effect = "Allow" |
| 134 | + actions = ["ecr:*"] |
| 135 | + resources = [ |
| 136 | + aws_ecr_repository.backend.arn, |
| 137 | + aws_ecr_repository.frontend.arn, |
| 138 | + "arn:${data.aws_partition.current.partition}:ecr:${var.aws_region}:${local.account_id}:repository/${local.backend_repo_name}", |
| 139 | + "arn:${data.aws_partition.current.partition}:ecr:${var.aws_region}:${local.account_id}:repository/${local.frontend_repo_name}" |
| 140 | + ] |
| 141 | + } |
| 142 | + |
| 143 | + statement { |
| 144 | + sid = "ECRAuth" |
| 145 | + effect = "Allow" |
| 146 | + actions = ["ecr:GetAuthorizationToken"] |
| 147 | + resources = ["*"] |
| 148 | + } |
| 149 | + |
| 150 | + statement { |
| 151 | + sid = "ECSAndInfraDeploy" |
| 152 | + effect = "Allow" |
| 153 | + actions = [ |
| 154 | + "ecs:*", |
| 155 | + "ec2:*", |
| 156 | + "elasticloadbalancing:*", |
| 157 | + "logs:*", |
| 158 | + "cloudwatch:*", |
| 159 | + "secretsmanager:*", |
| 160 | + "kms:*", |
| 161 | + "rds:*" |
| 162 | + ] |
| 163 | + resources = ["*"] |
| 164 | + } |
| 165 | + |
| 166 | + statement { |
| 167 | + sid = "StateBucket" |
| 168 | + effect = "Allow" |
| 169 | + actions = ["s3:*"] |
| 170 | + resources = [ |
| 171 | + aws_s3_bucket.terraform_state.arn, |
| 172 | + "${aws_s3_bucket.terraform_state.arn}/*" |
| 173 | + ] |
| 174 | + } |
| 175 | + |
| 176 | + statement { |
| 177 | + sid = "LegacyLockTable" |
| 178 | + effect = "Allow" |
| 179 | + actions = ["dynamodb:*"] |
| 180 | + resources = var.create_lock_table ? [aws_dynamodb_table.terraform_lock[0].arn] : ["*"] |
| 181 | + } |
| 182 | + |
| 183 | + statement { |
| 184 | + sid = "PassRole" |
| 185 | + effect = "Allow" |
| 186 | + actions = ["iam:PassRole", "iam:GetRole", "iam:CreateServiceLinkedRole"] |
| 187 | + resources = ["*"] |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | +resource "aws_iam_role_policy" "github_actions" { |
| 192 | + name = "GitHubActionsPolicy" |
| 193 | + role = aws_iam_role.github_actions.id |
| 194 | + policy = data.aws_iam_policy_document.github_actions_permissions.json |
| 195 | +} |
0 commit comments