Skip to content

Fix stale-issue bug, add integrations (SNS+Slack), and DSPM data discovery#8

Merged
therandomsecurityguy merged 3 commits into
mainfrom
dac/fixes-integrations-data-discovery
Jul 9, 2026
Merged

Fix stale-issue bug, add integrations (SNS+Slack), and DSPM data discovery#8
therandomsecurityguy merged 3 commits into
mainfrom
dac/fixes-integrations-data-discovery

Conversation

@therandomsecurityguy

@therandomsecurityguy therandomsecurityguy commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the gap analysis by addressing three of the highest-priority findings from the Wiz-parity review: the dead autoTicketConfig, the stale-issue lifecycle bug, and the absence of automated data discovery (DSPM).

Phase 1.1 — Stale-issue fix + posture trends

  • Bug fix: runner.ts existing-issue branch only added to activeIssueIds without refreshing fields — issues were frozen at first creation. Now refreshExistingIssue re-derives riskScore, severity, pathSummary, and metadata.scoringFactors on every re-match, guarded by #status <> :resolved so resolved issues aren't clobbered.
  • New PostureTrendStore (packages/risk-engine/src/posture-trend-store.ts) writes daily snapshots to DynamoDB PostureTrends (metrics: openIssuesBySeverity, publicBuckets, crossAccountTrusts, usersWithoutMfa).
  • New API: GET /trends/:metric?days=90 returns the historical series.

Phase 1.2 — Integrations core (SNS + Slack)

  • New @khalifa/integrations package with pluggable IssueActionSink interface — the previously dead autoTicketConfig is now wired to live sinks.
  • SNS sink publishes issue JSON envelopes to ISSUES_TOPIC_ARN (drives email/Lambda/SQS fan-out) with severity/rule/issueId message attributes.
  • Slack sink posts Block Kit cards to an incoming webhook, filtered by SLACK_MIN_SEVERITY (default high).
  • IssueIntegrationsOrchestrator loads sinks from comma-separated ISSUE_SINKS env var; dedupes names; ignores unknown sinks. Best-effort emit — sink errors never fail the rule run.
  • Issue.externalRefs field added to types (risk-engine + api-service), persisted via updateExternalRefs (dedup by system+id).
  • New API routes: GET /integrations/status (Viewer+), POST /issues/:id/suppress (Analyst+), POST /issues/:id/reopen (Analyst+).
  • CDK: SNS topic khalifa-issues, risk-engine role granted sns:Publish + PostureTrendsTable write.
  • ConfigMap: ISSUES_TOPIC_ARN, ISSUE_SINKS, SLACK_WEBHOOK_URL, SLACK_MIN_SEVERITY, UI_BASE_URL, POSTURE_TRENDS_TABLE.

Phase 2.2 — DSPM data discovery

  • New dspm-scanner Lambda — agentless S3 sampler with pluggable classifiers.
  • Regex classifier (regex-classifier.ts) detects: AWS access keys (AKIA…), AWS secret keys, GCP service-account JSON, private keys (-----BEGIN … PRIVATE KEY-----), JWTs, credit cards (Luhn-validated), emails, phone, SSN, high-entropy secrets (Shannon entropy ≥ 4.5).
  • Macie classifier (opt-in via MACIE_ENABLED=true) enriches with managed PII findings via ListFindings/GetFindings.
  • promoteClassification() maps findings to secret / restricted / internal tiers with confidence scores.
  • Graph schema: new DataClassificationFinding vertex + CLASSIFIES edge to S3Bucket/RdsInstance; new prop data_class_source: 'tag'|'scanner'|'macie'.
  • New rules: RULE-011 (public datastore with PII), RULE-012 (secret committed in S3 object).
  • CDK: DspmScannerFn (15m timeout, 2GB mem), EventBridge daily at 03:00 UTC, S3 read IAM grants; DSPM_SCAN_MODE=off|tagged-only|all (default tagged-only for cost control).
  • Privacy/OPSEC: sample-size cap (50 objects/bucket, 256KB/object), never stores sampled values — only metadata (piiTypes, secretCount, confidence).

