Skip to content

Commit 9389a80

Browse files
juliareynolds-navajscott-navagsfmichaeljvaldes
authored
[PLT-1358] Add SOPS to cdap to manage SSM parameter store (#324)
## 🎫 Ticket https://jira.cms.gov/browse/PLT-1358 ## 🛠 Changes Added a config service that uses SOPS to store parameters ## ℹ️ Context Adoption of the SOPS standard for CDAP ## 🧪 Validation See successful test run here: https://github.com/CMSgov/cdap/actions/runs/19517296089 --------- Co-authored-by: jscott-nava <julianscott@navapbc.com> Co-authored-by: Sean Fern <seanfern@navapbc.com> Co-authored-by: Michael Valdes <michaelvaldes@navapbc.com>
1 parent 0bf5f61 commit 9389a80

10 files changed

Lines changed: 209 additions & 3 deletions

File tree

.github/workflows/tf-config.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: tf-config
2+
run-name: tf-config ${{ (inputs.apply || (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'schedule') && 'apply' || 'plan' }}
3+
4+
on:
5+
push:
6+
paths:
7+
- .github/workflows/tf-config.yml
8+
- terraform/services/config/**
9+
schedule:
10+
- cron: "12 14 * * 1-5"
11+
workflow_dispatch:
12+
inputs:
13+
apply:
14+
required: false
15+
type: boolean
16+
description: "Apply the terraform?"
17+
18+
env:
19+
TENV_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20+
21+
defaults:
22+
run:
23+
working-directory: ./terraform/services/config
24+
25+
jobs:
26+
check-fmt:
27+
runs-on: codebuild-cdap-${{github.run_id}}-${{github.run_attempt}}
28+
steps:
29+
- uses: actions/checkout@v4
30+
- uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
31+
- uses: cmsgov/cdap/actions/setup-tenv@8343fb96563ce4b74c4dececee9b268f42bd4a40
32+
- run: tofu fmt -check -diff -recursive .
33+
plan-apply:
34+
needs: check-fmt
35+
permissions:
36+
contents: read
37+
id-token: write
38+
runs-on: codebuild-cdap-${{github.run_id}}-${{github.run_attempt}}
39+
strategy:
40+
fail-fast: false
41+
matrix:
42+
app: [bcda]
43+
env: [test,prod]
44+
steps:
45+
- uses: actions/checkout@v4
46+
- uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
47+
- uses: cmsgov/cdap/actions/setup-tenv@8343fb96563ce4b74c4dececee9b268f42bd4a40
48+
- uses: cmsgov/cdap/actions/setup-yq@328406d6e1d435b4e3da598bcdab22e576c3945e
49+
- uses: cmsgov/cdap/actions/setup-sops@84a6bcee5b70d63c44f8fec4f9b542cb5ec29a54
50+
- uses: aws-actions/configure-aws-credentials@v4
51+
with:
52+
role-to-assume: arn:aws:iam::${{ contains(fromJSON('["dev", "test"]'), matrix.env) && secrets.NON_PROD_ACCOUNT || secrets.PROD_ACCOUNT }}:role/delegatedadmin/developer/${{ matrix.app }}-${{ matrix.env }}-github-actions
53+
aws-region: ${{ vars.AWS_REGION }}
54+
- run: tofu init -backend-config=../../backends/${{ matrix.app }}-${{ matrix.env }}.s3.tfbackend
55+
- run: tofu plan -out=tf.plan
56+
env:
57+
TF_VAR_app: ${{ matrix.app }}
58+
TF_VAR_env: ${{ matrix.env }}
59+
- if: inputs.apply || (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'schedule'
60+
run: tofu apply -auto-approve tf.plan

terraform/modules/sops/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ output "edit" {
4242
value = module.sops.sopsw
4343
}
4444
```
45-
46-
45+
SOPS documentation: https://confluence.cms.gov/spaces/ODI/pages/1353352386/SOPS+for+Secrets+Management
4746

4847
<!-- TODO: Write standards, examples, etc for usage of this module -->
4948

terraform/modules/sops/variables.tf

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
variable "platform" {
22
description = "Object that describes standardized platform values."
3-
type = any
3+
type = object({
4+
app = string,
5+
parent_env = string,
6+
env = string,
7+
kms_alias_primary = object({
8+
target_key_arn = string,
9+
}),
10+
service = string,
11+
is_ephemeral_env = string
12+
})
413
}
514

615
variable "sopsw_values_file_extension" {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# CDAP Config Root Module
2+
3+
This root module is responsible for configuring the sops-enabled strategy for storing sensitive and nonsensitive configuration in AWS SSM Parameter Store.
4+
The _parent environment_ specific configuration values are located in the `values` directory.
5+
6+
<!-- BEGIN_TF_DOCS -->
7+
## Requirements
8+
9+
| Name | Version |
10+
|------|---------|
11+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5 |
12+
13+
## Providers
14+
15+
No providers.
16+
17+
## Modules
18+
19+
| Name | Source | Version |
20+
|------|--------|---------|
21+
| <a name="module_platform"></a> [platform](#module\_platform) | github.com/CMSgov/cdap//terraform/modules/platform | ff2ef539fb06f2c98f0e3ce0c8f922bdacb96d66 |
22+
| <a name="module_sops"></a> [sops](#module\_sops) | github.com/CMSgov/cdap//terraform/modules/sops | ff2ef539fb06f2c98f0e3ce0c8f922bdacb96d66 |
23+
24+
## Resources
25+
26+
No resources.
27+
28+
## Inputs
29+
30+
| Name | Description | Type | Default | Required |
31+
|------|-------------|------|---------|:--------:|
32+
| <a name="input_region"></a> [region](#input\_region) | n/a | `string` | `"us-east-1"` | no |
33+
| <a name="input_secondary_region"></a> [secondary\_region](#input\_secondary\_region) | n/a | `string` | `"us-west-2"` | no |
34+
35+
## Outputs
36+
37+
| Name | Description |
38+
|------|-------------|
39+
| <a name="output_edit"></a> [edit](#output\_edit) | n/a |
40+
<!-- END_TF_DOCS -->

terraform/services/config/main.tf

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# TODO replace ref with hash after merging
2+
module "platform" {
3+
source = "github.com/CMSgov/cdap//terraform/modules/platform?ref=plt-1358_sops"
4+
providers = { aws = aws, aws.secondary = aws.secondary }
5+
6+
app = "bcda"
7+
env = var.env
8+
root_module = "https://github.com/CMSgov/cdap/tree/terraform/services/config"
9+
service = local.service
10+
}
11+
12+
locals {
13+
default_tags = module.platform.default_tags
14+
env = terraform.workspace
15+
service = "config"
16+
}
17+
18+
module "sops" {
19+
source = "github.com/CMSgov/cdap//terraform/modules/sops?ref=ff2ef539fb06f2c98f0e3ce0c8f922bdacb96d66"
20+
platform = module.platform
21+
}
22+
23+
output "edit" {
24+
value = module.sops.sopsw
25+
}

terraform/services/config/tofu.tf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
provider "aws" {
2+
region = "us-east-1"
3+
default_tags {
4+
tags = local.default_tags
5+
}
6+
}
7+
8+
provider "aws" {
9+
alias = "secondary"
10+
region = "us-west-2"
11+
default_tags {
12+
tags = local.default_tags
13+
}
14+
}
15+
16+
terraform {
17+
backend "s3" {
18+
key = "config/terraform.tfstate"
19+
}
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/cdap/account/nonsensitive/security_events_slack_renotify_after_days: 30
2+
/cdap/account/nonsensitive/security_events_slack_severity_list: CRITICAL,HIGH,MEDIUM
3+
/cdap/sensitive/account/security_events_slack_webhook_url: ENC[AES256_GCM,data:z9MLEAlb76u6MZ+GWcWcfnRtax1J677k47tabDmwCqAGN7H2BrmTnkIs1fAhl9dShaL5qZrq78s0sY9b2hCAGIWWaUenVbGGpWBuZvh7rw==,iv:kbgCH76ryIbnU40SWd/Wgg+hULSgGsTO4LLWIPoDE68=,tag:NmwrTB/oVI0WEhL9R5eV2g==,type:str]
4+
/cdap/sensitive/bucket-access-logs-bucket: ENC[AES256_GCM,data:TjwtktvWlh7Gt7JrTuxZganUT3AotzmEAeYKkpn5GutLcIT1/KSpTV1kjMxV,iv:fSMld0pXjqKabcq+8CK7kG018tspwVAS30ngYFepJKw=,tag:dMsUtxHVSpiHb9U+ebUbNg==,type:str]
5+
/cdap/sensitive/mgmt-vpc/cidr: ENC[AES256_GCM,data:uNKE6Nckt24ZWHDHEWjU,iv:yVvl1HbK7ljy6lgZdGUkfi0CeIHPnd2uof9tVB1z008=,tag:9tQ1atj1Vwkgw6j1FQ8p5w==,type:str]
6+
/cdap/mgmt/public_nat_ipv4/sensitive/cdap-east-mgmt-a: ENC[AES256_GCM,data:FlVrW4HMpGxShfezY7k=,iv:5pZNFGbdfyrGCti7cL/7pfm4S3i5VpnESEO5Rglqw7E=,tag:NZIPNuaSZD/NSD6Q2sE2PQ==,type:str]
7+
/cdap/mgmt/public_nat_ipv4/sensitive/cdap-east-mgmt-b: ENC[AES256_GCM,data:N1zEW1bym0cRrT5b,iv:+i6TbqeQLVdZRGUb/O0FUDSEXHsuxxW8hEJbQJYy8gU=,tag:dypP4NS1W0h0c+SeMmuI+g==,type:str]
8+
/cdap/mgmt/public_nat_ipv4/sensitive/cdap-east-mgmt-c: ENC[AES256_GCM,data:dE2gJAAstO0VcCol,iv:C5g6vtQbu6AQUmtobCrnZmFcBc4Pn6EZmex1YhQqXA8=,tag:gsAznB9ygxhNdpK73HbAwQ==,type:str]
9+
/cdap/sensitive/sonarqube/token: ENC[AES256_GCM,data:IzX5uyi0n7Jas1UuHPP7pdmGpYlWuXdAh5cXOgBAc4D+I8vBQese8RZa8zs=,iv:jnjgYubcGBKeA+S+puNWR5OY+xxisorfNXBm8rLbwFI=,tag:r4JfuxyGxmqmdHB4JRb3cw==,type:str]
10+
/cdap/nonsensitive/sonarqube/url: https://sonarqube.cloud.cms.gov
11+
/cdap/sensitive/artifactory/password: ENC[AES256_GCM,data:Y0pqIlDqheFTaH7RGDS/c8D59emCj969TT2N0GVPcJln3cJF3fkhlvdaDugjwSoaxisLuNXV0nQYs/g80lPHAw==,iv:bur6pAEm5V+M/Jfn1YNXZAYMs60rqGjnkPCMR2Z+Isw=,tag:bwMQmmK7S99EvgdApgTLJQ==,type:str]
12+
/cdap/nonsensitive/artifactory/url: https://artifactory.cloud.cms.gov/artifactory
13+
/cdap/nonsensitive/artifactory/user: ab2d-bcda-dpc-plt
14+
sops:
15+
kms:
16+
- arn: arn:aws:kms:us-east-1:${ACCOUNT_ID}:key/e32dffdb-97e7-4b64-b5cb-f6dc4e6fabca
17+
created_at: "2025-10-03T17:27:53Z"
18+
enc: AQICAHiXhc+HhELIyRKOpc5vBWQJB9/2XFW+CxWFIfUyci0r/wGkXSt3AG0b8bCJ0pVuEmyuAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM+S5DlWnhTDkMvmOxAgEQgDvMXlly/I5Vb2ah1KX2fSbY3mMOxA92rK4MU/rsyUN2oR8WXebzzW+ooNY1pEdGE4FMUmLUrU5qbcUoPg==
19+
aws_profile: ""
20+
unencrypted_regex: /nonsensitive/
21+
mac_only_encrypted: true
22+
version: 3.11.0
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/cdap/nonsensitive/account/security_events_slack_renotify_after_days: 30
2+
/cdap/nonsensitive/account/security_events_slack_severity_list: CRITICAL,HIGH,MEDIUM
3+
/cdap/sensitive/account/security_events_slack_webhook_url: ENC[AES256_GCM,data:aiW0cRzw2ZBM+WmgyXYeEGTIgP3Rm2vL6wa8+mGYyMnMQ718iODap66yNHLkOttq2Lz3V+HDdvjwYXDfG+IBvj9zVpQTjC3EabvByOCIeA==,iv:3GRLuWVe8Z5N3I9JY0DVyrPcwmIv+5vMwIS5ZR4P/v0=,tag:N4Hq6cI/JUUkCzR0BaL/sA==,type:str]
4+
/cdap/sensitive/bucket-access-logs-bucket: ENC[AES256_GCM,data:a9oeAjfhElMm1bceKXkQiZuCnvKGJ4KZdUDHHgbcJhV/KDOJ/Kms+ThAl4s1,iv:86Bff+m1IP0eMbEEzTql64XjeXqkXqEpWXHc9HElkAU=,tag:bAIb8jWb4VQXw603f3zv1g==,type:str]
5+
/cdap/sensitive/mgmt-vpc/cidr: ENC[AES256_GCM,data:EFep+iQ02YJJe22XX4LZ,iv:nOoqFQiizuPIHDzR5xsLDeIDjZvGxmnDaWu8eGzjWrQ=,tag:En0682ms1NNWjCZhnOtrkg==,type:str]
6+
/cdap/sensitive/gmt/public_nat_ipv4/cdap-east-mgmt-a: ENC[AES256_GCM,data:Q//cSfZmUiNc5FqmzII=,iv:BDII9+oRF8tlpoZAGsH6eE0UBigdaZEwDWFs/saYvqQ=,tag:WwfrS9Wn1+aL2xieWP+pXA==,type:str]
7+
/cdap/sensitive/mgmt/public_nat_ipv4/cdap-east-mgmt-b: ENC[AES256_GCM,data:zznp+VJvDrbdMFgz,iv:/gS+Vtt+rBsKbyjLJAyYXeAWkMHAxYClv/kqocwGUfs=,tag:CpOs+maoTJChJW7lz72Slw==,type:str]
8+
/cdap/sensitive/mgmt/public_nat_ipv4/cdap-east-mgmt-c: ENC[AES256_GCM,data:jmZGAzdcyIwPdq69,iv:jlAyPtL700BnqiWtsqQSrmZmt2TXtSzJUM2cR07bRrc=,tag:Zul0kmzRQZNMkbsLwmiUIA==,type:str]
9+
/cdap/sensitive/sonarqube/token: ENC[AES256_GCM,data:G8DmkxGggaryrx9+eIGmOtgM2DW931q3k9X/Cjy58Q2ZQ/Tp/bgx4yoJ7Do=,iv:IgsPiB8Fjbw984dB6tgjJa2nQrGl6Ko9TiNWNI+VIUE=,tag:SP61z5HnoDjbe3HVkLfJiQ==,type:str]
10+
/cdap/nonsensitive/sonarqube/url: https://sonarqube.cloud.cms.gov
11+
/cdap/sensitive/artifactory/password: ENC[AES256_GCM,data:YHIx5dSONjUgnO/rAP7JsvIR0PElCzLiARuABts0zcAUTYXC4hl4M+MGabhEzrUAqtRfD3wvIw2RiXmFrKqRNQ==,iv:UCrI+tMCwoYtf1gWAlr1/7PWHzj/Tqvc5lajjbCxAd0=,tag:02HC5T7mi2mZi0euLEwELA==,type:str]
12+
/cdap/nonsensitive/artifactory/url: https://artifactory.cloud.cms.gov/artifactory
13+
/cdap/nonsensitive/artifactory/user: ab2d-bcda-dpc-plt
14+
sops:
15+
kms:
16+
- arn: arn:aws:kms:us-east-1:539247469933:alias/bcda-test
17+
created_at: "2025-11-17T21:10:18Z"
18+
enc: AQICAHjmpdIoLQvhLo0ak4uYFiScF9EZlYU3g9HHyCuiUTXbOwHLNWrV6czniW+ynxVXARD/AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMl7Aj8t3HMIwdjbVFAgEQgDsvvnioXJMRDPB5vydrZbzQKqEpISs9UOYX4OUGEfNHl7dGxI/3BA6yoZPn/GU7zl3RDZfxs9QQdZaIcg==
19+
aws_profile: ""
20+
lastmodified: "2025-11-17T21:19:40Z"
21+
mac: ENC[AES256_GCM,data:bssj91Ngo0DYAM6FItDqsWez3ycy4efnMAQ+D/nRyYsQ35LC5J+Ra0iE0GwqJjInt3iggKvNWGX8JPa4Xo0vDI9TCS+rBVT0keB0af0k6eApLPGavDC1LW0VWfZjBuIvx881HmGgAO10SrIGlBJV9Vv7y4injBJVvIB68PSO4aQ=,iv:EnEYf8SGUVQdQDNXNV++d+tcqaZsP0eW4Zb1/8xNgfs=,tag:Gn3IYLAGqQxHk9H8P/MjSg==,type:str]
22+
unencrypted_regex: /nonsensitive/
23+
version: 3.11.0
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
variable "env" {
2+
description = "The application environment (test, prod)"
3+
type = string
4+
validation {
5+
condition = contains(["test", "prod"], var.env)
6+
error_message = "Valid value for env is test or prod."
7+
}
8+
}

0 commit comments

Comments
 (0)