Skip to content

ServiceNow integration

ServiceNow is SARC’s workflow control plane. Where the Evidence Vault (Fides) holds the immutable evidence, ServiceNow holds the human change process — the change request, the approval, the CMDB, problems, incidents, and SLAs. SARC talks to ServiceNow in both directions: the CI pipeline writes the change record and its evidence, and the SARC portal reads that data back to drive decisions and surface it to operators and auditors.

This page is the full story: why, the technical design, what lands in ServiceNow, how the portal consumes it, and how SARC turns ServiceNow data into decisions. Use the Fullscreen button on any diagram to study it.

A scan result or a Fides attestation proves what happened technically. It does not satisfy the change-management control an enterprise auditor expects: a recorded change request, a risk assessment, an approver, and a closed-out record tied to the CMDB. SARC bridges that gap automatically — every pipeline run produces a real ServiceNow Change Request, enriched with the evidence, risk- scored, gated on approval, and closed after deploy. The result: the same deployment is both technically attested (Evidence Vault) and process- compliant (ServiceNow), with no manual ticket-raising.

flowchart TD
  subgraph CI["CI pipeline — WRITE path (Basic auth; attest + post-deploy)"]
    direction TB
    W1["servicenow-cr.sh<br/>POST change_request + ~40 custom fields"]
    W2["fides-score.sh<br/>PATCH 5-axis clearance + approval"]
    W3["compliance-report / sbom-attach<br/>POST /attachment/file + work_notes"]
    W4["servicenow-fides-sync.sh<br/>POST u_fides_artifact / test_result / vulnerability"]
    W5["wait-approval.sh<br/>GET approval (poll — qa/prod gate)"]
    W6["cr close (post-deploy)<br/>PATCH state=Closed + close_code"]
    W1 ~~~ W2 ~~~ W3 ~~~ W4 ~~~ W5 ~~~ W6
  end

  SNOW[("ServiceNow<br/>change_request · cmdb_ci_* · problem · incident<br/>task_sla · pa_dashboard · u_fides_*")]

  subgraph PORTAL["SARC portal — READ path (per-tenant TenantConfig Basic auth)"]
    direction TB
    R1["/change-requests · /timeline<br/>read CRs · approve / reject"]
    R2["/services · /services/[slug]<br/>SLA + CR-conflict banners"]
    R3["/problems<br/>regression + deploy correlation"]
    R4["/cmdb<br/>CIs + relationship graph"]
    R1 ~~~ R2 ~~~ R3 ~~~ R4
  end

  CI ==>|write| SNOW
  SNOW ==>|read| PORTAL
  PORTAL -.->|approve / reject · CMDB upsert| SNOW

  class W1,W2,W3,W4,W5,W6 write
  class R1,R2,R3,R4 read
  class SNOW snow
  classDef write fill:#2da44e,stroke:#116329,color:#ffffff
  classDef read fill:#1f6feb,stroke:#0b3d91,color:#ffffff
  classDef snow fill:#d29922,stroke:#8a6500,color:#ffffff

Both directions use the ServiceNow Table API (/api/now/table/...) and Attachment API (/api/now/attachment/file) over HTTP Basic auth. The pipeline reads its credentials from CI variables (SERVICENOW_INSTANCE_URL, SERVICENOW_USERNAME, SERVICENOW_PASSWORD); the portal reads per-tenant credentials from the TenantConfig table (snowUrl, snowUser, snowPass), so each tenant points at its own instance.

How the pipeline writes to ServiceNow (technical design)

Section titled “How the pipeline writes to ServiceNow (technical design)”

The write path runs in the attest stage (create + enrich + risk) and the post-deploy stage (close), with the approval poll in approve-deploy.

