Skip to content

Commit 0d9c7e2

Browse files
isadeksbgagent
andauthored
fix(cdk): allow-list JiraIntegration* secret in bootstrap policy (#402) (#403)
The custom least-privilege CFN execution-role policy (ADR-002) scopes secretsmanager:CreateSecret to per-integration ARN prefixes, but the Jira integration shipped without its pattern. A fresh `mise //cdk:bootstrap` + deploy of current main therefore rolls back with: cdk-hnb659fds-cfn-exec-role is not authorized to perform secretsmanager:CreateSecret (on JiraIntegrationWebhookSecre-...) jira-integration.ts creates `new secretsmanager.Secret(this, 'WebhookSecret')` under construct id `JiraIntegration`, which CloudFormation names `JiraIntegrationWebhookSecre-...`, matching no allow-listed prefix. Add `arn:aws:secretsmanager:*:*:secret:JiraIntegration*` to the SecretsManager statement and regenerate the bootstrap artifacts (application.json, bootstrap-template.yaml). Add the same pattern to the DEPLOYMENT_ROLES.md golden source-of-truth (+ Starlight mirror) so the golden-baseline parity test passes. Add a regression guard in policies.test.ts asserting the allow-list carries a pattern for every integration that creates a secret — the existing service-prefix check can't catch a missing resource ARN (it's still `secretsmanager:`), which is how this reached main. Fixes #402 Co-authored-by: bgagent <bgagent@noreply.github.com>
1 parent a55495d commit 0d9c7e2

6 files changed

Lines changed: 37 additions & 0 deletions

File tree

cdk/bootstrap/bootstrap-template.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,7 @@ Resources:
11291129
- arn:aws:secretsmanager:*:*:secret:GitHubTokenSecret*
11301130
- arn:aws:secretsmanager:*:*:secret:SlackIntegration*
11311131
- arn:aws:secretsmanager:*:*:secret:LinearIntegration*
1132+
- arn:aws:secretsmanager:*:*:secret:JiraIntegration*
11321133
- arn:aws:secretsmanager:*:*:secret:GitHubScreenshot*
11331134
- arn:aws:secretsmanager:*:*:secret:bgagent/*
11341135
Sid: SecretsManager

cdk/bootstrap/policies/application.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"arn:aws:secretsmanager:*:*:secret:GitHubTokenSecret*",
206206
"arn:aws:secretsmanager:*:*:secret:SlackIntegration*",
207207
"arn:aws:secretsmanager:*:*:secret:LinearIntegration*",
208+
"arn:aws:secretsmanager:*:*:secret:JiraIntegration*",
208209
"arn:aws:secretsmanager:*:*:secret:GitHubScreenshot*",
209210
"arn:aws:secretsmanager:*:*:secret:bgagent/*"
210211
],

cdk/src/bootstrap/policies/application.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ export function applicationPolicy(): iam.PolicyDocument {
246246
'arn:aws:secretsmanager:*:*:secret:GitHubTokenSecret*',
247247
'arn:aws:secretsmanager:*:*:secret:SlackIntegration*',
248248
'arn:aws:secretsmanager:*:*:secret:LinearIntegration*',
249+
'arn:aws:secretsmanager:*:*:secret:JiraIntegration*',
249250
'arn:aws:secretsmanager:*:*:secret:GitHubScreenshot*',
250251
'arn:aws:secretsmanager:*:*:secret:bgagent/*',
251252
],

cdk/test/bootstrap/policies.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,38 @@ describe('IaCRole-ABCA-Application', () => {
148148
]),
149149
);
150150
});
151+
152+
it('SecretsManager statement allow-lists a secret pattern for every integration that creates a secret', () => {
153+
// Regression guard for #402: each integration construct that creates a
154+
// Secrets Manager secret (GitHub token, Slack, Linear, Jira, GitHub
155+
// screenshot) names it after its construct id, so the CFN exec role's
156+
// scoped CreateSecret allow-list must carry a matching prefix. A missing
157+
// pattern is invisible to the service-prefix check above (it's still
158+
// `secretsmanager:`) but fails the deploy with AccessDenied at
159+
// CreateSecret time. Jira shipped without its pattern; this locks the
160+
// contract so the next integration can't repeat it.
161+
const resolvedDoc = stack.resolve(doc);
162+
const statements = resolvedDoc.Statement as Array<{
163+
Sid: string;
164+
Resource?: string | string[];
165+
}>;
166+
const secretsStatement = statements.find((s) => s.Sid === 'SecretsManager');
167+
expect(secretsStatement).toBeDefined();
168+
169+
const resources = Array.isArray(secretsStatement!.Resource)
170+
? secretsStatement!.Resource
171+
: [secretsStatement!.Resource];
172+
173+
for (const prefix of [
174+
'GitHubTokenSecret',
175+
'SlackIntegration',
176+
'LinearIntegration',
177+
'JiraIntegration',
178+
'GitHubScreenshot',
179+
]) {
180+
expect(resources).toContain(`arn:aws:secretsmanager:*:*:secret:${prefix}*`);
181+
}
182+
});
151183
});
152184

153185
describe('IaCRole-ABCA-Observability', () => {

docs/design/DEPLOYMENT_ROLES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ DynamoDB tables, Lambda functions, API Gateway, Cognito, WAFv2, EventBridge, SQS
473473
"arn:aws:secretsmanager:*:*:secret:GitHubTokenSecret*",
474474
"arn:aws:secretsmanager:*:*:secret:SlackIntegration*",
475475
"arn:aws:secretsmanager:*:*:secret:LinearIntegration*",
476+
"arn:aws:secretsmanager:*:*:secret:JiraIntegration*",
476477
"arn:aws:secretsmanager:*:*:secret:GitHubScreenshot*",
477478
"arn:aws:secretsmanager:*:*:secret:bgagent/*"
478479
]

docs/src/content/docs/architecture/Deployment-roles.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ DynamoDB tables, Lambda functions, API Gateway, Cognito, WAFv2, EventBridge, SQS
477477
"arn:aws:secretsmanager:*:*:secret:GitHubTokenSecret*",
478478
"arn:aws:secretsmanager:*:*:secret:SlackIntegration*",
479479
"arn:aws:secretsmanager:*:*:secret:LinearIntegration*",
480+
"arn:aws:secretsmanager:*:*:secret:JiraIntegration*",
480481
"arn:aws:secretsmanager:*:*:secret:GitHubScreenshot*",
481482
"arn:aws:secretsmanager:*:*:secret:bgagent/*"
482483
]

0 commit comments

Comments
 (0)