You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tags as primitive, alert enrichment, budget enforcement, RDS module (#77)
## Summary
Foundation changes to make tags a first-class primitive for ABAC, cost
attribution, and auditability. Plus alert enrichment, budget
enforcement, and RDS support.
### Tags as primitive
- **Tag schema**: 5 static tags (team, service, repo, environment,
managed-by) via provider `default_tags`. Dropped `project` tag (always
"javabin", zero information).
- **Resource tagger Lambda**: EventBridge-triggered (wildcard
`{"prefix": "aws."}` match), auto-tags `created-by` + `commit` from
CloudTrail session names. Tags added via AWS API — invisible to
Terraform, no drift.
- **Cost allocation tags**: Activated for all 7 tag keys so Cost
Explorer can group by team/service.
- **ECS tag propagation**: `propagate_tags = SERVICE` so Fargate task
costs are attributed to teams.
### Alert enrichment (Task A)
- CI session names changed to `{actor}-{sha8}-{run_id}` in all 4
workflows.
- `slack_alert` `parse_identity()` extracts actor/commit from new
format.
- Cost reports (daily + weekly) include per-team tag breakdown.
### Budget enforcement (Task D)
- New `budget-enforcer` Lambda: scales ECS services to `desired_count=0`
at 200% budget.
- `team_provisioner` adds 200% notification alongside existing 80%.
### RDS module (Task E)
- New `service-rds` module: PostgreSQL with Secrets Manager password,
private subnets, ECS SG ingress.
- `registry.py` + `expand-modules.py` updated with engine-based routing
(`postgres` vs `dynamodb`).
### IAM restructure
- Team deny policy: ABAC (ARN-scoped) where AWS supports tags (SNS, S3,
ECS, ELB). Explicit denies only where AWS lacks tag conditions (EC2 VPC,
GuardDuty, SecurityHub, Config, CloudTrail, Organizations, IAM).
- `service-role` module: configurable `trusted_services`
(ECS/EC2/Lambda).
- EventBridge resource-tagger uses wildcard; monitoring rules keep
curated lists (documented volume rationale).
## Test plan
- [ ] `terraform plan` shows tag migration (project removed,
service+repo added) on existing resources
- [ ] After apply: resources show 5 Terraform-managed tags in console
- [ ] Trigger CI run → Slack alert shows actor name + commit link
- [ ] Next day: Cost Explorer GroupBy `team` returns per-team costs
- [ ] Create test resource → resource-tagger tags it within 15 min
- [ ] Invoke budget-enforcer with test payload → ECS service scales to 0
- [ ] Test app with `engine: postgres` in app.yaml → RDS created in
private subnet
DynamoDB and PostgreSQL entries can coexist in the same `databases` list. Entries without `engine` (or with `engine: dynamodb`) use the DynamoDB module. Entries with `engine: postgres` or `engine: postgresql` use the RDS module.
141
+
142
+
RDS instances use `manage_master_user_password = true`, which stores the auto-generated master password in Secrets Manager. The ECS task role automatically receives IAM policies for `rds-db:connect` and `secretsmanager:GetSecretValue` on the password secret.
143
+
130
144
#### secrets
131
145
132
146
Secrets Manager secrets. Value is set manually after creation.
@@ -354,6 +368,7 @@ Generated files have a `# GENERATED FROM app.yaml` marker. The script only overw
**Purpose:** Syncs team definitions from registry YAML across Google Groups, GitHub teams, AWS Budgets (80% warning + 200% enforcement thresholds), Cognito groups, and Identity Center groups. Also handles hero account provisioning.
75
75
76
-
**Status:** Stub only — logs event and returns success. Blocked on Google Admin access.
76
+
| SSM Parameter | Purpose |
77
+
|---------------|---------|
78
+
|`/javabin/platform/google-admin-sa`| GCP service account JSON key (domain-wide delegation) |
79
+
|`/javabin/platform/google-admin-email`| Admin email for Google Admin SDK impersonation |
80
+
|`/javabin/platform/github-app-id`| GitHub App ID for team management |
**Trigger:** SNS notification from AWS Budgets (200% threshold)
87
+
**Purpose:** Scales a team's ECS services to `desired_count=0` when spending exceeds 200% of their monthly budget. Does NOT destroy resources — services can be scaled back up after resolution.
88
+
89
+
**Flow:** Parse budget name (`javabin-team-{team}`) → list ECS services tagged with team → scale to zero → post Slack alert.
**Trigger:** EventBridge rule matching all AWS service creation events (`{"prefix": "aws."}` source, `Create*`/`Run*` event names)
100
+
**Purpose:** Auto-tags newly created AWS resources with `created-by` (actor) and `commit` (SHA) parsed from the CloudTrail session name. Tags are set via AWS Resource Groups Tagging API, outside Terraform management — no drift or plan noise.
101
+
102
+
**Session name format:**`{actor}-{sha8}-{run_id}` (enriched in CI workflows)
103
+
104
+
Idempotent: skips resources that already have a `created-by` tag (preserves original creator).
Copy file name to clipboardExpand all lines: docs/reusable-modules.md
+39Lines changed: 39 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -53,6 +53,8 @@ additional_policy_jsons = {
53
53
}
54
54
```
55
55
56
+
**`trusted_services`** — controls which AWS service can assume the role. Default: `["ecs-tasks.amazonaws.com"]`. Can be set to `["ec2.amazonaws.com"]` or `["lambda.amazonaws.com"]` via `compute.trusted_service` in app.yaml. Enables cross-compute roles so EC2 instances and Lambda functions get the same auto-wired access policies.
Supports `environment` (map) and `secrets` (map of name => ARN) for container configuration.
63
65
66
+
**Tag propagation:**`enable_ecs_managed_tags = true` and `propagate_tags = "SERVICE"` ensure Fargate task-level compute costs are attributed to the team via Cost Explorer.
**Auto-wiring:**`access_policy_json` grants `rds-db:connect` + `secretsmanager:GetSecretValue`. Auto-attached to task role via `collect:access_policy_json`.
122
+
123
+
**app.yaml:**
124
+
```yaml
125
+
databases:
126
+
- name: main
127
+
engine: postgres
128
+
instance_class: db.t3.micro
129
+
allocated_storage: 20
130
+
engine_version: "16"
131
+
```
132
+
94
133
## service-alarm
95
134
96
135
CloudWatch alarms for ECS services: CPU high, memory high, unhealthy targets, 5xx errors.
0 commit comments