@prism-d1/cli 1.1.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/github-workflows/prism-agent-eval.yml +2 -1
- package/dist/assets/github-workflows/prism-eval-gate-kiro.yml +12 -2
- package/dist/assets/gitlab-workflows/prism-eval-gate.yml +8 -0
- package/dist/assets/infra/bin/app.ts +61 -37
- package/dist/assets/infra/lib/constructs/otel-collector-construct.ts +96 -0
- package/dist/assets/infra/lib/constructs/security-agent-construct.ts +35 -30
- package/dist/assets/infra/lib/dashboard-stack.ts +27 -0
- package/dist/assets/infra/lib/lambda/otel-receiver.ts +278 -8
- package/dist/assets/infra/lib/lambda/pricing/litellm-snapshot.json +3769 -0
- package/dist/assets/infra/lib/lambda/pricing/price-source.ts +56 -0
- package/dist/assets/infra/lib/lambda/pricing/price-table.ts +240 -0
- package/dist/assets/infra/lib/lambda/pricing/prices-key.ts +6 -0
- package/dist/assets/infra/lib/lambda/pricing/reprice.ts +108 -0
- package/dist/assets/infra/lib/lambda/pricing-refresh.ts +352 -0
- package/dist/assets/infra/lib/lambda/velocity-widget.ts +124 -1
- package/dist/assets/infra/lib/metrics-pipeline-stack.ts +2 -110
- package/dist/assets/infra/lib/security-agent-resources.ts +136 -0
- package/dist/assets/infra/lib/security-agent-stack.ts +69 -0
- package/dist/assets/infra/package.json +4 -1
- package/dist/assets/metric-hooks/prepare-commit-msg +3 -1
- package/dist/assets/pentest-cdk/bin/app.ts +12 -0
- package/dist/assets/pentest-cdk/cdk.json +7 -0
- package/dist/assets/pentest-cdk/lib/pentest-target-stack.ts +206 -0
- package/dist/assets/pentest-cdk/package.json +18 -0
- package/dist/assets/pentest-cdk/tsconfig.json +12 -0
- package/dist/src/codewatch/config.d.ts +17 -0
- package/dist/src/codewatch/config.d.ts.map +1 -0
- package/dist/src/codewatch/config.js +40 -0
- package/dist/src/codewatch/config.js.map +1 -0
- package/dist/src/codewatch/gitleaks.d.ts +49 -0
- package/dist/src/codewatch/gitleaks.d.ts.map +1 -0
- package/dist/src/codewatch/gitleaks.js +160 -0
- package/dist/src/codewatch/gitleaks.js.map +1 -0
- package/dist/src/codewatch/globalHooks.d.ts +52 -0
- package/dist/src/codewatch/globalHooks.d.ts.map +1 -0
- package/dist/src/codewatch/globalHooks.js +235 -0
- package/dist/src/codewatch/globalHooks.js.map +1 -0
- package/dist/src/codewatch/hooks.d.ts +38 -0
- package/dist/src/codewatch/hooks.d.ts.map +1 -0
- package/dist/src/codewatch/hooks.js +176 -0
- package/dist/src/codewatch/hooks.js.map +1 -0
- package/dist/src/codewatch/prepush.d.ts +37 -0
- package/dist/src/codewatch/prepush.d.ts.map +1 -0
- package/dist/src/codewatch/prepush.js +231 -0
- package/dist/src/codewatch/prepush.js.map +1 -0
- package/dist/src/codewatch/results.d.ts +210 -0
- package/dist/src/codewatch/results.d.ts.map +1 -0
- package/dist/src/codewatch/results.js +127 -0
- package/dist/src/codewatch/results.js.map +1 -0
- package/dist/src/codewatch/reviewers/claude.d.ts +9 -0
- package/dist/src/codewatch/reviewers/claude.d.ts.map +1 -0
- package/dist/src/codewatch/reviewers/claude.js +48 -0
- package/dist/src/codewatch/reviewers/claude.js.map +1 -0
- package/dist/src/codewatch/reviewers/index.d.ts +39 -0
- package/dist/src/codewatch/reviewers/index.d.ts.map +1 -0
- package/dist/src/codewatch/reviewers/index.js +97 -0
- package/dist/src/codewatch/reviewers/index.js.map +1 -0
- package/dist/src/codewatch/reviewers/kiro.d.ts +14 -0
- package/dist/src/codewatch/reviewers/kiro.d.ts.map +1 -0
- package/dist/src/codewatch/reviewers/kiro.js +32 -0
- package/dist/src/codewatch/reviewers/kiro.js.map +1 -0
- package/dist/src/codewatch/reviewers/types.d.ts +56 -0
- package/dist/src/codewatch/reviewers/types.d.ts.map +1 -0
- package/dist/src/codewatch/reviewers/types.js +91 -0
- package/dist/src/codewatch/reviewers/types.js.map +1 -0
- package/dist/src/codewatch/rules.d.ts +12 -0
- package/dist/src/codewatch/rules.d.ts.map +1 -0
- package/dist/src/codewatch/rules.js +27 -0
- package/dist/src/codewatch/rules.js.map +1 -0
- package/dist/src/commands/_top/dashboard.d.ts +17 -0
- package/dist/src/commands/_top/dashboard.d.ts.map +1 -0
- package/dist/src/commands/_top/dashboard.js +76 -0
- package/dist/src/commands/_top/dashboard.js.map +1 -0
- package/dist/src/commands/_top/version.d.ts +62 -0
- package/dist/src/commands/_top/version.d.ts.map +1 -0
- package/dist/src/commands/_top/version.js +175 -0
- package/dist/src/commands/_top/version.js.map +1 -0
- package/dist/src/commands/bedrock-protection/scan-account.d.ts.map +1 -1
- package/dist/src/commands/bedrock-protection/scan-account.js +2 -1
- package/dist/src/commands/bedrock-protection/scan-account.js.map +1 -1
- package/dist/src/commands/bedrock-protection/scan-org.d.ts.map +1 -1
- package/dist/src/commands/bedrock-protection/scan-org.js +16 -4
- package/dist/src/commands/bedrock-protection/scan-org.js.map +1 -1
- package/dist/src/commands/bootstrapper/install-eval-harness.d.ts.map +1 -1
- package/dist/src/commands/bootstrapper/install-eval-harness.js +15 -48
- package/dist/src/commands/bootstrapper/install-eval-harness.js.map +1 -1
- package/dist/src/commands/bootstrapper/install-git-hooks.d.ts +13 -0
- package/dist/src/commands/bootstrapper/install-git-hooks.d.ts.map +1 -1
- package/dist/src/commands/bootstrapper/install-git-hooks.js +28 -147
- package/dist/src/commands/bootstrapper/install-git-hooks.js.map +1 -1
- package/dist/src/commands/bootstrapper/setup-otel-sync.d.ts +12 -6
- package/dist/src/commands/bootstrapper/setup-otel-sync.d.ts.map +1 -1
- package/dist/src/commands/bootstrapper/setup-otel-sync.js +18 -443
- package/dist/src/commands/bootstrapper/setup-otel-sync.js.map +1 -1
- package/dist/src/commands/codewatch/pre-commit.d.ts +7 -0
- package/dist/src/commands/codewatch/pre-commit.d.ts.map +1 -0
- package/dist/src/commands/codewatch/pre-commit.js +30 -0
- package/dist/src/commands/codewatch/pre-commit.js.map +1 -0
- package/dist/src/commands/codewatch/pre-push.d.ts +16 -0
- package/dist/src/commands/codewatch/pre-push.d.ts.map +1 -0
- package/dist/src/commands/codewatch/pre-push.js +32 -0
- package/dist/src/commands/codewatch/pre-push.js.map +1 -0
- package/dist/src/commands/codewatch/report.d.ts +22 -0
- package/dist/src/commands/codewatch/report.d.ts.map +1 -0
- package/dist/src/commands/codewatch/report.js +64 -0
- package/dist/src/commands/codewatch/report.js.map +1 -0
- package/dist/src/commands/enable/codeburn.d.ts +59 -0
- package/dist/src/commands/enable/codeburn.d.ts.map +1 -0
- package/dist/src/commands/enable/codeburn.js +531 -0
- package/dist/src/commands/enable/codeburn.js.map +1 -0
- package/dist/src/commands/enable/codewatch.d.ts +15 -0
- package/dist/src/commands/enable/codewatch.d.ts.map +1 -0
- package/dist/src/commands/enable/codewatch.js +186 -0
- package/dist/src/commands/enable/codewatch.js.map +1 -0
- package/dist/src/commands/enable/security.d.ts +41 -0
- package/dist/src/commands/enable/security.d.ts.map +1 -0
- package/dist/src/commands/enable/security.js +130 -0
- package/dist/src/commands/enable/security.js.map +1 -0
- package/dist/src/commands/export/otel.d.ts +31 -0
- package/dist/src/commands/export/otel.d.ts.map +1 -0
- package/dist/src/commands/export/otel.js +52 -0
- package/dist/src/commands/export/otel.js.map +1 -0
- package/dist/src/commands/git/claude-session-context.d.ts.map +1 -1
- package/dist/src/commands/git/claude-session-context.js +2 -1
- package/dist/src/commands/git/claude-session-context.js.map +1 -1
- package/dist/src/commands/git/commit-trailers.js +1 -1
- package/dist/src/commands/git/commit-trailers.js.map +1 -1
- package/dist/src/commands/security/code-review.d.ts +22 -0
- package/dist/src/commands/security/code-review.d.ts.map +1 -0
- package/dist/src/commands/security/code-review.js +43 -0
- package/dist/src/commands/security/code-review.js.map +1 -0
- package/dist/src/commands/security/findings.d.ts +15 -0
- package/dist/src/commands/security/findings.d.ts.map +1 -0
- package/dist/src/commands/security/findings.js +31 -0
- package/dist/src/commands/security/findings.js.map +1 -0
- package/dist/src/commands/security/pentest.d.ts +18 -0
- package/dist/src/commands/security/pentest.d.ts.map +1 -0
- package/dist/src/commands/security/pentest.js +32 -0
- package/dist/src/commands/security/pentest.js.map +1 -0
- package/dist/src/commands/security/threat-model.d.ts +16 -0
- package/dist/src/commands/security/threat-model.d.ts.map +1 -0
- package/dist/src/commands/security/threat-model.js +24 -0
- package/dist/src/commands/security/threat-model.js.map +1 -0
- package/dist/src/commands/security/threats.d.ts +12 -0
- package/dist/src/commands/security/threats.d.ts.map +1 -0
- package/dist/src/commands/security/threats.js +23 -0
- package/dist/src/commands/security/threats.js.map +1 -0
- package/dist/src/commands/securityagent/setup.d.ts +19 -5
- package/dist/src/commands/securityagent/setup.d.ts.map +1 -1
- package/dist/src/commands/securityagent/setup.js +25 -189
- package/dist/src/commands/securityagent/setup.js.map +1 -1
- package/dist/src/commands/workshop/verify-setup.d.ts.map +1 -1
- package/dist/src/commands/workshop/verify-setup.js +5 -3
- package/dist/src/commands/workshop/verify-setup.js.map +1 -1
- package/dist/src/dashboard/codewatch.d.ts +106 -0
- package/dist/src/dashboard/codewatch.d.ts.map +1 -0
- package/dist/src/dashboard/codewatch.js +120 -0
- package/dist/src/dashboard/codewatch.js.map +1 -0
- package/dist/src/dashboard/commits.d.ts +96 -0
- package/dist/src/dashboard/commits.d.ts.map +1 -0
- package/dist/src/dashboard/commits.js +207 -0
- package/dist/src/dashboard/commits.js.map +1 -0
- package/dist/src/dashboard/page.d.ts +10 -0
- package/dist/src/dashboard/page.d.ts.map +1 -0
- package/dist/src/dashboard/page.js +470 -0
- package/dist/src/dashboard/page.js.map +1 -0
- package/dist/src/dashboard/payload.d.ts +114 -0
- package/dist/src/dashboard/payload.d.ts.map +1 -0
- package/dist/src/dashboard/payload.js +96 -0
- package/dist/src/dashboard/payload.js.map +1 -0
- package/dist/src/dashboard/report.d.ts +99 -0
- package/dist/src/dashboard/report.d.ts.map +1 -0
- package/dist/src/dashboard/report.js +300 -0
- package/dist/src/dashboard/report.js.map +1 -0
- package/dist/src/dashboard/repos.d.ts +58 -0
- package/dist/src/dashboard/repos.d.ts.map +1 -0
- package/dist/src/dashboard/repos.js +111 -0
- package/dist/src/dashboard/repos.js.map +1 -0
- package/dist/src/dashboard/security.d.ts +130 -0
- package/dist/src/dashboard/security.d.ts.map +1 -0
- package/dist/src/dashboard/security.js +144 -0
- package/dist/src/dashboard/security.js.map +1 -0
- package/dist/src/dashboard/server.d.ts +52 -0
- package/dist/src/dashboard/server.d.ts.map +1 -0
- package/dist/src/dashboard/server.js +163 -0
- package/dist/src/dashboard/server.js.map +1 -0
- package/dist/src/dashboard/setup.d.ts +67 -0
- package/dist/src/dashboard/setup.d.ts.map +1 -0
- package/dist/src/dashboard/setup.js +146 -0
- package/dist/src/dashboard/setup.js.map +1 -0
- package/dist/src/dashboard/usage.d.ts +43 -0
- package/dist/src/dashboard/usage.d.ts.map +1 -0
- package/dist/src/dashboard/usage.js +88 -0
- package/dist/src/dashboard/usage.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +48 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/security/cfn-diff.d.ts +57 -0
- package/dist/src/security/cfn-diff.d.ts.map +1 -0
- package/dist/src/security/cfn-diff.js +112 -0
- package/dist/src/security/cfn-diff.js.map +1 -0
- package/dist/src/security/errors.d.ts +45 -0
- package/dist/src/security/errors.d.ts.map +1 -0
- package/dist/src/security/errors.js +116 -0
- package/dist/src/security/errors.js.map +1 -0
- package/dist/src/security/marker.d.ts +46 -0
- package/dist/src/security/marker.d.ts.map +1 -0
- package/dist/src/security/marker.js +120 -0
- package/dist/src/security/marker.js.map +1 -0
- package/dist/src/security/pentest-dockerfile.d.ts +8 -0
- package/dist/src/security/pentest-dockerfile.d.ts.map +1 -0
- package/dist/src/security/pentest-dockerfile.js +163 -0
- package/dist/src/security/pentest-dockerfile.js.map +1 -0
- package/dist/src/security/pentest.d.ts +233 -0
- package/dist/src/security/pentest.d.ts.map +1 -0
- package/dist/src/security/pentest.js +1057 -0
- package/dist/src/security/pentest.js.map +1 -0
- package/dist/src/security/repo.d.ts +25 -0
- package/dist/src/security/repo.d.ts.map +1 -0
- package/dist/src/security/repo.js +38 -0
- package/dist/src/security/repo.js.map +1 -0
- package/dist/src/security/review.d.ts +202 -0
- package/dist/src/security/review.d.ts.map +1 -0
- package/dist/src/security/review.js +706 -0
- package/dist/src/security/review.js.map +1 -0
- package/dist/src/security/setup.d.ts +193 -0
- package/dist/src/security/setup.d.ts.map +1 -0
- package/dist/src/security/setup.js +728 -0
- package/dist/src/security/setup.js.map +1 -0
- package/dist/src/security/threat-model.d.ts +133 -0
- package/dist/src/security/threat-model.d.ts.map +1 -0
- package/dist/src/security/threat-model.js +653 -0
- package/dist/src/security/threat-model.js.map +1 -0
- package/dist/src/utils/audit-bedrock.d.ts +1 -0
- package/dist/src/utils/audit-bedrock.d.ts.map +1 -1
- package/dist/src/utils/audit-bedrock.js +133 -0
- package/dist/src/utils/audit-bedrock.js.map +1 -1
- package/dist/src/utils/audit-org.d.ts +1 -0
- package/dist/src/utils/audit-org.d.ts.map +1 -1
- package/dist/src/utils/audit-org.js +155 -0
- package/dist/src/utils/audit-org.js.map +1 -1
- package/dist/src/utils/exec.d.ts +6 -0
- package/dist/src/utils/exec.d.ts.map +1 -1
- package/dist/src/utils/exec.js +12 -1
- package/dist/src/utils/exec.js.map +1 -1
- package/dist/src/utils/otel-sync-schedule.d.ts +41 -0
- package/dist/src/utils/otel-sync-schedule.d.ts.map +1 -0
- package/dist/src/utils/otel-sync-schedule.js +90 -0
- package/dist/src/utils/otel-sync-schedule.js.map +1 -0
- package/dist/src/utils/tool-check.d.ts +14 -0
- package/dist/src/utils/tool-check.d.ts.map +1 -0
- package/dist/src/utils/tool-check.js +42 -0
- package/dist/src/utils/tool-check.js.map +1 -0
- package/package.json +3 -2
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
# - OIDC provider configured for GitHub Actions in your AWS account
|
|
7
7
|
# - IAM role with bedrock:InvokeModel and events:PutEvents permissions
|
|
8
8
|
# - Repository secret PRISM_METRICS_ROLE_ARN set to the OIDC role ARN
|
|
9
|
-
# - .prism/config.json committed to the repo
|
|
9
|
+
# - .prism/config.json committed to the repo with a "team_id" key; add it by hand, e.g.
|
|
10
|
+
# {"team_id": "team-payments"} (prism-cli enable codewatch keeps existing keys in this file)
|
|
10
11
|
# - .prism/eval-harness/ installed (run: bash prism-cli bootstrapper install-eval-harness)
|
|
11
12
|
# - (Optional) Agent entry point supports --mock flag for dry-run execution
|
|
12
13
|
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
#
|
|
5
5
|
# Required setup:
|
|
6
6
|
# - Kiro API key stored as repository secret: KIRO_API_KEY
|
|
7
|
-
# - .
|
|
7
|
+
# - .prism/review/rules.md (shared with the local pre-push review) or
|
|
8
|
+
# .kiro/steering/code-review.md in your repo (review rules)
|
|
8
9
|
# - (Optional) PRISM_METRICS_ROLE_ARN for EventBridge metrics emission
|
|
9
10
|
# - (Optional) AWS Continuum configured for security scanning
|
|
10
11
|
#
|
|
@@ -236,6 +237,15 @@ jobs:
|
|
|
236
237
|
exit 0
|
|
237
238
|
fi
|
|
238
239
|
|
|
240
|
+
# Shared rule set: .prism/review/rules.md is the one source for this
|
|
241
|
+
# gate and the local pre-push review (prism-cli enable codewatch).
|
|
242
|
+
# kiro-cli loads rules from .kiro/steering/, so sync it in for this run.
|
|
243
|
+
if [ -f .prism/review/rules.md ]; then
|
|
244
|
+
mkdir -p .kiro/steering
|
|
245
|
+
cp .prism/review/rules.md .kiro/steering/code-review.md
|
|
246
|
+
echo "Review rules: .prism/review/rules.md"
|
|
247
|
+
fi
|
|
248
|
+
|
|
239
249
|
# Get all changed source files in this PR
|
|
240
250
|
FILES=$(git diff --name-only "${BASE_SHA}..${HEAD_SHA}" \
|
|
241
251
|
| grep -E '\.(ts|js|py|go|java|rs|tsx|jsx)$' \
|
|
@@ -638,7 +648,7 @@ jobs:
|
|
|
638
648
|
|
|
639
649
|
if [ -z "$CODE_REVIEW_ID" ]; then
|
|
640
650
|
echo "::error::Could not create the Continuum Code Review resource: ${CR_OUTPUT}"
|
|
641
|
-
echo " Run 'prism-cli
|
|
651
|
+
echo " Run 'prism-cli enable security' to create it manually."
|
|
642
652
|
echo "scan_error=true" >> "$GITHUB_OUTPUT"
|
|
643
653
|
echo "findings=-1" >> "$GITHUB_OUTPUT"
|
|
644
654
|
exit 0
|
|
@@ -186,6 +186,14 @@ prism-eval-gate:
|
|
|
186
186
|
elif [ -z "${BASE_SHA}" ] || [ -z "${HEAD_SHA}" ]; then
|
|
187
187
|
echo "⚠️ Missing base/head SHA — review skipped."
|
|
188
188
|
else
|
|
189
|
+
# Shared rule set (also used by the local pre-push review). kiro-cli
|
|
190
|
+
# loads rules from .kiro/steering/, so sync it in for this run.
|
|
191
|
+
if [ -f .prism/review/rules.md ]; then
|
|
192
|
+
mkdir -p .kiro/steering
|
|
193
|
+
cp .prism/review/rules.md .kiro/steering/code-review.md
|
|
194
|
+
echo "Review rules: .prism/review/rules.md"
|
|
195
|
+
fi
|
|
196
|
+
|
|
189
197
|
FILES=$(git diff --name-only "${BASE_SHA}..${HEAD_SHA}" \
|
|
190
198
|
| grep -E '\.(ts|js|py|go|java|rs|tsx|jsx)$' \
|
|
191
199
|
| grep -vE '\.test\.|\.spec\.|__test__|_test\.' \
|
|
@@ -6,6 +6,7 @@ import { AwsSolutionsChecks } from 'cdk-nag';
|
|
|
6
6
|
import { MetricsPipelineStack } from '../lib/metrics-pipeline-stack';
|
|
7
7
|
import { ApiStack } from '../lib/api-stack';
|
|
8
8
|
import { DashboardStack } from '../lib/dashboard-stack';
|
|
9
|
+
import { SecurityAgentStack } from '../lib/security-agent-stack';
|
|
9
10
|
|
|
10
11
|
const app = new cdk.App();
|
|
11
12
|
|
|
@@ -14,43 +15,66 @@ const env: cdk.Environment = {
|
|
|
14
15
|
region: process.env.CDK_DEFAULT_REGION ?? 'us-west-2',
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
18
|
+
// securityAgentStandalone=true builds ONLY PrismD1SecurityAgent: AWS Security
|
|
19
|
+
// Agent without the metrics pipeline (what `prism-cli enable security` deploys
|
|
20
|
+
// in an account that does not host it in the pipeline). It and
|
|
21
|
+
// enableSecurityAgent=true (Security Agent inside PrismD1MetricsPipeline) use
|
|
22
|
+
// the same resource and export names, so one account can only have one.
|
|
23
|
+
const standalone = app.node.tryGetContext('securityAgentStandalone') === 'true';
|
|
24
|
+
if (standalone && app.node.tryGetContext('enableSecurityAgent') === 'true') {
|
|
25
|
+
throw new Error('securityAgentStandalone=true and enableSecurityAgent=true are exclusive: Security Agent lives either in PrismD1SecurityAgent or in PrismD1MetricsPipeline, never both.');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (standalone) {
|
|
29
|
+
new SecurityAgentStack(app, 'PrismD1SecurityAgent', {
|
|
30
|
+
env,
|
|
31
|
+
description: 'PRISM D1 Velocity - AWS Security Agent (standalone, without the metrics pipeline)',
|
|
32
|
+
kmsKeyArn: app.node.tryGetContext('securityAgentKmsKeyArn') as string | undefined,
|
|
33
|
+
tags: {
|
|
34
|
+
'prism:project': 'PRISM',
|
|
35
|
+
'prism:domain': 'D1-Velocity',
|
|
36
|
+
'prism:component': 'SecurityAgent',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
} else {
|
|
40
|
+
const pipelineStack = new MetricsPipelineStack(app, 'PrismD1MetricsPipeline', {
|
|
41
|
+
env,
|
|
42
|
+
description: 'PRISM D1 Velocity - Core metrics event pipeline (EventBridge, DynamoDB)',
|
|
43
|
+
tags: {
|
|
44
|
+
'prism:project': 'PRISM',
|
|
45
|
+
'prism:domain': 'D1-Velocity',
|
|
46
|
+
'prism:component': 'MetricsPipeline',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const apiStack = new ApiStack(app, 'PrismD1Api', {
|
|
51
|
+
env,
|
|
52
|
+
description: 'PRISM D1 Velocity - Metric ingestion and query API',
|
|
53
|
+
eventBus: pipelineStack.eventBus,
|
|
54
|
+
eventsTable: pipelineStack.eventsTable,
|
|
55
|
+
metadataTable: pipelineStack.metadataTable,
|
|
56
|
+
kmsKey: pipelineStack.kmsKey,
|
|
57
|
+
tags: {
|
|
58
|
+
'prism:project': 'PRISM',
|
|
59
|
+
'prism:domain': 'D1-Velocity',
|
|
60
|
+
'prism:component': 'Api',
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const dashboardStack = new DashboardStack(app, 'PrismD1Dashboard', {
|
|
65
|
+
env,
|
|
66
|
+
description: 'PRISM D1 Velocity - CloudWatch dashboards and alarms',
|
|
67
|
+
productivityWidgetArn: pipelineStack.otelCollector?.productivityWidgetArn,
|
|
68
|
+
velocityWidgetArn: pipelineStack.velocityWidgetArn,
|
|
69
|
+
tags: {
|
|
70
|
+
'prism:project': 'PRISM',
|
|
71
|
+
'prism:domain': 'D1-Velocity',
|
|
72
|
+
'prism:component': 'Dashboard',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
apiStack.addDependency(pipelineStack);
|
|
77
|
+
}
|
|
54
78
|
|
|
55
79
|
// Enable cdk-nag AWS Solutions checks on all stacks
|
|
56
80
|
Aspects.of(app).add(new AwsSolutionsChecks({ verbose: true }));
|
|
@@ -24,6 +24,9 @@ import * as cognito from 'aws-cdk-lib/aws-cognito';
|
|
|
24
24
|
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
25
25
|
import * as kms from 'aws-cdk-lib/aws-kms';
|
|
26
26
|
import * as logs from 'aws-cdk-lib/aws-logs';
|
|
27
|
+
import * as events from 'aws-cdk-lib/aws-events';
|
|
28
|
+
import * as targets from 'aws-cdk-lib/aws-events-targets';
|
|
29
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
27
30
|
import * as apigwv2 from 'aws-cdk-lib/aws-apigatewayv2';
|
|
28
31
|
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
29
32
|
import { HttpJwtAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
|
|
@@ -32,6 +35,7 @@ import * as ssm from 'aws-cdk-lib/aws-ssm';
|
|
|
32
35
|
import * as path from 'path';
|
|
33
36
|
import { Construct } from 'constructs';
|
|
34
37
|
import { NagSuppressions } from 'cdk-nag';
|
|
38
|
+
import { PRICES_KEY } from '../lambda/pricing/prices-key';
|
|
35
39
|
|
|
36
40
|
/** codeburn sync fixed loopback callback ports (see codeburn src/sync/auth.ts). */
|
|
37
41
|
const CODEBURN_CALLBACK_PORTS = [19876, 19877, 19878];
|
|
@@ -509,9 +513,101 @@ export class OtelCollectorConstruct extends Construct {
|
|
|
509
513
|
|
|
510
514
|
props.aiUsageTable.grantReadWriteData(receiver);
|
|
511
515
|
this.archiveBucket.grantPut(receiver);
|
|
516
|
+
// The LiteLLM price table the refresh Lambda maintains (pricing/price-source.ts).
|
|
517
|
+
// Exact key, read only. KMS decrypt comes from grantEncryptDecrypt below.
|
|
518
|
+
const pricesObjectArn = this.archiveBucket.arnForObjects(PRICES_KEY);
|
|
519
|
+
receiver.addToRolePolicy(new iam.PolicyStatement({
|
|
520
|
+
actions: ['s3:GetObject'],
|
|
521
|
+
resources: [pricesObjectArn],
|
|
522
|
+
}));
|
|
512
523
|
props.kmsKey.grantEncryptDecrypt(receiver);
|
|
513
524
|
this.receiverFunction = receiver;
|
|
514
525
|
|
|
526
|
+
// -------------------------------------------------------
|
|
527
|
+
// Price refresh + reprice — daily
|
|
528
|
+
// Keeps the receiver's LiteLLM fallback table current in S3, then
|
|
529
|
+
// corrects spans stored at $0 whose model has since been priced.
|
|
530
|
+
// See lib/lambda/pricing-refresh.ts.
|
|
531
|
+
//
|
|
532
|
+
// Deliberately NOT in the VPC: the PRISM VPC has no NAT gateway, and this
|
|
533
|
+
// function's one job that needs a network path is an HTTPS GET to
|
|
534
|
+
// raw.githubusercontent.com. It accepts no inbound traffic, and reaches
|
|
535
|
+
// only S3 and DynamoDB besides, both over their public endpoints with IAM.
|
|
536
|
+
// -------------------------------------------------------
|
|
537
|
+
const pricingRefresh = new lambda.Function(this, 'PricingRefresh', {
|
|
538
|
+
functionName: 'prism-d1-pricing-refresh',
|
|
539
|
+
runtime: lambda.Runtime.NODEJS_22_X,
|
|
540
|
+
handler: 'pricing-refresh.handler',
|
|
541
|
+
code: lambda.Code.fromAsset(path.join(__dirname, '..', 'lambda'), {
|
|
542
|
+
bundling: {
|
|
543
|
+
image: lambda.Runtime.NODEJS_22_X.bundlingImage,
|
|
544
|
+
command: [
|
|
545
|
+
'bash', '-c',
|
|
546
|
+
[
|
|
547
|
+
'npm init -y > /dev/null 2>&1',
|
|
548
|
+
'npm install --save @aws-sdk/client-dynamodb @aws-sdk/client-s3 esbuild > /dev/null 2>&1',
|
|
549
|
+
'npx esbuild pricing-refresh.ts --bundle --platform=node --target=node22 --outfile=/asset-output/pricing-refresh.js --external:@aws-sdk/*',
|
|
550
|
+
].join(' && '),
|
|
551
|
+
],
|
|
552
|
+
local: {
|
|
553
|
+
tryBundle(outputDir: string): boolean {
|
|
554
|
+
try {
|
|
555
|
+
const { execSync } = require('child_process');
|
|
556
|
+
execSync(
|
|
557
|
+
`npx esbuild ${path.join(__dirname, '..', 'lambda', 'pricing-refresh.ts')} --bundle --platform=node --target=node22 --outfile=${path.join(outputDir, 'pricing-refresh.js')} --external:@aws-sdk/*`,
|
|
558
|
+
{ stdio: 'pipe' },
|
|
559
|
+
);
|
|
560
|
+
return true;
|
|
561
|
+
} catch {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
}),
|
|
568
|
+
// A full-table scan plus, on the first run, a read of the raw archive to
|
|
569
|
+
// recover cache-token counts for spans stored before they were kept.
|
|
570
|
+
timeout: cdk.Duration.minutes(15),
|
|
571
|
+
memorySize: 1024,
|
|
572
|
+
environment: {
|
|
573
|
+
AI_USAGE_TABLE: props.aiUsageTable.tableName,
|
|
574
|
+
ARCHIVE_BUCKET: this.archiveBucket.bucketName,
|
|
575
|
+
},
|
|
576
|
+
logRetention: logs.RetentionDays.ONE_MONTH,
|
|
577
|
+
description: 'Daily: refresh the LiteLLM price table in S3, then reprice usage spans stored at $0',
|
|
578
|
+
});
|
|
579
|
+
props.aiUsageTable.grantReadWriteData(pricingRefresh);
|
|
580
|
+
// Read the raw archive (to recover cache-token counts), and read/write the
|
|
581
|
+
// one price-table object. No delete: an old table is only ever overwritten.
|
|
582
|
+
this.archiveBucket.grantRead(pricingRefresh, 'otlp/*');
|
|
583
|
+
pricingRefresh.addToRolePolicy(new iam.PolicyStatement({
|
|
584
|
+
actions: ['s3:GetObject', 's3:PutObject'],
|
|
585
|
+
resources: [pricesObjectArn],
|
|
586
|
+
}));
|
|
587
|
+
props.kmsKey.grantEncryptDecrypt(pricingRefresh);
|
|
588
|
+
|
|
589
|
+
new events.Rule(this, 'PricingRefreshSchedule', {
|
|
590
|
+
ruleName: 'prism-d1-pricing-refresh-daily',
|
|
591
|
+
description: 'Refresh LiteLLM prices and reprice $0 spans',
|
|
592
|
+
// 06:17 UTC: off the hour so it is not queued behind other schedules.
|
|
593
|
+
schedule: events.Schedule.cron({ minute: '17', hour: '6' }),
|
|
594
|
+
// No retry: a failed run already repriced what it could and the next day's
|
|
595
|
+
// run starts from the same state. Errors surface on the Lambda metric.
|
|
596
|
+
targets: [new targets.LambdaFunction(pricingRefresh, { retryAttempts: 0 })],
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
NagSuppressions.addResourceSuppressions(pricingRefresh, [
|
|
600
|
+
{
|
|
601
|
+
id: 'AwsSolutions-IAM5',
|
|
602
|
+
reason: 'grantRead scopes S3 reads to the otlp/* prefix of the single archive bucket (raw OTLP batches, read to recover cache-token counts); grantReadWriteData adds the AI-usage table GSI index wildcard.',
|
|
603
|
+
appliesTo: [
|
|
604
|
+
'Action::s3:GetObject*', 'Action::s3:GetBucket*', 'Action::s3:List*',
|
|
605
|
+
{ regex: '/^Resource::<OtelCollectorArchiveBucket.*\\.Arn>\\/otlp\\/\\*$/g' },
|
|
606
|
+
{ regex: '/^Resource::<AiUsageTable.*\\.Arn>\\/index\\/\\*$/g' },
|
|
607
|
+
],
|
|
608
|
+
},
|
|
609
|
+
], true);
|
|
610
|
+
|
|
515
611
|
// -------------------------------------------------------
|
|
516
612
|
// CloudWatch Custom Widget: Developer Productivity
|
|
517
613
|
// Invoked by CloudWatch dashboards with the VIEWING user's IAM creds
|
|
@@ -168,6 +168,32 @@ export class SecurityAgentConstruct extends Construct {
|
|
|
168
168
|
);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
// -------------------------------------------------------
|
|
172
|
+
// S3 Scan Bucket — stores repo ZIPs and diff files for
|
|
173
|
+
// API-triggered code reviews (diff scans from CI/CD) and
|
|
174
|
+
// threat models. Created before the agent space, which lists it.
|
|
175
|
+
// -------------------------------------------------------
|
|
176
|
+
this.scanBucket = new s3.Bucket(this, 'ScanBucket', {
|
|
177
|
+
bucketName: `security-agent-scans-${cdk.Aws.ACCOUNT_ID}-${cdk.Aws.REGION}`,
|
|
178
|
+
// SSE-S3 (not the customer-managed KMS key): the Continuum service reads
|
|
179
|
+
// this bucket when creating the code review and cannot access a CMK it
|
|
180
|
+
// has no grant on. Artifacts here are ephemeral diffs (30-day lifecycle),
|
|
181
|
+
// the bucket is private (BLOCK_ALL) and SSL-enforced.
|
|
182
|
+
encryption: s3.BucketEncryption.S3_MANAGED,
|
|
183
|
+
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
184
|
+
enforceSSL: true,
|
|
185
|
+
versioned: false,
|
|
186
|
+
lifecycleRules: [
|
|
187
|
+
{
|
|
188
|
+
id: 'expire-scan-artifacts',
|
|
189
|
+
expiration: cdk.Duration.days(30),
|
|
190
|
+
enabled: true,
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
194
|
+
autoDeleteObjects: true,
|
|
195
|
+
});
|
|
196
|
+
|
|
171
197
|
// Agent Space
|
|
172
198
|
const agentSpace = new securityagent.CfnAgentSpace(this, 'AgentSpace', {
|
|
173
199
|
name: props.agentSpaceName,
|
|
@@ -177,6 +203,9 @@ export class SecurityAgentConstruct extends Construct {
|
|
|
177
203
|
}),
|
|
178
204
|
awsResources: {
|
|
179
205
|
iamRoles: [this.serviceRole.roleArn],
|
|
206
|
+
// create-threat-model refuses S3 sources and scope docs in a bucket the
|
|
207
|
+
// agent space does not list ("S3 bucket not found in agent instance S3 buckets").
|
|
208
|
+
s3Buckets: [this.scanBucket.bucketArn],
|
|
180
209
|
},
|
|
181
210
|
tags: [
|
|
182
211
|
{ key: 'prism:component', value: 'security-agent' },
|
|
@@ -210,7 +239,7 @@ export class SecurityAgentConstruct extends Construct {
|
|
|
210
239
|
|
|
211
240
|
// Log group for pen test results (Security Agent writes to /aws/securityagent/<space>/pt-<id>)
|
|
212
241
|
// Note: we do NOT set logGroupName to avoid conflicts with pre-existing log groups
|
|
213
|
-
// created by prism-cli
|
|
242
|
+
// created by prism-cli enable security or the Security Agent service itself.
|
|
214
243
|
const pentestLogGroup = logs.LogGroup.fromLogGroupName(
|
|
215
244
|
this, 'PentestLogGroup',
|
|
216
245
|
`/aws/securityagent/${props.agentSpaceName}`,
|
|
@@ -237,31 +266,6 @@ export class SecurityAgentConstruct extends Construct {
|
|
|
237
266
|
});
|
|
238
267
|
}
|
|
239
268
|
|
|
240
|
-
// -------------------------------------------------------
|
|
241
|
-
// S3 Scan Bucket — stores repo ZIPs and diff files for
|
|
242
|
-
// API-triggered code reviews (diff scans from CI/CD).
|
|
243
|
-
// -------------------------------------------------------
|
|
244
|
-
this.scanBucket = new s3.Bucket(this, 'ScanBucket', {
|
|
245
|
-
bucketName: `security-agent-scans-${cdk.Aws.ACCOUNT_ID}-${cdk.Aws.REGION}`,
|
|
246
|
-
// SSE-S3 (not the customer-managed KMS key): the Continuum service reads
|
|
247
|
-
// this bucket when creating the code review and cannot access a CMK it
|
|
248
|
-
// has no grant on. Artifacts here are ephemeral diffs (30-day lifecycle),
|
|
249
|
-
// the bucket is private (BLOCK_ALL) and SSL-enforced.
|
|
250
|
-
encryption: s3.BucketEncryption.S3_MANAGED,
|
|
251
|
-
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
252
|
-
enforceSSL: true,
|
|
253
|
-
versioned: false,
|
|
254
|
-
lifecycleRules: [
|
|
255
|
-
{
|
|
256
|
-
id: 'expire-scan-artifacts',
|
|
257
|
-
expiration: cdk.Duration.days(30),
|
|
258
|
-
enabled: true,
|
|
259
|
-
},
|
|
260
|
-
],
|
|
261
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
262
|
-
autoDeleteObjects: true,
|
|
263
|
-
});
|
|
264
|
-
|
|
265
269
|
// Grant Security Agent service role read access to the scan bucket
|
|
266
270
|
this.scanBucket.grantRead(this.serviceRole);
|
|
267
271
|
|
|
@@ -298,10 +302,11 @@ export class SecurityAgentConstruct extends Construct {
|
|
|
298
302
|
// Code Review resource — NOT created here in CDK.
|
|
299
303
|
// CreateCodeReview requires assets.sourceCode pointing to
|
|
300
304
|
// an existing ZIP of the repo (chicken-and-egg at deploy).
|
|
301
|
-
// Instead, `prism-cli
|
|
302
|
-
//
|
|
305
|
+
// Instead, `prism-cli enable security` (or the CI eval gate on its
|
|
306
|
+
// first run) handles, per repo:
|
|
307
|
+
// 1. git archive → upload repo/<repo-slug>/latest.zip to the scan bucket
|
|
303
308
|
// 2. CreateCodeReview API call
|
|
304
|
-
// 3. Write code-review-id to SSM
|
|
309
|
+
// 3. Write /prism/continuum/code-review-id/<repo-slug> to SSM
|
|
305
310
|
// The CDK only provisions the bucket + role + SSM scaffold.
|
|
306
311
|
// -------------------------------------------------------
|
|
307
312
|
|
|
@@ -325,7 +330,7 @@ export class SecurityAgentConstruct extends Construct {
|
|
|
325
330
|
tier: ssm.ParameterTier.STANDARD,
|
|
326
331
|
});
|
|
327
332
|
|
|
328
|
-
// code-review-id is written by `prism-cli
|
|
333
|
+
// code-review-id/<repo-slug> is written by `prism-cli enable security` (not CDK)
|
|
329
334
|
// because CreateCodeReview needs an existing repo ZIP in S3 first.
|
|
330
335
|
|
|
331
336
|
new ssm.StringParameter(this, 'ParamScanBucket', {
|
|
@@ -808,6 +808,33 @@ export class DashboardStack extends cdk.Stack {
|
|
|
808
808
|
}),
|
|
809
809
|
);
|
|
810
810
|
|
|
811
|
+
// --- Row 5: Tools the model invoked (codeburn ai.tools) ---
|
|
812
|
+
// Store-backed like the spend tiles: OTEL#TOOLDAY rollups are bucketed by
|
|
813
|
+
// the call's own day and keep full history, so a backfilled sync push is
|
|
814
|
+
// not cut off at CloudWatch's two-week window. Follows the Developer filter.
|
|
815
|
+
devDashboard.addWidgets(
|
|
816
|
+
new cloudwatch.CustomWidget({
|
|
817
|
+
functionArn: props.velocityWidgetArn ?? '',
|
|
818
|
+
title: 'Tool Usage: Top Tools & MCP Servers',
|
|
819
|
+
width: 16,
|
|
820
|
+
height: 9,
|
|
821
|
+
params: { view: 'tool-usage-top', user: USER_TOKEN },
|
|
822
|
+
updateOnRefresh: true,
|
|
823
|
+
updateOnResize: false,
|
|
824
|
+
updateOnTimeRangeChange: true,
|
|
825
|
+
}),
|
|
826
|
+
new cloudwatch.CustomWidget({
|
|
827
|
+
functionArn: props.velocityWidgetArn ?? '',
|
|
828
|
+
title: 'Tool Calls / Day',
|
|
829
|
+
width: 8,
|
|
830
|
+
height: 9,
|
|
831
|
+
params: { view: 'tool-usage-trend', user: USER_TOKEN },
|
|
832
|
+
updateOnRefresh: true,
|
|
833
|
+
updateOnResize: false,
|
|
834
|
+
updateOnTimeRangeChange: true,
|
|
835
|
+
}),
|
|
836
|
+
);
|
|
837
|
+
|
|
811
838
|
new cdk.CfnOutput(this, 'DevProductivityDashboardUrl', {
|
|
812
839
|
value: `https://${this.region}.console.aws.amazon.com/cloudwatch/home?region=${this.region}#dashboards:name=PRISM-D1-Developer-Productivity`,
|
|
813
840
|
description: 'Developer Productivity Dashboard URL',
|