Skip to content

Pipelines + integration

SARC runs the same compliance pipeline on three CI platforms — GitLab CI, GitHub Actions, and Azure DevOps — and pushes the resulting evidence into Kosli and the resulting workflow events into ServiceNow.

This page is the conceptual integration map. It is enough to evaluate, design around, or have an architecture conversation about. It is not a copy-paste install guide — the underlying templates carry the secrets, the registry config, and the per-cloud auth wiring, and live in the repository for engagement customers.

Per CI platform, the pipeline has the same six logical stages:

  1. Validate — yaml lint, shell lint, terraform fmt+validate, helm lint+template.
  2. Test + scan — unit tests, SAST, SCA, container scanning, secret scanning, IaC scanning, dependency scanning.
  3. Attest — push every scan + every artefact + every metadata blob to Kosli as attestations on the running trail.
  4. Build + publish — container build + push to the registry (ECR / GHCR / ACR / Artifact Registry).
  5. Approve + deploy — create / update the ServiceNow change request with the 5-axis risk score, wait on CAB if needed, deploy via Helm + ArgoCD.
  6. Post-deploy — Kosli env-snapshot attestation, ServiceNow CR closure, DAST follow-up, notifications.
StageGitLab CI sourceGitHub Actions sourceAzure DevOps source
Validate.gitlab/ci/templates/validate-*.yml.github/workflows/_reusable-validate-*.ymlci/azuredevops/templates/validate-*.yml
Test + scan.gitlab/ci/templates/scan-*.yml + GitLab Security templates.github/workflows/_reusable-scan-*.ymlci/azuredevops/templates/scan-*.yml
Attest.gitlab/ci/templates/kosli-*.yml.github/workflows/_reusable-kosli-*.ymlci/azuredevops/templates/kosli-*.yml
Build + publish.gitlab/ci/templates/build-*.yml.github/workflows/_reusable-build-*.ymlci/azuredevops/templates/build-*.yml
Approve + deploy.gitlab/ci/templates/servicenow-*.yml + deploy-helm.yml.github/workflows/_reusable-servicenow-*.yml + deploy-helm-*.ymlci/azuredevops/templates/servicenow-*.yml + deploy-helm.yml
Post-deploy.gitlab/ci/templates/postsync-*.yml.github/workflows/_reusable-postsync-*.ymlci/azuredevops/templates/postsync-*.yml

GitLab is the source of truth; GitHub Actions and Azure DevOps reach functional parity for the gates that matter (validate, attest, deploy, post-deploy). Some per-platform specifics — GitLab Security scanners vs. GitHub Advanced Security vs. ADO equivalents — differ in implementation but converge to the same attestation shape inside Kosli.

Kosli is the evidence data plane. Each pipeline run is a “trail.” Every scan, build, and deploy is an “attestation” on that trail.

The conceptual flow:

[CI job: scan] [CI job: build] [CI job: deploy]
| | |
| attest:security | attest:artifact | attest:deploy
| (SARIF report) | (container digest) | (env snapshot)
v v v
+--------------------------------------------------------------+
| Kosli trail (per pipeline) |
| policy-aliases -> pullrequest -> artifact -> deploy |
+--------------------------------------------------------------+
|
| sync (via SARC portal CronJob + the karc-portal webhook)
v
SARC portal "Kosli" view + risk score input

Authentication: each CI platform uses a different mechanism, all of them short-lived (no long-lived API keys in the pipeline):

  • GitLab CI — Kosli API token in masked CI variable.
  • GitHub Actions — Kosli API token in encrypted GitHub secret.
  • Azure DevOps — Kosli API token in Azure Key Vault, surfaced via the ADO Library variable group.

The token’s scope is limited to write attestations on the configured flows; it cannot read other tenants’ data or modify Kosli policy.

Example of an attestation invocation (omitted: the full env wiring + the trail-naming convention):

Terminal window
# Container image attestation — happens after build, before push to env
kosli attest artifact "${IMAGE}@${DIGEST}" \
--flow karc-pipeline \
--trail "${CI_COMMIT_SHORT_SHA}" \
--build-url "${CI_JOB_URL}"

The trail-naming + flow-naming convention, and the per-cloud env-name mapping (${TARGET_CLOUD}-karc-${env}), are intentionally not documented in full here — they live in the engagement docs.

ServiceNow is the workflow control plane. CRs, problems, incidents, and the (optional) u_kosli_* custom tables.

