Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/tf/github-actions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module "github_actions" {
source = "./modules/github-actions"

application_ses_policy_arns = local.application_ses_policy_arns
application_ses_senders = local.application_ses_senders
aws_account_id = data.aws_caller_identity.current.account_id
oidc_provider_arn = aws_iam_openid_connect_provider.github_actions.arn
ses_identity_arns = [for identity in aws_sesv2_email_identity.domain : identity.arn]
state_bucket_arn = aws_s3_bucket.tfstate_state.arn
state_bucket_name = aws_s3_bucket.tfstate_state.bucket
state_lock_table_arn = aws_dynamodb_table.tflock_state.arn
vm_workloads_bootstrap_parameter_arns = [
"arn:aws:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${local.sgfdevs_vms_eso_access_key_id_path}",
"arn:aws:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${local.sgfdevs_vms_eso_secret_access_key_path}",
]
vm_workloads_parameter_arn = "arn:aws:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${local.sgfdevs_vms_parameter_path}"
}
180 changes: 180 additions & 0 deletions src/tf/modules/github-actions/common.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
locals {
repositories = {
app_config = {
github_subject = "repo:sgfdevs@53604170/infra-app-config@1298907442"
repository = "sgfdevs/infra-app-config"
role_name = "GitHubActionsInfraAppConfigRole"
state_key = "sgfdevs-infra-app-config/terraform.tfstate"
state_prefix = "sgfdevs-infra-app-config"
}
dns = {
github_subject = "repo:sgfdevs@53604170/infra-dns@1191039220"
repository = "sgfdevs/infra-dns"
role_name = "GitHubActionsInfraDNSRole"
state_key = "sgfdevs-infra-dns/terraform.tfstate"
state_prefix = "sgfdevs-infra-dns"
}
gh = {
github_subject = "repo:sgfdevs@53604170/infra-gh@1331469226"
repository = "sgfdevs/infra-gh"
role_name = "GitHubActionsInfraGHRole"
state_key = "sgfdevs/infra-gh/terraform.tfstate"
state_prefix = "sgfdevs/infra-gh"
}
vm_workloads = {
github_subject = "repo:sgfdevs@53604170/infra-vm-workloads@1189754282"
repository = "sgfdevs/infra-vm-workloads"
role_name = "GitHubActionsInfraVMWorkloadsRole"
state_key = "sgfdevs-vm-workloads/terraform.tfstate"
state_prefix = "sgfdevs-vm-workloads"
}
}
}

resource "aws_iam_role" "github_actions" {
for_each = local.repositories

name = each.value.role_name

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = var.oidc_provider_arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
"token.actions.githubusercontent.com:sub" = [
"${each.value.github_subject}:ref:refs/heads/main",
"${each.value.github_subject}:pull_request",
]
}
}
}
]
})

tags = {
Environment = "global"
GitHubMainSubject = "${each.value.github_subject}:ref:refs/heads/main"
ManagedBy = "OpenTofu"
Name = "sgfdevs-github-actions-infra-${replace(each.key, "_", "-")}-role"
Repository = each.value.repository
TerraformStateKey = each.value.state_key
TerraformStatePrefix = each.value.state_prefix
}
}

resource "aws_iam_policy" "terraform_state_access" {
name = "GitHubActionsTerraformStateAccess"
description = "Repository-scoped OpenTofu state access derived from IAM role tags"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "ReadStateBucketMetadata"
Effect = "Allow"
Action = [
"s3:GetBucketLocation",
"s3:GetBucketVersioning",
]
Resource = var.state_bucket_arn
},
{
Sid = "ListRepositoryState"
Effect = "Allow"
Action = "s3:ListBucket"
Resource = var.state_bucket_arn
Condition = {
StringLike = {
"s3:prefix" = [
"$${aws:PrincipalTag/TerraformStatePrefix}",
"$${aws:PrincipalTag/TerraformStatePrefix}/*",
]
}
}
},
{
Sid = "ReadRepositoryState"
Effect = "Allow"
Action = "s3:GetObject"
Resource = "${var.state_bucket_arn}/$${aws:PrincipalTag/TerraformStateKey}"
},
{
Sid = "DescribeStateLockTable"
Effect = "Allow"
Action = "dynamodb:DescribeTable"
Resource = var.state_lock_table_arn
},
{
Sid = "ManageRepositoryStateLock"
Effect = "Allow"
Action = [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
]
Resource = var.state_lock_table_arn
Condition = {
"ForAllValues:StringEquals" = {
"dynamodb:LeadingKeys" = "${var.state_bucket_name}/$${aws:PrincipalTag/TerraformStateKey}"
}
}
},
{
Sid = "ReadRepositoryStateChecksum"
Effect = "Allow"
Action = "dynamodb:GetItem"
Resource = var.state_lock_table_arn
Condition = {
"ForAllValues:StringEquals" = {
"dynamodb:LeadingKeys" = "${var.state_bucket_name}/$${aws:PrincipalTag/TerraformStateKey}-md5"
}
}
},
{
Sid = "WriteRepositoryStateFromMain"
Effect = "Allow"
Action = "s3:PutObject"
Resource = "${var.state_bucket_arn}/$${aws:PrincipalTag/TerraformStateKey}"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
}
},
{
Sid = "WriteRepositoryStateChecksumFromMain"
Effect = "Allow"
Action = "dynamodb:PutItem"
Resource = var.state_lock_table_arn
Condition = {
"ForAllValues:StringEquals" = {
"dynamodb:LeadingKeys" = "${var.state_bucket_name}/$${aws:PrincipalTag/TerraformStateKey}-md5"
}
StringEquals = {
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
}
},
]
})

tags = {
Environment = "global"
ManagedBy = "OpenTofu"
Name = "sgfdevs-github-actions-terraform-state-access"
}
}

