Files
git.stella-ops.org/docs/flows/10-cicd-gate-flow.md
StellaOps Bot ca578801fd save progress
2026-01-03 00:49:19 +02:00

16 KiB

CI/CD Gate Flow

Overview

The CI/CD Gate Flow describes how StellaOps integrates into continuous integration and deployment pipelines to provide automated security gates. The flow covers CLI-based scanning, policy evaluation, and pass/fail decisions that control pipeline progression.

Business Value: Shift-left security by catching vulnerabilities before deployment, with deterministic, reproducible verdicts that integrate into existing DevOps workflows.

Actors

Actor Type Role
CI Pipeline System GitHub Actions, GitLab CI, Jenkins, etc.
StellaOps CLI Tool Executes scans from pipeline
Gateway Service API entry point
Scanner Service Performs image analysis
Policy Engine Service Evaluates security policies
Attestor Service Signs scan results

Prerequisites

  • StellaOps CLI installed in CI environment
  • API credentials configured (token or OIDC)
  • Policy set defined for the pipeline
  • Container image built and available

Supported CI/CD Platforms

Platform Integration Method Credentials
GitHub Actions Action + CLI OIDC or PAT
GitLab CI Job template + CLI CI_JOB_TOKEN or PAT
Azure DevOps Task + CLI Service connection
Jenkins Plugin + CLI Credentials binding
CircleCI Orb + CLI Context variables
Tekton Task + CLI Kubernetes secrets

Flow Diagram

┌─────────────────────────────────────────────────────────────────────────────────┐
│                            CI/CD Gate Flow                                       │
└─────────────────────────────────────────────────────────────────────────────────┘

┌────────────┐  ┌───────────┐  ┌─────────┐  ┌─────────┐  ┌────────┐  ┌─────────┐
│ CI Pipeline│  │StellaOps  │  │ Gateway │  │ Scanner │  │ Policy │  │ Attestor│
│            │  │   CLI     │  │         │  │         │  │        │  │         │
└─────┬──────┘  └─────┬─────┘  └────┬────┘  └────┬────┘  └───┬────┘  └────┬────┘
      │               │             │            │           │            │
      │ docker build  │             │            │           │            │
      │───────┐       │             │            │           │            │
      │       │       │             │            │           │            │
      │<──────┘       │             │            │           │            │
      │               │             │            │           │            │
      │ stellaops     │             │            │           │            │
      │ scan          │             │            │           │            │
      │ --policy=prod │             │            │           │            │
      │──────────────>│             │            │           │            │
      │               │             │            │           │            │
      │               │ POST /scans │            │           │            │
      │               │────────────>│            │           │            │
      │               │             │            │           │            │
      │               │             │ Dispatch   │           │            │
      │               │             │───────────>│           │            │
      │               │             │            │           │            │
      │               │             │            │ Analyze   │           │
      │               │             │            │ image     │           │
      │               │             │            │───┐       │           │
      │               │             │            │   │       │           │
      │               │             │            │<──┘       │           │
      │               │             │            │           │            │
      │               │             │            │ Evaluate  │           │
      │               │             │            │──────────>│           │
      │               │             │            │           │            │
      │               │             │            │           │ Apply     │
      │               │             │            │           │ rules     │
      │               │             │            │           │───┐       │
      │               │             │            │           │   │       │
      │               │             │            │           │<──┘       │
      │               │             │            │           │            │
      │               │             │            │ Verdict   │           │
      │               │             │            │<──────────│           │
      │               │             │            │           │            │
      │               │             │            │ Sign      │           │
      │               │             │            │──────────────────────>│
      │               │             │            │           │            │
      │               │             │            │ DSSE      │            │
      │               │             │            │<──────────────────────│
      │               │             │            │           │            │
      │               │             │ Result     │           │            │
      │               │             │<───────────│           │            │
      │               │             │            │           │            │
      │               │ Verdict     │            │           │            │
      │               │<────────────│            │           │            │
      │               │             │            │           │            │
      │ Exit code     │             │            │           │            │
      │ (0=pass,      │             │            │           │            │
      │  1=fail)      │             │            │           │            │
      │<──────────────│             │            │           │            │
      │               │             │            │           │            │
      │ [if pass]     │             │            │           │            │
      │ docker push   │             │            │           │            │
      │───────┐       │             │            │           │            │
      │       │       │             │            │           │            │
      │<──────┘       │             │            │           │            │
      │               │             │            │           │            │

Step-by-Step

1. Pipeline Configuration

GitHub Actions Example

name: Build and Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build-and-scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write  # For OIDC

    steps:
      - uses: actions/checkout@v4

      - name: Build Docker image
        run: |
          docker build -t myapp:${{ github.sha }} .

      - name: Install StellaOps CLI
        run: |
          curl -sSL https://get.stellaops.io/cli | sh
          echo "$HOME/.stellaops/bin" >> $GITHUB_PATH

      - name: Authenticate with OIDC
        run: |
          stellaops auth login --oidc \
            --issuer ${{ secrets.STELLAOPS_OIDC_ISSUER }} \
            --client-id ${{ secrets.STELLAOPS_CLIENT_ID }}

      - name: Scan image
        id: scan
        run: |
          stellaops scan myapp:${{ github.sha }} \
            --policy production \
            --format sarif \
            --output results.sarif \
            --attestation \
            --fail-on violation

      - name: Upload SARIF to GitHub Security
        if: always()
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: results.sarif

      - name: Push to registry
        if: steps.scan.outcome == 'success'
        run: |
          docker tag myapp:${{ github.sha }} ghcr.io/org/myapp:${{ github.sha }}
          docker push ghcr.io/org/myapp:${{ github.sha }}