flowchart TD
  CREATE["attest · servicenow-cr.sh create<br/>POST change_request (state=New)<br/>custom fields + 5 narratives + assignment refs"]
  RISK["attest · fides-score.sh<br/>query Evidence Vault trail -> 5-axis clearance<br/>PATCH u_risk_score · u_risk_assessment · approval"]
  ENRICH["attest · enrich<br/>compliance report + SBOM zip (attachments)<br/>+ u_fides_* rows"]
  GATE{"auto-approve?<br/>risk &lt;= env threshold<br/>AND Evidence Vault compliant"}
  WAIT["approve-deploy · wait-approval.sh<br/>poll approval (30s, 1h timeout)"]
  CLOSE["post-deploy · servicenow-cr.sh close<br/>PATCH state=Closed · close_code · duration"]

  CREATE --> RISK --> ENRICH --> GATE
  GATE -->|"dev: always · qa: score&lt;=5"| AUTO["auto-approved<br/>(fast-path, no poll)"]
  GATE -->|"prod: always manual · or non-compliant"| WAIT
  AUTO --> CLOSE
  WAIT -->|approved| CLOSE
  WAIT -->|rejected / timeout| FAIL["pipeline fails<br/>(real gate)"]

  class CREATE,ENRICH write
  class RISK risk
  class GATE,WAIT gate
  class AUTO auto
  class CLOSE close
  class FAIL fail
  classDef write fill:#2da44e,stroke:#116329,color:#ffffff
  classDef risk fill:#6639ba,stroke:#3b1f7a,color:#ffffff
  classDef gate fill:#9a6700,stroke:#5c3d00,color:#ffffff
  classDef auto fill:#1f8f6b,stroke:#0d5a42,color:#ffffff
  classDef close fill:#1b7c83,stroke:#0f4a4e,color:#ffffff
  classDef fail fill:#b62324,stroke:#6e0f10,color:#ffffff

Create (servicenow-cr.sh) POSTs a change_request carrying the full pipeline context as u_* custom fields — u_target_cloud, u_deploy_env, u_commit_sha, u_branch, u_services_deployed, u_cluster_namespace, u_security_scan_url, u_platform (and platform-specific IDs for GitLab / GitHub / Azure DevOps) — plus the five narrative fields ServiceNow requires (short description, justification, implementation plan, backout plan, risk & impact, test plan). Reference fields (assignment_group, assigned_to) are resolved from names/emails to sys_ids by servicenow-resolve-refs.sh (robust to renames, retries on transient errors).

Enrich attaches the compliance report (JSON/TXT/optional PDF) and a zipped bundle of all CycloneDX SBOMs to the CR, and posts work notes linking back to the pipeline and the evidence trail.

Close (post-deploy, when: always) moves the CR to Closed with a close_code derived from the deploy outcome, the deployment duration, and an audit work note — so the change lifecycle always completes.

fides-score.sh reads the Evidence Vault trail for the commit and computes a deployment clearance across five axes, written to the CR:

AxisWhat it evaluates
ArtifactIs the pipeline-validation attestation present and compliant?
ScopeEnvironment + cloud + blast radius (dev < qa < prod; internal vs customer-facing)
AttestationStatus of all 8 canonical attestations (SAST, secret, dependency, container, IaC, k8s-manifest, SBOM, pipeline-validation)
TemporalFreshness of the attestations
CodeMerged security-scanner findings (SARIF + GitLab reports)

The result lands on the CR as u_risk_score / u_risk_level (Low → Moderate → High → Critical → HOLD), with the full assessment in u_risk_assessment and the reasoning in u_risk_evidence_chain. A legacy 0–100 scalar drives the auto-approval gate:

  • dev — always auto-approves (fast iteration).
  • qa — auto-approves only if the score is at/under the threshold (default ≤ 5).
  • prodalways manual CAB; never auto-approves.
  • Hard gate: auto-approval is refused if the Evidence Vault trail is not compliant, even when the score would otherwise pass (defense in depth).

This is the decision that makes “compliant changes ship fast, risky ones get a human” automatic and evidence-driven — see approve-deploy-qa and approve-deploy-prod.

What lands in ServiceNow — and what it’s used for

