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.
The three-platform shape
Section titled “The three-platform shape”Per CI platform, the pipeline has the same six logical stages:
- Validate — yaml lint, shell lint, terraform fmt+validate, helm lint+template.
- Test + scan — unit tests, SAST, SCA, container scanning, secret scanning, IaC scanning, dependency scanning.
- Attest — push every scan + every artefact + every metadata blob to Kosli as attestations on the running trail.
- Build + publish — container build + push to the registry (ECR / GHCR / ACR / Artifact Registry).
- Approve + deploy — create / update the ServiceNow change request with the 5-axis risk score, wait on CAB if needed, deploy via Helm + ArgoCD.
- Post-deploy — Kosli env-snapshot attestation, ServiceNow CR closure, DAST follow-up, notifications.
| Stage | GitLab CI source | GitHub Actions source | Azure DevOps source |
|---|---|---|---|
| Validate | .gitlab/ci/templates/validate-*.yml | .github/workflows/_reusable-validate-*.yml | ci/azuredevops/templates/validate-*.yml |
| Test + scan | .gitlab/ci/templates/scan-*.yml + GitLab Security templates | .github/workflows/_reusable-scan-*.yml | ci/azuredevops/templates/scan-*.yml |
| Attest | .gitlab/ci/templates/kosli-*.yml | .github/workflows/_reusable-kosli-*.yml | ci/azuredevops/templates/kosli-*.yml |
| Build + publish | .gitlab/ci/templates/build-*.yml | .github/workflows/_reusable-build-*.yml | ci/azuredevops/templates/build-*.yml |
| Approve + deploy | .gitlab/ci/templates/servicenow-*.yml + deploy-helm.yml | .github/workflows/_reusable-servicenow-*.yml + deploy-helm-*.yml | ci/azuredevops/templates/servicenow-*.yml + deploy-helm.yml |
| Post-deploy | .gitlab/ci/templates/postsync-*.yml | .github/workflows/_reusable-postsync-*.yml | ci/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.
How CI talks to Kosli
Section titled “How CI talks to 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 inputAuthentication: 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):
# Container image attestation — happens after build, before push to envkosli 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.
How CI talks to ServiceNow
Section titled “How CI talks to ServiceNow”ServiceNow is the workflow control plane. CRs, problems, incidents, and the (optional) u_kosli_* custom tables.
Three integration points:
1. Create the CR + enrich it
Section titled “1. Create the CR + enrich it”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.
2. Wait on approval
Section titled “2. Wait on approval”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.
3. Close the CR + push CMDB
Section titled “3. Close the CR + push CMDB”After successful deploy:
- The CR moves to
ImplementedthenClosedvia 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.
How the rest of the systems plug in
Section titled “How the rest of the systems plug in”| System | What it is | How CI talks to it | Where it shows in the portal |
|---|---|---|---|
| GitLab Security | SAST, DAST, container, dep, secret scanning | GitLab CI templates (built-in artifacts) | /vulnerabilities, /scans |
| Trivy / Grype | Container vuln scanning (cross-platform) | Reusable scan steps on all three CI | /vulnerabilities |
| Checkov | IaC scanning (Terraform) | Reusable scan steps on all three CI | /scans |
| SonarQube (optional) | Code quality + SAST | Per-tenant webhook into the portal | /scans |
| Snyk (optional) | SCA / container | Per-tenant API key + webhook | /vulnerabilities |
| Wiz (optional) | Cloud posture | Per-tenant API key + nightly CronJob ingest | /scans |
| GitGuardian (optional) | Secret scanning | Per-tenant API key + webhook | /scans |
| CycloneDX | SBOM format | Generated in build step, attested to Kosli + attached to CR | /sbom |
| ArgoCD | GitOps controller | Pipeline updates gitops/ image tag; ArgoCD syncs | /argocd, /clusters |
| Kyverno | Policy gate | ArgoCD PreSync hook | /policies |
| Tekton (optional) | In-cluster pipelines | Per-tenant cluster wiring | /tekton |
| AWS Cost Explorer / Azure Cost Mgmt / GCP Billing | Cloud cost | Nightly CronJob ingest per cloud | /costs, /costs/chargeback |
| M365 / Google Calendar | Change windows | Bidirectional sync (CalendarSyncConfig + CalendarEventMapping) | /change-windows |
| GitLab Issues / GitHub Issues / ADO Work Items | Issue tracking | 3-way broker (scripts/issue-sync/) | /issue-sync |
| Multi-provider LLM (Anthropic / Azure OpenAI / Bedrock / Vertex / on-prem) | AI for AskAI + agent recipes | Per-tenant key + provider selection | /settings/ai, AskAI popovers |
The glue, in one diagram
Section titled “The glue, in one diagram” 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)Where to go next
Section titled “Where to go next”- Architecture — the system-shape view that frames why the integration looks like this
- Multi-cloud parity — how the
TARGET_CLOUDswitch 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