GitLab CI Example

stages:
  - build
  - scan
  - deploy

variables:
  STELLAOPS_API_URL: https://api.stellaops.local

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

scan:
  stage: scan
  image: stellaops/cli:latest
  script:
    - stellaops auth login --token $STELLAOPS_TOKEN
    - stellaops scan $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
        --policy production
        --fail-on violation
  artifacts:
    reports:
      sast: gl-sast-report.json

deploy:
  stage: deploy
  needs: [scan]
  script:
    - kubectl set image deployment/myapp app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

2. CLI Authentication

The CLI supports multiple authentication methods:

Method Command Use Case
Token stellaops auth login --token $TOKEN CI/CD with secrets
OIDC stellaops auth login --oidc GitHub/GitLab OIDC
Interactive stellaops auth login Local development
Keyless stellaops auth login --keyless Sigstore OIDC

3. Scan Execution

CLI submits scan request and waits for completion:

stellaops scan docker.io/myorg/myapp:v1.2.3 \
  --policy production \
  --format json \
  --output scan-results.json \
  --attestation \
  --timeout 5m \
  --fail-on violation

CLI Options

Option Description Default
--policy Policy set to evaluate against default
--format Output format (json, sarif, table) table
--output Write results to file stdout
--attestation Generate DSSE attestation false
--timeout Maximum wait time 10m
--fail-on Exit 1 on: violation, warning, any violation
--quiet Suppress progress output false

4. Policy Evaluation

Policy engine evaluates findings against CI-specific rules:

# Policy Set: production
version: "stella-dsl@1"
name: production

rules:
  - name: block-critical
    condition: severity == 'critical' AND vex_status != 'not_affected'
    action: FAIL

  - name: block-high-unfixed
    condition: severity == 'high' AND fixed_version == null
    action: FAIL

  - name: block-known-exploited
    condition: kev == true
    action: FAIL

  - name: require-sbom
    condition: sbom_complete == false
    action: FAIL
    message: "SBOM must cover all detected packages"

gates:
  ci:
    max_critical: 0
    max_high_unfixed: 0
    require_attestation: true

5. Verdict and Exit Code

CLI translates verdict to exit code:

Verdict Exit Code Pipeline Result
PASS 0 Continue
WARN 0 (or 1 if --fail-on warning) Continue with warning
FAIL 1 Block deployment
ERROR 2 Pipeline failure

6. SARIF Integration

CLI outputs SARIF for IDE and GitHub integration:

{
  "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
  "version": "2.1.0",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "StellaOps",
          "version": "2.1.0",
          "informationUri": "https://stellaops.io"
        }
      },
      "results": [
        {
          "ruleId": "CVE-2024-1234",
          "level": "error",
          "message": {
            "text": "Critical vulnerability in lodash@4.17.20"
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "package-lock.json"
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

7. Attestation Storage

If --attestation is specified, CLI stores attestation:

# View attestation
stellaops attestation show --scan $SCAN_ID

# Verify attestation
stellaops attestation verify --image myapp:v1.2.3 --policy production

Attestation is stored as DSSE envelope:

{
  "payloadType": "application/vnd.in-toto+json",
  "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEi...",
  "signatures": [
    {
      "keyid": "sha256:abc123...",
      "sig": "MEQCI..."
    }
  ]
}

Gate Behaviors

Soft Gate (Warning Only)

# .stellaops.yaml
gates:
  ci:
    mode: soft  # Report but don't fail
    notify:
      - slack://security-channel

Hard Gate (Blocking)

gates:
  ci:
    mode: hard  # Fail pipeline on violations
    exceptions:
      - CVE-2024-9999  # Known false positive

Progressive Gate

gates:
  ci:
    mode: progressive
    thresholds:
      - branch: main
        max_critical: 0
        max_high: 5
      - branch: develop
        max_critical: 2
        max_high: 20
      - branch: feature/*
        mode: soft  # Warn only on feature branches

Data Contracts

CLI Scan Output Schema

interface CliScanOutput {
  scan_id: string;
  image: string;
  digest: string;
  verdict: 'PASS' | 'WARN' | 'FAIL';
  confidence: number;
  summary: {
    critical: number;
    high: number;
    medium: number;
    low: number;
  };
  violations: Array<{
    cve: string;
    severity: string;
    package: string;
    rule: string;
    message: string;
  }>;
  attestation?: {
    digest: string;
    rekor_log_index?: number;
  };
  timing: {
    queued_ms: number;
    scan_ms: number;
    policy_ms: number;
    total_ms: number;
  };
}

Error Handling

Error Exit Code Recovery
Auth failure 2 Check credentials
Image not found 2 Verify image reference
API timeout 2 Retry with --timeout
Policy not found 2 Check policy name
Network error 2 Check connectivity

Observability

Metrics

Metric Type Labels
cli_scan_total Counter verdict, ci_platform
cli_scan_duration_seconds Histogram ci_platform
cli_gate_blocked_total Counter policy, reason

CI/CD Annotations

GitHub Actions annotations:

::error file=package-lock.json::CVE-2024-1234: Critical vulnerability in lodash@4.17.20
::warning file=Dockerfile::Using outdated base image