# 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 | ### 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 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