Test plan

  • npm run build --workspaces — all 9 workspaces compile clean
  • CDK stack compiles (cdk workspace tsc)
  • npx jest121 tests passing across 12 suites (risk-engine, integrations, api-service, dspm-scanner, collector)
  • Lint clean on all modified workspaces (0 errors; pre-existing policy-evaluator warnings untouched)
  • runner.test.ts verifies re-match updates existing issue fields (not frozen)
  • runner.test.ts verifies emitToIntegrations skips suppressed issues and disabled autoTicketConfig
  • orchestrator.test.ts verifies sink loading, dedup, and unknown-sink handling
  • classifier.test.ts verifies regex patterns (AWS keys, private keys, JWT, Luhn credit cards, SSN, GCP SA, high-entropy) and promoteClassification tiers
  • rules.test.ts updated to expect 12 rules (11 enabled — RULE-003 still disabled)

Files changed

37 files, +2,180 / -302 lines.

Not in this PR (Phase 2.1 — designed, not built)

Jira sink, Security Hub ASFF export, and SSM Automation auto-remediation actions. The IssueActionSink interface and RemediationAction type in packages/integrations/src/types.ts are ready to accept them as a follow-up.

Phase 1.1 - Stale-issue fix + trends:
- Fix runner.ts existing-issue branch to re-derive riskScore/severity/pathSummary
  on re-match instead of skipping (was frozen at first creation)
- Add PostureTrendStore for daily posture snapshots (openIssues, publicBuckets, etc.)
- Add GET /trends/:metric API endpoint
- CDK: add PostureTrendsTable

Phase 1.2 - Integrations core (SNS + Slack):
- New @khalifa/integrations package with pluggable IssueActionSink interface
- SNS sink (publishes issue JSON to ISSUES_TOPIC_ARN)
- Slack sink (incoming-webhook card with severity filtering)
- IssueIntegrationsOrchestrator loads sinks from ISSUE_SINKS env var
- Wire emitToIntegrations into runner after issue create/update
- Add Issue.externalRefs field persisted to DynamoDB
- API: GET /integrations/status, POST /issues/:id/suppress, POST /issues/:id/reopen
- CDK: add SNS topic, grant risk-engine sns:Publish
- ConfigMap: ISSUE_SINKS, SLACK_WEBHOOK_URL, SLACK_MIN_SEVERITY env vars

Phase 2.2 - DSPM data discovery:
- New dspm-scanner Lambda with S3 sampler + regex + Macie classifiers
- Regex classifier detects: AWS keys, GCP SA JSON, private keys, JWT,
  credit cards (Luhn), emails, phone, SSN, high-entropy secrets
- Macie classifier (opt-in) pulls findings via ListFindings/GetFindings
- promoteClassification() maps PII findings to data_classification tiers
- New DataClassificationFinding vertex + CLASSIFIES edge in graph schema
- New RULE-011 (public datastore with PII) and RULE-012 (secret in S3)
- CDK: DspmScannerFn (15m timeout, 2GB mem), EventBridge daily 03:00 UTC
- ConfigMap: DSPM_SCAN_MODE (off|tagged-only|all), MACIE_ENABLED env vars

Tests: 121 passing across 12 suites (risk-engine, integrations, api-service,
dspm-scanner, collector)
- Remove prepare:tsc from risk-engine package.json (caused npm ci to
  run tsc before @khalifa/integrations was built)
- Update build:lambdas to build integrations first
- Update jest.setup.js to build integrations before risk-engine
- Update CI workflow: add integrations/dspm-scanner to cache paths,
  format/lint/typecheck/build steps, and build integrations before
  risk-engine in typecheck/build/test jobs
The old prepare:tsc produced dist/ during npm ci, which api-service's
tsc --noEmit relied on. Now we explicitly build integrations + risk-engine
(with output) before type-checking api-service.
@Shasheen8

Copy link
Copy Markdown
Collaborator

@therandomsecurityguy I wanted to ask you about the direction for this.

Would be good to discuss what a final state of this tool would look like.

@Shasheen8

Copy link
Copy Markdown
Collaborator

@Anusha-RG can we get this data into the dashboard too? But we need to first plug it into prod

@therandomsecurityguy therandomsecurityguy merged commit d0a04f8 into main Jul 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants