Skip to content

Implement vulnerability integration and ticketing configurations#137

Merged
alex-dembele merged 9 commits into
masterfrom
feature/vulnerability-management-connectors
Jul 18, 2026
Merged

Implement vulnerability integration and ticketing configurations#137
alex-dembele merged 9 commits into
masterfrom
feature/vulnerability-management-connectors

Conversation

@alex-dembele

Copy link
Copy Markdown
Member

No description provided.

alex-dembele and others added 9 commits July 17, 2026 13:59
…ed creds)

Add VulnIntegration (per-source scanner connector config: encrypted API
credentials, base URL, live-pull schedule, inbound webhook token, auto-risk /
auto-ticket toggles) and VulnTicketingConfig (tenant ITSM config) domain models,
their tenant-scoped Gorm repository, and the cross-module linkage columns on the
Vulnerability register (risk_id + ticket ref). Credentials are AES-256-GCM at
rest and never serialised (json:"-"); only HasCredentials is exposed. Wired
into AutoMigrate + migration 0033.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… returned)

Add the connector-configuration use cases (Save/List/Get/Delete integration,
Save/Get/Delete ticketing) behind a CredentialCipher seam satisfied by the
scanner's AES-256-GCM cipher, plus the Fiber handler and routes under
/vulnerabilities/integrations and /vulnerabilities/ticketing (guarded by
vulnerabilities:{read,update,delete}). Credentials are write-only (json:"-"),
preserved on update when not re-supplied, and a webhook token is minted on demand.
Tests: save success/unsupported-source/preserve-creds, cross-tenant NotFound,
ticketing requires-provider/success.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scanners can now push findings automatically to
POST /api/v1/vulnerabilities/webhook/:source, authenticated by the integration's
opaque webhook token (query ?token=, X-Webhook-Token, or Bearer) — no user JWT.
Mounted on `app` before the /api/v1 JWT gate (same pattern as scanner agents);
the token carries the tenant identity, the :source segment is cross-checked, and
the payload parser accepts a bare array, a {findings|results|data|vulnerabilities|
items} wrapper, or a single object. Unknown/disabled tokens get a uniform 401.
Test: parseWebhookFindings across shapes + malformed input.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add internal/vulnscan/livepull: a per-source Puller registry that makes REAL
authenticated HTTP calls and returns findings in each tool's native shape, which
then flow through the existing normalisers → prioritisation → upsert.

Real pullers (httptest-proven mechanisms): Microsoft Defender for Endpoint
(OAuth2 client-credentials → /api/vulnerabilities), CrowdStrike Falcon Spotlight
(OAuth2 → combined/vulnerabilities), Tenable Nessus/Tenable.io (X-ApiKeys →
workbenches), Qualys VMDR (Basic auth → XML detection list, parsed), Microsoft
Defender for Cloud (OAuth2 → ARM subAssessments). Honest seams for OpenVAS (GMP,
not REST) and AWS Inspector (SDK path) — they report why + point to webhook/
import, never fabricating data (same contract as the scanner cloud collectors).

TriggerLivePullUseCase decrypts creds, polls via an injectable LivePuller seam,
ingests, and records ok/error + count on the integration row; exposed at
POST /vulnerabilities/integrations/:id/pull. LivePullScheduler polls due
integrations (schedule_minutes) behind VULN_LIVEPULL_ENABLED.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…TI feed

IngestUseCase gains an optional CTIEnricher seam (WithCTIEnricher): every
ingested finding with a CVE is cross-referenced against cti_vulnerabilities
(NVD + CISA-KEV sync) BEFORE prioritisation. KEV is OR-ed in (never downgraded)
and implies exploited-in-the-wild; CVSS/severity backfill only gaps. So a
scanner finding that only knew a modest CVSS is correctly floored to P1 once the
CTI feed reveals it is known-exploited. EPSS stays sourced from the finding (the
current CTI feed has no EPSS; a future feed lights it up with no caller change).
Wired in main.go via a CTIRepoEnricher over the shared CTI repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
IngestUseCase gains an optional RiskProposer seam (WithRiskProposer) triggered,
opt-in per integration (IngestInput.AutoCreateRisk, propagated from the webhook,
live-pull and manual-import paths), when a finding is P1 or CISA-KEV AND
attributed to an asset. The created risk is linked back onto the vulnerability
row (risk_id). The infrastructure impl (internal/infrastructure/vulnrisk) mirrors
the CTI CVE→risk path: Source=scan_auto, SourceCVEID set, probability/impact on
the Score Engine scales, idempotent by (tenant, asset, cve|name) so re-scans
never duplicate. Tests: KEV-on-asset creates+links, disabled/no-asset/low-priority
all skip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add pkg/ticketing: a domain-free provider package with REAL REST clients for
Jira Cloud (POST /rest/api/2/issue, Basic email+token → SEC-42 + /browse URL)
and ServiceNow (POST /api/now/table/incident, Basic auth → INC number + nav URL);
absent/wrong creds surface the tool's real error, never a fabricated ticket
(httptest-proven, incl. the 401 case + SN priority map).

Application: ConfigTicketOpener composes the tenant ITSM config + provider and
renders a vulnerability into a ticket (summary/description/priority). Wired into
ingest via WithTicketOpener (auto-open for P1/KEV, opt-in per integration
AutoCreateTicket, propagated through webhook/live-pull/manual) and exposed
manually at POST /vulnerabilities/:id/ticket (CreateTicketUseCase — 404 unknown,
409 already-ticketed, 400 ITSM-not-configured). Ticket ref linked onto the row.
Tests: auto-open on KEV, skip when disabled, manual success/not-configured/
already-ticketed/not-found.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…webhooks)

Replace the read-only ConnectorsPanel with a full config screen (IntegrationsPanel):
per-source credential forms (write-only — existing secrets show as configured and
are preserved unless re-typed), base URL, inbound webhook URL with copy +
regenerate, live-pull toggle + schedule + Pull now, and the auto-create-risk /
auto-create-ticket toggles. A Ticketing tab configures Jira/ServiceNow (provider,
instance URL, project/table, credentials). New typed service + React Query hooks
(zero any). The vulnerability drawer now shows the opened ITSM ticket link (or an
Open-a-ticket button) and flags a linked auto-created risk.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… 6.5)

Document the integration config screen (encrypted creds + inbound webhooks),
real REST live-pull (Defender/CrowdStrike/Nessus/Qualys/Azure + honest OpenVAS/
AWS seams), CTI KEV/CVSS enrichment on ingest, auto-create-risk from P1/KEV, and
Jira/ServiceNow auto-ticketing — with the live-proof (creds never returned,
webhook 202/401/400, real Qualys 401 recorded, encrypted-at-rest, no fake ticket).
@alex-dembele
alex-dembele merged commit 467d7ac into master Jul 18, 2026
9 of 18 checks passed
@alex-dembele
alex-dembele deleted the feature/vulnerability-management-connectors branch July 18, 2026 15:45
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.

1 participant