Three integration points:

After scans + attestations complete, the pipeline calls a ServiceNow create-CR endpoint with:

  • short description (commit msg + change summary)
  • assignment group (per-service, looked up from the SARC service catalog)
  • planned start/end window (from the change-window calendar sync if configured)
  • attached artefacts: SBOM (CycloneDX), SARIF reports, the Kosli trail URL
  • the 5-axis risk score as a custom field (u_sarc_risk_score)

A second job uploads the bulk attestations to the CR via the ServiceNow attachment API.

The 5-axis score is computed by scripts/ci/kosli-score.sh (in the repo). The math is straightforward but the weights are tunable per-tenant — that part lives in tenant config.

For QA and prod the pipeline blocks on CR approval. Two approval flows:

  • Auto-approve — if all five risk axes are below tenant-configured thresholds. Configurable per-env.
  • Manual — production always; QA when one or more axes exceeds threshold.

The wait is a polling job. Timeout + reschedule logic lives in scripts/ci/servicenow-cr-wait.sh.

After successful deploy:

  • The CR moves to Implemented then Closed via the ServiceNow API.
  • The CMDB (cmdb_ci_service, cmdb_ci_deployment) is updated with the new image digest + the Kosli trail link.
  • For OpenShift tenants, the BuildConfig → Build → ImageStreamTag → Route walk is pushed as separate CIs (see issue 319 in the migration plan).

The OAuth + REST API config on the ServiceNow side is the operator’s responsibility; SARC ships the calling code, not the SN instance setup.

SystemWhat it isHow CI talks to itWhere it shows in the portal
GitLab SecuritySAST, DAST, container, dep, secret scanningGitLab CI templates (built-in artifacts)/vulnerabilities, /scans
Trivy / GrypeContainer vuln scanning (cross-platform)Reusable scan steps on all three CI/vulnerabilities
CheckovIaC scanning (Terraform)Reusable scan steps on all three CI/scans
SonarQube (optional)Code quality + SASTPer-tenant webhook into the portal/scans
Snyk (optional)SCA / containerPer-tenant API key + webhook/vulnerabilities
Wiz (optional)Cloud posturePer-tenant API key + nightly CronJob ingest/scans
GitGuardian (optional)Secret scanningPer-tenant API key + webhook/scans
CycloneDXSBOM formatGenerated in build step, attested to Kosli + attached to CR/sbom
ArgoCDGitOps controllerPipeline updates gitops/ image tag; ArgoCD syncs/argocd, /clusters
KyvernoPolicy gateArgoCD PreSync hook/policies
Tekton (optional)In-cluster pipelinesPer-tenant cluster wiring/tekton
AWS Cost Explorer / Azure Cost Mgmt / GCP BillingCloud costNightly CronJob ingest per cloud/costs, /costs/chargeback
M365 / Google CalendarChange windowsBidirectional sync (CalendarSyncConfig + CalendarEventMapping)/change-windows
GitLab Issues / GitHub Issues / ADO Work ItemsIssue tracking3-way broker (scripts/issue-sync/)/issue-sync
Multi-provider LLM (Anthropic / Azure OpenAI / Bedrock / Vertex / on-prem)AI for AskAI + agent recipesPer-tenant key + provider selection/settings/ai, AskAI popovers
GitLab CI GitHub Actions Azure DevOps
\ | /
\ | /
\ v /
+----> shared compliance gates <----+
|
| per-job: attest -> Kosli flow karc-pipeline
v
+-----------------+
| Kosli | evidence ground truth
+-----------------+
|
| webhook + CronJob
v
+------------------------+
| SARC portal |
| (karc-portal) | composes Kosli + ServiceNow,
| | computes 5-axis risk score,
| | enriches CRs, exports evidence
+------------------------+
/ | \
v v v
ServiceNow ArgoCD AWS / Azure / GCP
(CRs + (deploys (clouds, costs,
CMDB + per cloud) cluster state)
tables)
  • Architecture — the system-shape view that frames why the integration looks like this
  • Multi-cloud parity — how the TARGET_CLOUD switch keeps the same pipeline working on AWS / Azure / GCP / k3d
  • Multi-CI parity — what’s identical and what’s per-platform across GitLab / GitHub / ADO
  • Compliance frameworks — how the resulting evidence rolls up per framework
  • Portal — what an operator actually sees on top of this pipeline