Section titled “What lands in ServiceNow — and what it’s used for”
Artifact in ServiceNowWhat SARC puts thereWhat it’s used for
change_request + u_* fieldsFull per-deploy change record with risk, evidence links, platform metadataCAB review, change calendar, SOC 2 evidence export, native risk routing
AttachmentsCompliance report + zipped SBOMs + attestation evidenceOne-pane audit evidence on the CR
u_fides_artifact / u_fides_test_result / u_fides_vulnerabilityEvidence rows keyed by commit SHA (trail)Native ServiceNow reporting on evidence with no Fides login (#306); e.g. “critical CVEs shipped to prod in 30 days”
cmdb_ci_service + 9 u_* fieldsContainer image, digest, namespace, Helm release, ArgoCD app, pipeline/commit URLsCMDB mapping; trace a CR to the running service
Kubernetes CIs (cmdb_ci_kubernetes_*)Workloads, services, ingress, (pods planned)Deployment-impact views in the standard SN UI
OpenShift CIs (Build → BuildConfig → ImageStreamTag → Route)Walked and pushed on Build-complete (#319)Correlate deployments back to OCP builds + routes for CAB

Because the evidence lives in native ServiceNow tables, the customer can build their own ServiceNow reports, Performance Analytics dashboards, and CAB workflows on top of SARC’s output without any external lookups.

The x_sarc_agent_tools scoped app registers three SARC agent recipes as Now Assist Tools so a ServiceNow AI agent (e.g. “Change Risk Analysis”) can invoke them from the CR without leaving ServiceNow — each calls POST {portal}/api/agents/run with a stored Portal Token:

  • x_sarc.vuln_suggest_fix — propose a dependency bump + open a PR/MR.
  • x_sarc.problem_investigate_fix — investigate a Problem record and propose a fix.
  • x_sarc.right_sizing_apply — apply a right-sizing recommendation.

A read-only MCP server (servicenow_server.py) also exposes ServiceNow + Evidence Vault data (change requests, analytics, risk-score details, trails) to MCP clients. Every agent write stays human-gated — propose → approve → execute.

How the SARC portal reads and uses ServiceNow

Section titled “How the SARC portal reads and uses ServiceNow”

The portal authenticates per tenant (Basic auth from TenantConfig) and applies Layer-2 scoping: every read is filtered to the tenant’s allow-listed cmdb_ci / business-service sys_ids (strict by default, permissive for legacy instances), so one portal safely serves many tenants on shared instances.

flowchart LR
  subgraph IN["ServiceNow data (read)"]
    direction TB
    D1["change_request<br/>(overlapping windows)"]
    D2["task_sla<br/>(14-day trailing)"]
    D3["problem<br/>(reopen_count · closed_at)"]
    D4["cmdb_ci_* · cmdb_rel_ci"]
  end

  subgraph DEC["Decisions SARC makes"]
    direction TB
    C1["CR conflict banner<br/>warn on overlapping change windows"]
    C2["SLA compliance pill<br/>compliancePct + week-over-week delta"]
    C3["Problem regression flag<br/>+ fixed-by-deploy correlation (±60 min)"]
    C4["CR approve / reject<br/>RBAC APPROVER/ADMIN + hash-chained audit"]
    C5["CMDB graph + impact view"]
  end

  D1 --> C1
  D1 --> C4
  D2 --> C2
  D3 --> C3
  D4 --> C5

  class D1,D2,D3,D4 read
  class C1,C2,C3,C4,C5 decision
  classDef read fill:#d29922,stroke:#8a6500,color:#ffffff
  classDef decision fill:#8957e5,stroke:#512a8f,color:#ffffff

What the operator sees, and the decisions behind it:

  • /change-requests — the CR list (scoped, with per-CR Evidence Vault clearance); approve / reject is RBAC-gated (APPROVER or ADMIN) and writes a hash-chained audit log entry, flipping state + approval in ServiceNow.
  • /services/[slug] — a CR-conflict banner (other non-terminal CRs whose change windows overlap this service’s deploy window) and an SLA pill (task_sla over 14 days → compliance % and a week-over-week delta arrow).
  • /problems — a regression flag (reopened within 30 days) and problem-to-deploy correlation (a Problem closed within ±60 min of a DeploymentRecord is tagged “fixed in deploy <sha>”).
  • /cmdb — browse CIs and the relationship graph (relationships fetched in 100-id batches), plus an ADMIN-only CMDB sync that upserts Kubernetes workload CIs via the ServiceNow IRE API.
  • /timeline — a live SSE stream that merges ServiceNow CR events (polled every 15s) with GitLab pipelines, Evidence Vault audits, ArgoCD syncs, and internal deploy records, with a REST snapshot fallback.
  • Auth: HTTP Basic over TLS. Pipeline creds from CI variables; portal creds per-tenant in TenantConfig (encrypted at rest). No long-lived data in URLs.
  • No-op when unconfigured: every write script exits 0 cleanly if SERVICENOW_INSTANCE_URL is unset (local dev, MRs), and most CR jobs are allow_failure: true — a ServiceNow outage never blocks a deploy, because the Evidence Vault remains the source of truth. The approval-poll jobs are the exception (allow_failure: false) — they are real gates.
  • ACLs: the u_fides_* custom tables need an itil-scoped read ACL applied on the instance, or the Table API returns 403; the portal’s integration user carries a role that inherits itil.