From 093db536f08b5f5f35fb803ee057ed860ef38732 Mon Sep 17 00:00:00 2001 From: Mitchell Alessio <5306896+malessi@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:17:35 -0400 Subject: [PATCH] BFD-3583: Update GHA IAM Role with permissions to apply static-site Terraservice (#2430) --- ops/terraform/env/mgmt/data-sources.tf | 7 + ops/terraform/env/mgmt/github-actions-iam.tf | 238 +++++++++++++++++- ops/terraform/env/mgmt/main.tf | 1 + ops/terraform/services/static-site/README.md | 5 +- ops/terraform/services/static-site/main.tf | 8 +- ops/terraform/services/static-site/s3.tf | 7 +- .../services/static-site/variables.tf | 5 - 7 files changed, 250 insertions(+), 21 deletions(-) delete mode 100644 ops/terraform/services/static-site/variables.tf diff --git a/ops/terraform/env/mgmt/data-sources.tf b/ops/terraform/env/mgmt/data-sources.tf index e08ae497db..cc96bbb669 100644 --- a/ops/terraform/env/mgmt/data-sources.tf +++ b/ops/terraform/env/mgmt/data-sources.tf @@ -57,3 +57,10 @@ data "aws_ssm_parameter" "cpm_aws_account_arn" { data "aws_ssm_parameters_by_path" "common_sensitive" { path = "/bfd/${local.env}/common/sensitive" } + +data "aws_ec2_managed_prefix_list" "vpn" { + filter { + name = "prefix-list-name" + values = ["cmscloud-vpn"] + } +} diff --git a/ops/terraform/env/mgmt/github-actions-iam.tf b/ops/terraform/env/mgmt/github-actions-iam.tf index 2fee35e878..96c68a726a 100644 --- a/ops/terraform/env/mgmt/github-actions-iam.tf +++ b/ops/terraform/env/mgmt/github-actions-iam.tf @@ -101,6 +101,239 @@ resource "aws_iam_policy" "github_actions_ecr" { ) } +resource "aws_iam_policy" "github_actions_tf_state" { + name = "bfd-${local.env}-gha-tf-state" + description = "Grants permissions necessary for GHA to modify/read Terraform state" + path = "/" + policy = jsonencode( + { + Statement = [ + { + Sid = "AllowTerraformDynamoStateManagement" + Effect = "Allow" + Action = [ + "dynamodb:DeleteItem", + "dynamodb:GetItem", + "dynamodb:PutItem" + ] + Resource = "arn:aws:dynamodb:${local.region}:${local.account_id}:table/bfd-tf-table" + }, + { + Sid = "AllowTerraformS3StateManagement" + Effect = "Allow" + Action = [ + "s3:ListBucket", + "s3:GetObject*", + "s3:PutObject*" + ] + Resource = ["arn:aws:s3:::bfd-tf-state", "arn:aws:s3:::bfd-tf-state/*"] + }, + { + Sid = "AllowDescribeAndUseOfStateCMK" + Effect = "Allow" + Action = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ] + Resource = data.aws_kms_key.tf_state.arn + }, + ] + Version = "2012-10-17" + } + ) +} + +resource "aws_iam_policy" "github_actions_tf_logs" { + name = "bfd-${local.env}-gha-tf-logs" + description = "Grants permissions necessary for GHA to submit Terraform logs to CloudWatch Logs" + path = "/" + policy = jsonencode( + { + Statement = [ + { + Sid = "AllowCloudWatchLogsDescribeActions" + Effect = "Allow" + Action = [ + "logs:DescribeLogGroups", + "logs:DescribeLogStreams" + ] + Resource = "*" + }, + { + Sid = "AllowCloudWatchLogStreamActions" + Effect = "Allow" + Action = [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + Resource = [ + "arn:aws:logs:${local.region}:${local.account_id}:log-group:*:log-stream:*" + ] + }, + { + Sid = "AllowDescribeAndEncryptWithDataCMKs" + Effect = "Allow" + Action = [ + "kms:Encrypt", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ] + Resource = local.all_kms_data_key_arns + } + ] + Version = "2012-10-17" + } + ) +} + +# FUTURE: When IAM Role-based permissions are introduced, refactor this policy out into a generic resource +resource "aws_iam_policy" "github_actions_static_site" { + name = "bfd-${local.env}-static-site" + description = join("", [ + "Grants permissions necessary to apply the static-site Terraservice and manipulate the Static", + " Site artifacts in any environment" + ]) + path = "/" + policy = jsonencode( + { + Statement = [ + { + Sid = "AllowAllCloudfrontActions" + Action = [ + "cloudfront:*" + ] + Effect = "Allow" + Resource = "*" + }, + { + Sid = "AllowManagementOfStaticSiteBuckets" + Effect = "Allow" + Action = [ + "s3:CreateBucket*", + "s3:PutBucket*", + "s3:GetBucket*", + "s3:ListBucket*", + "s3:DeleteBucket*", + "s3:*LifecycleConfiguration", + "s3:*EncryptionConfiguration", + "s3:*AccelerateConfiguration", + "s3:*ReplicationConfiguration" + ] + Resource = ["arn:aws:s3:::bfd-*-static", "arn:aws:s3:::bfd-*-staticlogging"] + }, + { + Sid = "AllowFullControlOfStaticSiteBucketObjects" + Effect = "Allow" + Action = [ + "s3:CreateObject*", + "s3:PutObject*", + "s3:GetObject*", + "s3:ListObject*", + "s3:DeleteObject*", + "s3:AbortMultipartUpload", + "s3:ListMultipartUploadParts" + ] + Resource = ["arn:aws:s3:::bfd-*-static/*", "arn:aws:s3:::bfd-*-staticlogging/*"] + }, + { + Sid = "AllowUnconditionalDescribeActions" + Effect = "Allow" + Action = [ + "ec2:DescribeManagedPrefixLists", + "ec2:DescribeRouteTables", + "ec2:DescribeVpcs", + "route53:ListHostedZones", + "s3:ListAllMyBuckets", + "sts:GetCallerIdentity" + ] + Resource = "*" + }, + { + Sid = "AllowGetHostedZoneParams" + Effect = "Allow" + Action = [ + "ssm:GetParameter" + ] + Resource = [ + "arn:aws:ssm:${local.region}:${local.account_id}:parameter/bfd/mgmt/common/sensitive/r53_hosted_zone_root_domain", + "arn:aws:ssm:${local.region}:${local.account_id}:parameter/bfd/mgmt/common/sensitive/r53_hosted_zone_root_is_private" + ] + }, + { + Sid = "AllowGetStaticSiteAndCommonParams" + Effect = "Allow" + Action = [ + "ssm:GetParametersByPath" + ] + Resource = [ + "arn:aws:ssm:${local.region}:${local.account_id}:parameter/bfd/*/static-site*", + "arn:aws:ssm:${local.region}:${local.account_id}:parameter/bfd/*/common*" + ] + }, + { + Sid = "AllowGetVpnPrefixList" + Effect = "Allow" + Action = [ + "ec2:GetManagedPrefixListEntries" + ] + Resource = data.aws_ec2_managed_prefix_list.vpn.arn + }, + { + Sid = "AllowGetRootHostedZone" + Effect = "Allow" + Action = [ + "route53:GetHostedZone" + ] + Resource = aws_route53_zone.zones["root"].arn + }, + { + Sid = "AllowListingRoute53ResourceRecordSets" + Effect = "Allow" + Action = [ + "route53:ListResourceRecordSets" + ] + Resource = "arn:aws:route53:::hostedzone/*" + }, + { + Sid = "AllowListingRoute53Tags" + Effect = "Allow" + Action = [ + "route53:ListTagsForResource" + ] + Resource = [ + "arn:aws:route53:::healthcheck/*", + "arn:aws:route53:::hostedzone/*" + ] + }, + { + Sid = "AllowDescribeVpcAttributes" + Effect = "Allow" + Action = [ + "ec2:DescribeVpcAttribute" + ] + Resource = "arn:aws:ec2:${local.region}:${local.account_id}:vpc/*" + }, + { + Sid = "AllowDescribeAndUseOfCMKs" + Effect = "Allow" + Action = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ] + Resource = concat(local.all_kms_config_key_arns, local.all_kms_data_key_arns) + } + ] + Version = "2012-10-17" + } + ) +} + data "tls_certificate" "github_actions" { url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration" } @@ -119,7 +352,10 @@ resource "aws_iam_role" "github_actions" { managed_policy_arns = [ aws_iam_policy.code_artifact_rw.arn, aws_iam_policy.github_actions_s3its.arn, - aws_iam_policy.github_actions_ecr.arn + aws_iam_policy.github_actions_ecr.arn, + aws_iam_policy.github_actions_tf_state.arn, + aws_iam_policy.github_actions_tf_logs.arn, + aws_iam_policy.github_actions_static_site.arn ] assume_role_policy = jsonencode( diff --git a/ops/terraform/env/mgmt/main.tf b/ops/terraform/env/mgmt/main.tf index 4ce1e8fcee..b9bf9af9e0 100644 --- a/ops/terraform/env/mgmt/main.tf +++ b/ops/terraform/env/mgmt/main.tf @@ -28,6 +28,7 @@ locals { init_fail_alarm_name = "bfd-${local.env}-cloud-init-failure" # + all_kms_data_key_arns = concat(values(aws_kms_key.data_keys)[*].arn, values(aws_kms_key.data_keys_alt)[*].arn) all_kms_config_key_arns = flatten( [ for v in concat( diff --git a/ops/terraform/services/static-site/README.md b/ops/terraform/services/static-site/README.md index 46e7d23e5e..0abead3d84 100644 --- a/ops/terraform/services/static-site/README.md +++ b/ops/terraform/services/static-site/README.md @@ -32,9 +32,7 @@ terraform apply ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [bfd\_version\_override](#input\_bfd\_version\_override) | BFD release version override. When empty, defaults to resolving the release version from GitHub releases. | `string` | `null` | no | +No inputs.