# 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 ```yaml 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 ```yaml 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: ```bash 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 | ### 3b. AI Code Guard (optional) Run AI code guard checks on a change set and emit CI-friendly output: ```bash stella guard run \ --policy .stellaops.yml \ --format sarif \ --out guard.sarif ``` Recommended exit behavior: - pass: exit 0 - review: exit 0 (with warning in report) - block: exit 1 ### 4. Policy Evaluation Policy engine evaluates findings against CI-specific rules: ```yaml # 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 | ### 5a. DSSE Witness Verification (Required) > Sprint: SPRINT_20260112_004_DOC_cicd_gate_verification Before deploying, pipelines must verify DSSE witness signatures and Rekor inclusion (or offline ledger). This ensures attestation integrity and provides tamper-evident audit trail. #### Online Verification ```bash # Verify DSSE signature and Rekor inclusion stellaops proof verify \ --image ghcr.io/org/myapp:$COMMIT_SHA \ --attestation-type scan-result \ --check-rekor \ --fail-on-missing # Exit codes: # 0 - Verified successfully # 1 - Verification failed # 2 - Missing attestation or Rekor entry ``` #### Offline Verification (Air-Gapped Environments) ```bash # Verify against local offline ledger stellaops proof verify \ --image myapp:$COMMIT_SHA \ --attestation-type scan-result \ --offline \ --ledger-path /var/lib/stellaops/ledger \ --fail-on-missing # Alternative: verify a bundled evidence pack stellaops evidence-pack verify \ --bundle /path/to/evidence-pack.tar.gz \ --check-signatures \ --check-merkle ``` #### Cosign Equivalent Commands For environments using cosign directly: ```bash # Online: verify with Rekor cosign verify-attestation \ --type https://stellaops.io/attestation/scan/v1 \ --rekor-url https://rekor.sigstore.dev \ ghcr.io/org/myapp:$COMMIT_SHA # Offline: verify with bundled certificate cosign verify-attestation \ --type https://stellaops.io/attestation/scan/v1 \ --certificate /path/to/cert.pem \ --certificate-chain /path/to/chain.pem \ --offline \ ghcr.io/org/myapp:$COMMIT_SHA ``` #### GitHub Actions Integration ```yaml - name: Verify attestation run: | stellaops proof verify \ --image ghcr.io/org/myapp:${{ github.sha }} \ --attestation-type scan-result \ --check-rekor \ --fail-on-missing - name: Push to registry (only if verified) if: success() run: | docker push ghcr.io/org/myapp:${{ github.sha }} ``` #### GitLab CI Integration ```yaml verify: stage: verify script: - stellaops proof verify --image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --attestation-type scan-result --check-rekor --fail-on-missing rules: - if: $CI_COMMIT_BRANCH == "main" ``` **Related Documentation:** - [Score Proofs Runbook](../operations/score-proofs-runbook.md) - [Proof Verification Runbook](../operations/proof-verification-runbook.md) ### 6. SARIF Integration CLI outputs SARIF for IDE and GitHub integration: ```json { "$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: ```bash # View attestation stellaops attestation show --scan $SCAN_ID # Verify attestation ``` ### 8. PR/MR Comment and Status Integration StellaOps can post scan results as PR/MR comments and status checks for visibility directly in the SCM platform. #### GitHub PR Integration When scanning PRs, the system can: - Post a summary comment with findings count and severity breakdown - Create check runs with inline annotations - Update commit status with pass/fail verdict ```yaml # GitHub Actions with PR comments - name: Scan with PR feedback run: | stellaops scan myapp:${{ github.sha }} \ --policy production \ --pr-comment \ --check-run \ --github-token ${{ secrets.GITHUB_TOKEN }} ``` Example PR comment format: ```markdown ## StellaOps Scan Results **Verdict:** :warning: WARN | Severity | Count | |----------|-------| | Critical | 0 | | High | 2 | | Medium | 5 | | Low | 12 | ### Findings Requiring Attention | CVE | Severity | Package | Status | |-----|----------|---------|--------| | CVE-2026-1234 | High | lodash@4.17.21 | Fix available: 4.17.22 | | CVE-2026-5678 | High | express@4.18.0 | VEX: Not affected |
View full report [Download SARIF](https://stellaops.example.com/scans/abc123/sarif) [View in Console](https://stellaops.example.com/scans/abc123)
--- *Scan ID: abc123 | Policy: production | [Evidence](https://stellaops.example.com/evidence/abc123)* ``` #### GitLab MR Integration For GitLab Merge Requests: - Post MR notes with findings summary - Update commit status on the pipeline - Create discussion threads for critical findings ```yaml # GitLab CI with MR feedback scan: stage: test script: - stellaops scan $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA \ --policy production \ --mr-comment \ --commit-status \ --gitlab-token $CI_JOB_TOKEN rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" ``` #### Comment Behavior Options | Option | Description | Default | |--------|-------------|---------| | `--pr-comment` / `--mr-comment` | Post summary comment | false | | `--check-run` | Create GitHub check run with annotations | false | | `--commit-status` | Update commit status | false | | `--update-existing` | Edit previous comment instead of new | true | | `--collapse-details` | Use collapsible sections for long output | true | | `--evidence-link` | Include link to evidence bundle | true | #### Evidence Anchoring in Comments Comments include evidence references for auditability: - **Scan ID**: Unique identifier for the scan - **Policy Version**: The policy version used for evaluation - **Attestation Digest**: DSSE envelope digest for signed results - **Rekor Entry**: Log index when transparency logging is enabled #### Error Handling | Scenario | Behavior | |----------|----------| | No SCM token | Skip comment, log warning | | API rate limit | Retry with backoff, then skip | | Comment too long | Truncate with link to full report | | PR already merged | Skip comment | #### Evidence-First Annotation Format PR/MR comments use ASCII-only output for determinism and maximum compatibility: ``` ## StellaOps Security Scan **Verdict:** [BLOCKING] Policy violation detected | Status | Finding | Package | Action | | --- | --- | --- | --- | | [+] New | CVE-2026-1234 | lodash@4.17.21 | Fix: 4.17.22 | | [-] Fixed | CVE-2025-9999 | express@4.17.0 | Resolved | | [^] Upgraded | CVE-2026-5678 | axios@1.0.0 | High -> Medium | | [v] Downgraded | CVE-2026-4321 | react@18.0.0 | Medium -> Low | ### Evidence | Field | Value | | --- | --- | | Attestation Digest | sha256:abc123... | | Policy Verdict | FAIL | | Verify Command | `stellaops verify --digest sha256:abc123...` | --- *[OK] 12 findings unchanged | Policy: production v2.1.0* ``` **ASCII Indicator Reference:** | Indicator | Meaning | |-----------|---------| | `[OK]` | Pass / Success | | `[BLOCKING]` | Fail / Hard gate triggered | | `[WARNING]` | Soft gate / Advisory | | `[+]` | New finding introduced | | `[-]` | Finding fixed / removed | | `[^]` | Severity upgraded | | `[v]` | Severity downgraded | #### Offline Mode In air-gapped environments: - Comments are queued locally - Export comment payload for manual posting - Generate markdown file for offline review stellaops attestation verify --image myapp:v1.2.3 --policy production ``` Attestation is stored as DSSE envelope: ```json { "payloadType": "application/vnd.in-toto+json", "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEi...", "signatures": [ { "keyid": "sha256:abc123...", "sig": "MEQCI..." } ] } ``` ## Gate Behaviors ### Soft Gate (Warning Only) ```yaml # .stellaops.yaml gates: ci: mode: soft # Report but don't fail notify: - slack://security-channel ``` ### Hard Gate (Blocking) ```yaml gates: ci: mode: hard # Fail pipeline on violations exceptions: - CVE-2024-9999 # Known false positive ``` ### Progressive Gate ```yaml 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 ```typescript 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 ``` ## Related Flows - [Scan Submission Flow](02-scan-submission-flow.md) - Underlying scan mechanics - [Policy Evaluation Flow](04-policy-evaluation-flow.md) - Policy rule details - [Binary Delta Attestation Flow](15-binary-delta-attestation-flow.md) - Attestation details