resource "aws_iam_role_policy_attachment" "terraform_state_access" {
for_each = local.repositories

role = aws_iam_role.github_actions[each.key].name
policy_arn = aws_iam_policy.terraform_state_access.arn
}
124 changes: 124 additions & 0 deletions src/tf/modules/github-actions/infra-app-config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
resource "aws_iam_role_policy" "github_actions_app_config" {
name = "InfraAppConfigRepositoryAccess"
role = aws_iam_role.github_actions["app_config"].id

policy = jsonencode({
Version = "2012-10-17"
Statement = concat(
[for key, application in var.application_ses_senders : {
Sid = "Create${replace(title(key), "_", "")}SESUsers"
Effect = "Allow"
Action = "iam:CreateUser"
Resource = "arn:aws:iam::${var.aws_account_id}:user/applications/${application.path}/*"
Condition = {
StringEquals = {
"aws:RequestTag/ManagedBy" = "OpenTofu"
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
StringLike = {
"aws:RequestTag/SESFromAddress" = "*@${application.domain}"
}
Null = {
"aws:RequestTag/Application" = "false"
}
"ForAllValues:StringEquals" = {
"aws:TagKeys" = [
"Application",
"Environment",
"ManagedBy",
"SESFromAddress",
]
}
}
}],
[for key, application in var.application_ses_senders : {
Sid = "AttachOnly${replace(title(key), "_", "")}SESPolicy"
Effect = "Allow"
Action = [
"iam:AttachUserPolicy",
"iam:DetachUserPolicy"
]
Resource = "arn:aws:iam::${var.aws_account_id}:user/applications/${application.path}/*"
Condition = {
ArnEquals = {
"iam:PolicyARN" = var.application_ses_policy_arns[key]
}
StringEquals = {
"iam:ResourceTag/ManagedBy" = "OpenTofu"
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
StringLike = {
"iam:ResourceTag/SESFromAddress" = "*@${application.domain}"
}
Null = {
"iam:ResourceTag/Application" = "false"
}
}
}],
[for key, application in var.application_ses_senders : {
Sid = "Read${replace(title(key), "_", "")}SESUsers"
Effect = "Allow"
Action = [
"iam:GetAccessKeyLastUsed",
"iam:GetUser",
"iam:ListAccessKeys",
"iam:ListAttachedUserPolicies",
"iam:ListGroupsForUser",
"iam:ListUserTags",
]
Resource = "arn:aws:iam::${var.aws_account_id}:user/applications/${application.path}/*"
Condition = {
StringEquals = {
"iam:ResourceTag/ManagedBy" = "OpenTofu"
}
StringLike = {
"iam:ResourceTag/SESFromAddress" = "*@${application.domain}"
}
Null = {
"iam:ResourceTag/Application" = "false"
}
}
}],
[for key, application in var.application_ses_senders : {
Sid = "Manage${replace(title(key), "_", "")}SESUsers"
Effect = "Allow"
Action = [
"iam:CreateAccessKey",
"iam:DeleteAccessKey",
"iam:DeleteUser",
"iam:TagUser",
"iam:UntagUser",
"iam:UpdateAccessKey",
"iam:UpdateUser",
]
Resource = "arn:aws:iam::${var.aws_account_id}:user/applications/${application.path}/*"
Condition = {
StringEquals = {
"iam:ResourceTag/ManagedBy" = "OpenTofu"
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
StringLike = {
"iam:ResourceTag/SESFromAddress" = "*@${application.domain}"
}
Null = {
"iam:ResourceTag/Application" = "false"
}
}
}],
[for key, application in var.application_ses_senders : {
Sid = "RejectInvalid${replace(title(key), "_", "")}SenderTags"
Effect = "Deny"
Action = "iam:TagUser"
Resource = "arn:aws:iam::${var.aws_account_id}:user/applications/${application.path}/*"
Condition = {
Null = {
"aws:RequestTag/SESFromAddress" = "false"
}
StringNotLike = {
"aws:RequestTag/SESFromAddress" = "*@${application.domain}"
}
}
}],
)
})
}
19 changes: 19 additions & 0 deletions src/tf/modules/github-actions/infra-dns.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
resource "aws_iam_role_policy" "github_actions_dns" {
name = "InfraDNSRepositoryAccess"
role = aws_iam_role.github_actions["dns"].id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "ReadSESIdentities"
Effect = "Allow"
Action = [
"ses:GetEmailIdentity",
"ses:ListTagsForResource",
]
Resource = var.ses_identity_arns
},
]
})
}
54 changes: 54 additions & 0 deletions src/tf/modules/github-actions/infra-vm-workloads.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
resource "aws_iam_role_policy" "github_actions_vm_workloads" {
name = "InfraVMWorkloadsRepositoryAccess"
role = aws_iam_role.github_actions["vm_workloads"].id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "ReadWorkloadParameters"
Effect = "Allow"
Action = [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:ListTagsForResource",
]
Resource = var.vm_workloads_parameter_arn
},
{
Sid = "ReadBootstrapParameters"
Effect = "Allow"
Action = [
"ssm:GetParameter",
"ssm:GetParameters",
]
Resource = var.vm_workloads_bootstrap_parameter_arns
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
}
},
{
Sid = "DescribeParameters"
Effect = "Allow"
Action = "ssm:DescribeParameters"
Resource = "*"
},
{
Sid = "ManageWorkloadParametersFromMain"
Effect = "Allow"
Action = [
"ssm:DeleteParameter",
"ssm:PutParameter",
]
Resource = var.vm_workloads_parameter_arn
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:sub" = "$${aws:PrincipalTag/GitHubMainSubject}"
}
}
},
]
})
}
Loading