diff --git a/ops/services/10-config/README.md b/ops/services/10-config/README.md index 022a1ea32..b8bf4c67f 100644 --- a/ops/services/10-config/README.md +++ b/ops/services/10-config/README.md @@ -92,8 +92,8 @@ No requirements. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [env](#input\_env) | The application environment (dev, test, sandbox, prod) | `string` | n/a | yes | | [create\_local\_sops\_wrapper](#input\_create\_local\_sops\_wrapper) | When `true`, creates sops wrapper file at `bin/sopsw`. | `bool` | `false` | no | +| [parent\_env](#input\_parent\_env) | The parent environment of the current solution. Will correspond with `terraform.workspace`".
Necessary on `tofu init` and `tofu workspace select` \_only\_. In all other situations, parent env
will be divined from `terraform.workspace`. | `string` | `null` | no | | [region](#input\_region) | n/a | `string` | `"us-east-1"` | no | | [secondary\_region](#input\_secondary\_region) | n/a | `string` | `"us-west-2"` | no | diff --git a/ops/services/10-config/main.tf b/ops/services/10-config/main.tf index e7d96ec50..5423ec01d 100644 --- a/ops/services/10-config/main.tf +++ b/ops/services/10-config/main.tf @@ -1,5 +1,7 @@ locals { - service = "config" + service = "config" + default_tags = module.platform.default_tags + env = terraform.workspace } module "platform" { diff --git a/ops/services/10-config/values/prod.sopsw.yaml b/ops/services/10-config/values/prod.sopsw.yaml index a9e1f16e9..a257de1d9 100644 --- a/ops/services/10-config/values/prod.sopsw.yaml +++ b/ops/services/10-config/values/prod.sopsw.yaml @@ -200,6 +200,8 @@ /bcda/${env}/sensitive/worker/BB_CLIENT_CERT.pem: ENC[AES256_GCM,data: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,iv:yMdChzg2fjmCbjmchIuuSvoz+/6+FQILgqRhNs+2N2g=,tag:o8XGfQaH0jsabSkDO8q9NA==,type:str] /bcda/${env}/sensitive/worker/BB_CLIENT_KEY.pem: ENC[AES256_GCM,data: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,iv:UBLyIpokk1J1orOziKIMepzkV5sbFem4U1Bwzan8EKo=,tag:h1232aCofGKIEVwJlQV9wg==,type:str] /bcda/${env}/sensitive/worker/config.yml: ENC[AES256_GCM,data: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,iv:J/1ZH/uHwqaQJZY5GBaAtOJ90chS+IaoMEl203kzEAE=,tag:yBlnx3KxItJcRSvEoM/K5w==,type:str] +/bcda/${env}/bene_prefs/sensitive/iam_bucket_role_arn: ENC[AES256_GCM,data:fODp/5DSn5veEd2N7RYb9tQgHej3L7ut/Pfie7wKLBuDSM6vx2PvrJ4xQHPgd5pV6jOSxx1w17zc8ErT80CwCYf+agYki9zz/vRaMsJhnoCRpNxUZgAEB6LUqYTf/z8Wosod,iv:RE7M4VbXtYfvnUATm/LD+aztuMDUET2nWims3r6GYyA=,tag:VOXHOFICu4GfsU+KxILzJA==,type:str] +/bcda/${env}/bene_prefs/sensitive/sns_topic_arn: ENC[AES256_GCM,data:S2bIl7FM5W/WAN60B1Ls0i2m8sP60SW/ZxRPWXXrOwcP7EMlif0yMAcx21IdIaH+Ak0N500+TvwloK7VRh0hAbLt/ff5tU8=,iv:NIusJubYySLkhYWlCUoHXQWtaqIQuTFVy/XmGCtvQEo=,tag:vn8RWx3TvmjpjT7Grn1u8Q==,type:str] sops: kms: - arn: arn:aws:kms:us-east-1:${ACCOUNT_ID}:alias/bcda-prod diff --git a/ops/services/20-bene-prefs/README.md b/ops/services/20-bene-prefs/README.md new file mode 100644 index 000000000..9c0cc2073 --- /dev/null +++ b/ops/services/20-bene-prefs/README.md @@ -0,0 +1,79 @@ + + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.100.0 | + + +## Requirements + +No requirements. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [parent\_env](#input\_parent\_env) | The parent environment of the current solution. Will correspond with `terraform.workspace`".
Necessary on `tofu init` and `tofu workspace select` \_only\_. In all other situations, parent env
will be divined from `terraform.workspace`. | `string` | `null` | no | +| [region](#input\_region) | n/a | `string` | `"us-east-1"` | no | +| [secondary\_region](#input\_secondary\_region) | n/a | `string` | `"us-west-2"` | no | + + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [bucket](#module\_bucket) | github.com/CMSgov/cdap//terraform/modules/bucket | 787224b | +| [platform](#module\_platform) | github.com/CMSgov/cdap//terraform/modules/platform | ff2ef539fb06f2c98f0e3ce0c8f922bdacb96d66 | + + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy.assume_bucket_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.default_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_lambda_event_source_mapping.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_event_source_mapping) | resource | +| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.db](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_sns_topic_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_sqs_queue.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_iam_policy_document.assume_bucket_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.default_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_rds_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/rds_cluster) | data source | +| [aws_security_groups.db](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/security_groups) | data source | + + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/ops/services/20-bene-prefs/main.tf b/ops/services/20-bene-prefs/main.tf new file mode 100644 index 000000000..ea582474f --- /dev/null +++ b/ops/services/20-bene-prefs/main.tf @@ -0,0 +1,301 @@ +locals { + service = "bene-prefs" + default_tags = module.platform.default_tags + env = terraform.workspace + + account_id = module.platform.aws_caller_identity.account_id + kms_key_arn_primary = module.platform.kms_alias_primary.target_key_arn + kms_key_arn_secondary = module.platform.kms_alias_secondary.target_key_arn + name_prefix = "${local.service_prefix}-${local.service}" + private_subnets = nonsensitive(toset(keys(module.platform.private_subnets))) +} + +module "platform" { + source = "github.com/CMSgov/cdap//terraform/modules/platform?ref=ff2ef539fb06f2c98f0e3ce0c8f922bdacb96d66" + + providers = { aws = aws, aws.secondary = aws.secondary } + + app = local.app + env = local.env + root_module = "https://github.com/CMSgov/bcda-app/tree/main/ops/services/10-config" + service = local.service + ssm_root_map = { + bene_prefs = "/bcda/${local.env}/bene_prefs/" + } +} + +data "aws_rds_cluster" "this" { + cluster_identifier = "${local.app}-${local.env}-aurora" +} + +data "aws_security_groups" "db" { + tags = { + Name = "bcda-${local.env}-db" + } +} + +resource "aws_security_group_rule" "db" { + type = "ingress" + from_port = data.aws_rds_cluster.this.port + to_port = data.aws_rds_cluster.this.port + protocol = "tcp" + security_group_id = one([data.aws_security_groups.db.ids])[0] + source_security_group_id = aws_security_group.this.id +} + +# --------------------------------------------------------------------------- +# Managed policies +# --------------------------------------------------------------------------- + +data "aws_iam_policy_document" "assume_bucket_role" { + statement { + sid = "AssumeBucketRole" + actions = ["sts:AssumeRole"] + resources = [module.platform.ssm.bene_prefs.iam_bucket_role_arn.value] + } +} + +resource "aws_iam_policy" "assume_bucket_role" { + name = "bcda-${local.env}-${local.service}-assume-bucket-role" + path = module.platform.iam_defaults.path + description = "Allows ${local.service} to assume the S3 bucket role from SSM." + + policy = data.aws_iam_policy_document.assume_bucket_role.json +} + +data "aws_iam_policy_document" "default_function" { + statement { + sid = "SsmSqsLogsEc2" + actions = [ + "ssm:GetParameters", + "ssm:GetParameter", + "sqs:ReceiveMessage", + "sqs:GetQueueAttributes", + "sqs:DeleteMessage", + "logs:PutLogEvents", + "logs:CreateLogStream", + "logs:CreateLogGroup", + ] + resources = ["*"] #TODO: Consider splitting into discrete statements/policy allowances + } + statement { + + sid = "KmsEncryptDecrypt" + actions = [ + "kms:GenerateDataKey", + "kms:Encrypt", + "kms:Decrypt", + ] + resources = [ + local.kms_key_arn_primary, + local.kms_key_arn_secondary, + ] + } +} + +resource "aws_iam_policy" "default_function" { + name = "bcda-${local.env}-${local.service}-default-function" + path = module.platform.iam_defaults.path + description = "SSM, SQS, CloudWatch Logs, EC2 networking, and KMS permissions for ${local.service}." + + policy = data.aws_iam_policy_document.default_function.json +} + +# --------------------------------------------------------------------------- +# IAM role +# --------------------------------------------------------------------------- + +resource "aws_iam_role" "this" { + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + { + Action = [ + "sts:TagSession", + "sts:AssumeRoleWithWebIdentity", + ] + Condition = { + StringEquals = { + "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" + } + StringLike = { + "token.actions.githubusercontent.com:sub" = "repo:CMSgov/bcda-app:*" + } + } + Effect = "Allow" + Principal = { + Federated = "arn:aws:iam::${local.account_id}:oidc-provider/token.actions.githubusercontent.com" + } + }, + { + Action = [ + "sts:TagSession", + "sts:AssumeRole", + ] + Effect = "Allow" + Principal = { + AWS = [ + module.platform.kion_roles["ct-ado-dasg-application-admin"].arn, + module.platform.kion_roles["ct-ado-bcda-application-admin"].arn, + ] + } + }, + ] + }) + + force_detach_policies = true + name = "bcda-${local.env}-${local.service}" + path = module.platform.iam_defaults.path + permissions_boundary = module.platform.iam_defaults.boundary +} + +resource "aws_iam_role_policy_attachment" "this" { + #TODO: Complexity below is for eventual targeting of `test` and `prod` environments + for_each = { for k, v in { + assume_bucket_role = try(aws_iam_policy.assume_bucket_role.arn, "") + default_function = try(aws_iam_policy.default_function.arn, "") + } : k => v if length(v) > 0 } + + role = aws_iam_role.this.name + policy_arn = each.value +} + +module "bucket" { + source = "github.com/CMSgov/cdap//terraform/modules/bucket?ref=787224b" + + app = local.app + env = local.env + name = "${local.app}-${local.env}-${local.service}-lambda" + ssm_parameter = "/${local.app}/${local.env}/${local.service}/nonsensitive/bucket_name" +} + +resource "aws_lambda_function" "this" { + s3_key = "function-3540b70393e3dc30f375eee2e8635a65c6f21036.zip" + s3_bucket = module.bucket.id + package_type = "Zip" + handler = "bootstrap" + + function_name = local.name_prefix + description = "Ingests the most recent beneficiary opt-out list from BFD" + kms_key_arn = local.kms_key_arn_primary + memory_size = 128 + reserved_concurrent_executions = 1 + role = aws_iam_role.this.arn + runtime = "provided.al2023" + skip_destroy = false + timeout = 900 + architectures = [ + "x86_64", + ] + + tags = { + code = "https://github.com/CMSgov/bcda-app/tree/main/bcda/lambda/optout" + } + + lifecycle { + ignore_changes = [ + s3_object_version, + s3_key, + ] + } + + environment { + variables = { + APP_NAME = local.name_prefix + DB_HOST = "postgres://${data.aws_rds_cluster.this.endpoint}:${data.aws_rds_cluster.this.port}/bcda" + ENV = local.env + } + } + + ephemeral_storage { + size = 512 + } + + logging_config { + log_format = "Text" + log_group = "/aws/lambda/bcda-${local.env}-${local.service}" + } + + tracing_config { + mode = "Active" + } + + vpc_config { + ipv6_allowed_for_dual_stack = false + security_group_ids = [aws_security_group.this.id] + subnet_ids = local.private_subnets + } +} + +resource "aws_security_group" "this" { + description = "Temporary SG for ${local.name_prefix}" + egress = [ + { + cidr_blocks = [ + "0.0.0.0/0", + ] + description = "" + from_port = 0 + ipv6_cidr_blocks = [ + "::/0", + ] + prefix_list_ids = [] + protocol = "-1" + security_groups = [] + self = false + to_port = 0 + }, + ] + name = local.name_prefix + tags = { Name = local.name_prefix } +} + +resource "aws_sqs_queue" "this" { + content_based_deduplication = false + delay_seconds = 0 + fifo_queue = false + kms_data_key_reuse_period_seconds = 300 + kms_master_key_id = local.kms_key_arn_primary + name = local.name_prefix + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sqs:SendMessage" + Condition = { + ArnEquals = { + "aws:SourceArn" = module.platform.ssm.bene_prefs.sns_topic_arn.value + } + } + Effect = "Allow" + Principal = { + Service = "sns.amazonaws.com" + } + Resource = "arn:aws:sqs:us-east-1:${local.account_id}:${local.name_prefix}" + Sid = "SnsSendMessage" + }, + ] + }) + receive_wait_time_seconds = 0 + visibility_timeout_seconds = 900 +} + +resource "aws_sns_topic_subscription" "this" { + endpoint = aws_sqs_queue.this.arn + protocol = "sqs" + topic_arn = module.platform.ssm.bene_prefs.sns_topic_arn.value +} + +resource "aws_lambda_event_source_mapping" "this" { + event_source_arn = aws_sqs_queue.this.arn + function_name = aws_lambda_function.this.function_name + batch_size = 1 + enabled = true +} diff --git a/ops/services/20-bene-prefs/tofu.tf b/ops/services/20-bene-prefs/tofu.tf new file mode 120000 index 000000000..007a2292a --- /dev/null +++ b/ops/services/20-bene-prefs/tofu.tf @@ -0,0 +1 @@ +../root.tofu.tf \ No newline at end of file diff --git a/ops/services/README.md b/ops/services/README.md new file mode 100644 index 000000000..f0b30b1a8 --- /dev/null +++ b/ops/services/README.md @@ -0,0 +1,29 @@ +# BCDA Terraservices +- each directory herein is an opinionated module for terraform (tofu) +- each module is terraform workspace-enabled, unless otherwise specified +- the two-digit numbers for each module is significant and identifies the sequence of operations for ordered module application + +## Requirements +Some of these modules have requirements for local development or remote CI. Those are including (but not limited to): +- jq *and* yq for manipulating json and yaml documents +- awscli + +## Applying Changes +Applying changes for these modules requires initialization of the state **and** selection of the appropriate environmental workspace. +Both can be achieved with the following commands: + +```sh +### prod environment +TF_WORKSPACE=default tofu init -var parent_env=prod -reconfigure && tofu workspace select -var parent_env=prod -or-create prod + +### sandbox environment +TF_WORKSPACE=default tofu init -var parent_env=sandbox -reconfigure && tofu workspace select -var parent_env=sandbox -or-create sandbox + +### test environment +TF_WORKSPACE=default tofu init -var parent_env=test -reconfigure && tofu workspace select -var parent_env=test -or-create test + +### dev environment +TF_WORKSPACE=default tofu init -var parent_env=dev -reconfigure && tofu workspace select -var parent_env=dev -or-create dev +``` + +After the state has been initialized and the workspace selected, users or automation can apply changes by running `tofu apply`. diff --git a/ops/services/root.tofu.tf b/ops/services/root.tofu.tf index fb48b7b24..5b81e0078 100644 --- a/ops/services/root.tofu.tf +++ b/ops/services/root.tofu.tf @@ -1,12 +1,22 @@ # This root tofu.tf is symlink'd to by all per-env Terraservices. Changes to this tofu.tf apply to # _all_ Terraservices, so be careful! -variable "env" { - description = "The application environment (dev, test, sandbox, prod)" - type = string - validation { - condition = contains(["dev", "test", "sandbox", "prod"], var.env) - error_message = "Valid value for env is dev, test, sandbox, or prod." +locals { + app = "bcda" + established_envs = ["dev", "test", "sandbox", "prod"] + service_prefix = "${local.app}-${local.env}" + + parent_env = coalesce( + var.parent_env, + one([for x in local.established_envs : x if can(regex("${x}$$", terraform.workspace))]), + "invalid-parent-environment;do-better" + ) + + state_buckets = { + dev = "bcda-dev-tfstate-20250409202710600700000001" + test = "bcda-test-tfstate-20250409171646342600000001" + sandbox = "bcda-sandbox-tfstate-20250416201512973800000001" + prod = "bcda-prod-tfstate-20250411203841436200000001" } } @@ -22,33 +32,43 @@ variable "secondary_region" { type = string } -locals { - app = "bcda" - env = var.env - service_prefix = "${local.app}-${local.env}" - - state_buckets = { - dev = "bcda-dev-tfstate-20250409202710600700000001" - test = "bcda-test-tfstate-20250409171646342600000001" - sandbox = "bcda-sandbox-tfstate-20250416201512973800000001" - prod = "bcda-prod-tfstate-20250411203841436200000001" +variable "parent_env" { + description = <<-EOF + The parent environment of the current solution. Will correspond with `terraform.workspace`". + Necessary on `tofu init` and `tofu workspace select` _only_. In all other situations, parent env + will be divined from `terraform.workspace`. + EOF + type = string + nullable = true + default = null + validation { + condition = var.parent_env == null || one([for x in local.established_envs : x if var.parent_env == x && endswith(terraform.workspace, x)]) != null + error_message = "Invalid parent environment name." } } provider "aws" { region = var.region + default_tags { + tags = local.default_tags + } } provider "aws" { - alias = "secondary" + alias = "secondary" + region = var.secondary_region + default_tags { + tags = local.default_tags + } } terraform { backend "s3" { - bucket = local.state_buckets[local.env] + bucket = local.state_buckets[local.parent_env] + encrypt = true key = "ops/services/${local.service}/tofu.tfstate" - use_lockfile = true region = var.region + use_lockfile = true } }