Files
git.stella-ops.org/docs/10_CONCELIER_CLI_QUICKSTART.md
master 7b5bdcf4d3 feat(docs): Add comprehensive documentation for Vexer, Vulnerability Explorer, and Zastava modules
- Introduced AGENTS.md, README.md, TASKS.md, and implementation_plan.md for Vexer, detailing mission, responsibilities, key components, and operational notes.
- Established similar documentation structure for Vulnerability Explorer and Zastava modules, including their respective workflows, integrations, and observability notes.
- Created risk scoring profiles documentation outlining the core workflow, factor model, governance, and deliverables.
- Ensured all modules adhere to the Aggregation-Only Contract and maintain determinism and provenance in outputs.
2025-10-30 00:09:39 +02:00

16 KiB
Raw Blame History

10 · Concelier + CLI Quickstart

This guide walks through configuring the Concelier web service and the stellaops-cli tool so an operator can ingest advisories, merge them, and publish exports from a single workstation. It focuses on deployment-facing surfaces only (configuration, runtime wiring, CLI usage) and leaves connector/internal customization for later.


0 · Prerequisites

  • .NET SDK 10.0.100-preview (matches global.json)
  • MongoDB instance reachable from the host (local Docker or managed)
  • trivy-db binary on PATH for Trivy exports (and oras if publishing to OCI)
  • Plugin assemblies present in StellaOps.Concelier.PluginBinaries/ (already included in the repo)
  • Optional: Docker/Podman runtime if you plan to run scanners locally

Tip

air-gapped installs should preload trivy-db and oras binaries into the runner image since Concelier never fetches them dynamically.


1 · Configure Concelier

  1. Copy the sample config to the expected location (CI/CD pipelines can stamp values into this file during deployment—see the “Deployment automation” note below):

    mkdir -p etc
    cp etc/concelier.yaml.sample etc/concelier.yaml
    
  2. Edit etc/concelier.yaml and update the MongoDB DSN (and optional database name). The default template configures plug-in discovery to look in StellaOps.Concelier.PluginBinaries/ and disables remote telemetry exporters by default.

  3. (Optional) Override settings via environment variables. All keys are prefixed with CONCELIER_. Example:

    export CONCELIER_STORAGE__DSN="mongodb://user:pass@mongo:27017/concelier"
    export CONCELIER_TELEMETRY__ENABLETRACING=false
    
  4. Start the web service from the repository root:

dotnet run --project src/Concelier/StellaOps.Concelier.WebService


 On startup Concelier validates the options, boots MongoDB indexes, loads plug-ins,
 and exposes:

 - `GET /health`  returns service status and telemetry settings
 - `GET /ready`  performs a MongoDB `ping`
 - `GET /jobs` + `POST /jobs/{kind}`  inspect and trigger connector/export jobs

> **Security note**  authentication now ships via StellaOps Authority. Keep
> `authority.allowAnonymousFallback: true` only during the staged rollout and
> disable it before **2025-12-31 UTC** so tokens become mandatory.

Rollout checkpoints for the two Authority toggles:

| Phase | `authority.enabled` | `authority.allowAnonymousFallback` | Goal | Observability focus |
| ----- | ------------------- | ---------------------------------- | ---- | ------------------- |
| **Validation (staging)** | `true` | `true` | Verify token issuance, CLI scopes, and audit log noise without breaking cron jobs. | Watch `Concelier.Authorization.Audit` for `bypass=True` events and scope gaps; confirm CLI `auth status` succeeds. |
| **Cutover rehearsal** | `true` | `false` | Exercise production-style enforcement before the deadline; ensure only approved maintenance ranges remain in `bypassNetworks`. | Expect some HTTP 401s; verify `web.jobs.triggered` metrics flatten for unauthenticated calls and audit logs highlight missing tokens. |
| **Enforced (steady state)** | `true` | `false` | Production baseline after the 2025-12-31 UTC cutoff. | Alert on new `bypass=True` entries and on repeated 401 bursts; correlate with Authority availability dashboards. |

### Authority companion configuration (preview)

1. Copy the Authority sample configuration:

 ```bash
 cp etc/authority.yaml.sample etc/authority.yaml
  1. Update the issuer URL, token lifetimes, and plug-in descriptors to match your environment. Authority expects per-plugin manifests in etc/authority.plugins/; sample standard.yaml and ldap.yaml files are provided as starting points. For air-gapped installs keep the default plug-in binary directory (../StellaOps.Authority.PluginBinaries) so packaged plug-ins load without outbound access.

  2. Environment variables prefixed with STELLAOPS_AUTHORITY_ override individual fields. Example:

    export STELLAOPS_AUTHORITY__ISSUER="https://authority.stella-ops.local"
    export STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0="/srv/authority/plugins"
    

2 · Configure the CLI

The CLI reads configuration from JSON/YAML files and environment variables. The defaults live in src/Cli/StellaOps.Cli/appsettings.json and expect overrides at runtime.

Setting Environment variable Default Purpose
BackendUrl STELLAOPS_BACKEND_URL empty Base URL of the Concelier web service
ApiKey API_KEY empty Reserved for legacy key auth; leave empty when using Authority
ScannerCacheDirectory STELLAOPS_SCANNER_CACHE_DIRECTORY scanners Local cache folder
ResultsDirectory STELLAOPS_RESULTS_DIRECTORY results Where scan outputs are written
Authority.Url STELLAOPS_AUTHORITY_URL empty StellaOps Authority issuer/token endpoint
Authority.ClientId STELLAOPS_AUTHORITY_CLIENT_ID empty Client identifier for the CLI
Authority.ClientSecret STELLAOPS_AUTHORITY_CLIENT_SECRET empty Client secret (omit when using username/password grant)
Authority.Username STELLAOPS_AUTHORITY_USERNAME empty Username for password grant flows
Authority.Password STELLAOPS_AUTHORITY_PASSWORD empty Password for password grant flows
Authority.Scope STELLAOPS_AUTHORITY_SCOPE concelier.jobs.trigger advisory:ingest Space-separated OAuth scopes requested for backend operations
Authority.TokenCacheDirectory STELLAOPS_AUTHORITY_TOKEN_CACHE_DIR ~/.stellaops/tokens Directory that persists cached tokens
Authority.Resilience.EnableRetries STELLAOPS_AUTHORITY_ENABLE_RETRIES true Toggle Polly retry handler for Authority HTTP calls
Authority.Resilience.RetryDelays STELLAOPS_AUTHORITY_RETRY_DELAYS 1s,2s,5s Comma- or space-separated backoff delays (hh:mm:ss)
Authority.Resilience.AllowOfflineCacheFallback STELLAOPS_AUTHORITY_ALLOW_OFFLINE_CACHE_FALLBACK true Allow CLI to reuse cached discovery/JWKS metadata when Authority is offline
Authority.Resilience.OfflineCacheTolerance STELLAOPS_AUTHORITY_OFFLINE_CACHE_TOLERANCE 00:10:00 Additional tolerance window applied to cached metadata

Example bootstrap:

export STELLAOPS_BACKEND_URL="http://localhost:5000"
export STELLAOPS_RESULTS_DIRECTORY="$HOME/.stellaops/results"
export STELLAOPS_AUTHORITY_URL="https://authority.local"
export STELLAOPS_AUTHORITY_CLIENT_ID="concelier-cli"
export STELLAOPS_AUTHORITY_CLIENT_SECRET="s3cr3t"
export STELLAOPS_AUTHORITY_SCOPE="concelier.jobs.trigger advisory:ingest advisory:read"
dotnet run --project src/Cli/StellaOps.Cli -- db merge

# Acquire a bearer token and confirm cache state
dotnet run --project src/Cli/StellaOps.Cli -- auth login
dotnet run --project src/Cli/StellaOps.Cli -- auth status
dotnet run --project src/Cli/StellaOps.Cli -- auth whoami

Refer to docs/dev/32_AUTH_CLIENT_GUIDE.md for deeper guidance on tuning retry/offline settings and rollout checklists.

To persist configuration, you can create stellaops-cli.yaml next to the binary or rely on environment variables for ephemeral runners.


3 · Operating Workflow

  1. Trigger connector fetch stages

    dotnet run --project src/Cli/StellaOps.Cli -- db fetch --source osv --stage fetch
    dotnet run --project src/Cli/StellaOps.Cli -- db fetch --source osv --stage parse
    dotnet run --project src/Cli/StellaOps.Cli -- db fetch --source osv --stage map
    

    Use --mode resume when continuing from a previous window:

    dotnet run --project src/Cli/StellaOps.Cli -- db fetch --source redhat --stage fetch --mode resume
    
  2. Merge canonical advisories

    dotnet run --project src/Cli/StellaOps.Cli -- db merge
    
  3. Produce exports

    # JSON tree (vuln-list style)
    dotnet run --project src/Cli/StellaOps.Cli -- db export --format json
    
    # Trivy DB (delta example)
    

dotnet run --project src/Cli/StellaOps.Cli -- db export --format trivy-db --delta


  Concelier always produces a deterministic OCI layout. The first run after a clean
  bootstrap emits a **full** baseline; subsequent `--delta` runs reuse the previous
  baselines blobs when only JSON manifests change. If the exporter detects that a
  prior delta is still active (i.e., `LastDeltaDigest` is recorded) it automatically
  upgrades the next run to a full export and resets the baseline so operators never
  chain deltas indefinitely. The CLI exposes `--publish-full/--publish-delta` (for
  ORAS pushes) and `--include-full/--include-delta` (for offline bundles) should you
  need to override the defaults interactively.

  **Smoke-check delta reuse:** after the first baseline completes, run the export a
  second time with `--delta` and verify that the new directory reports `mode=delta`
  while reusing the previous layer blob.

  ```bash
  export_root=${CONCELIER_EXPORT_ROOT:-exports/trivy}
  base=$(ls -1d "$export_root"/* | sort | tail -n2 | head -n1)
  delta=$(ls -1d "$export_root"/* | sort | tail -n1)

  jq -r '.mode,.baseExportId' "$delta/metadata.json"

base_manifest=$(jq -r '.manifests[0].digest' "$base/index.json")
delta_manifest=$(jq -r '.manifests[0].digest' "$delta/index.json")
printf 'baseline manifest: %s\ndelta manifest:    %s\n' "$base_manifest" "$delta_manifest"

layer_digest=$(jq -r '.layers[0].digest' "$base/blobs/sha256/${base_manifest#sha256:}")
cmp "$base/blobs/sha256/${layer_digest#sha256:}" \
    "$delta/blobs/sha256/${layer_digest#sha256:}"

cmp returning exit code 0 confirms the delta export reuses the baselines db.tar.gz layer instead of rebuilding it.

  1. Verify guard compliance

    export STELLA_TENANT="${STELLA_TENANT:-tenant-a}"
    
    dotnet run --project src/Cli/StellaOps.Cli -- aoc verify \
      --since 24h \
      --format table \
      --tenant "$STELLA_TENANT"
    
    # Optional: capture JSON evidence for pipelines/audits
    dotnet run --project src/Cli/StellaOps.Cli -- aoc verify \
      --since 7d \
      --limit 100 \
      --format json \
      --export artifacts/aoc-verify.json \
      --tenant "$STELLA_TENANT"
    

    The CLI exits with 0 when no violations are detected. Guard failures map to ERR_AOC_00x codes (11…17), while truncated results return 18. Use --sources/--codes to focus on noisy connectors and feed the exported JSON into dashboards or evidence lockers for compliance reviews.

  2. Pre-flight individual payloads

    stella sources ingest --dry-run \
      --source redhat \
      --input ./fixtures/redhat/RHSA-2025-9999.json \
      --tenant "$STELLA_TENANT" \
      --format json \
      --output artifacts/redhat-dry-run.json
    

    Exit code 0 confirms the candidate document is AOC compliant. Any guard violation is emitted as deterministic ERR_AOC_00x exit codes (11…17); reuse the exported JSON in PRs or incident timelines to show offending paths.

  3. Manage scanners (optional)

    dotnet run --project src/Cli/StellaOps.Cli -- scanner download --channel stable
    dotnet run --project src/Cli/StellaOps.Cli -- scan run --entry scanners/latest/Scanner.dll --target ./sboms
    dotnet run --project src/Cli/StellaOps.Cli -- scan upload --file results/scan-001.json
    

Add --verbose to any command for structured console logs. All commands honour Ctrl+C cancellation and exit with non-zero status codes when the backend returns a problem document.


4 · Verification Checklist

  • Concelier /health returns "status":"healthy" and Storage bootstrap is marked complete after startup.
  • CLI commands return HTTP 202 with a Location header (job tracking URL) when triggering Concelier jobs.
  • Export artefacts are materialised under the configured output directories and their manifests record digests.
  • MongoDB contains the expected document, dto, advisory, and export_state collections after a run.

5 · Deployment Automation

  • Treat etc/concelier.yaml.sample as the canonical template. CI/CD should copy it to the deployment artifact and replace placeholders (DSN, telemetry endpoints, cron overrides) with environment-specific secrets.
  • Keep secret material (Mongo credentials, OTLP tokens) outside of the repository; inject them via secret stores or pipeline variables at stamp time.
  • When building container images, include trivy-db (and oras if used) so air-gapped clusters do not need outbound downloads at runtime.

5 · Next Steps

  • Enable authority-backed authentication in non-production first. Set authority.enabled: true while keeping authority.allowAnonymousFallback: true to observe logs, then flip it to false before 2025-12-31 UTC to enforce tokens.
  • Automate the workflow above via CI/CD (compose stack or Kubernetes CronJobs).
  • Pair with the Concelier connector teams when enabling additional sources so their module-specific requirements are pulled in safely.

6 · Authority Integration

  • Concelier now authenticates callers through StellaOps Authority using OAuth 2.0 resource server flows. Populate the authority block in concelier.yaml:

    authority:
      enabled: true
      allowAnonymousFallback: false         # keep true only during the staged rollout window
      issuer: "https://authority.example.org"
      audiences:
        - "api://concelier"
      requiredScopes:
        - "concelier.jobs.trigger"
        - "advisory:read"
        - "advisory:ingest"
      requiredTenants:
        - "tenant-default"
      clientId: "concelier-jobs"
      clientSecretFile: "../secrets/concelier-jobs.secret"
      clientScopes:
        - "concelier.jobs.trigger"
        - "advisory:read"
        - "advisory:ingest"
      bypassNetworks:
        - "127.0.0.1/32"
        - "::1/128"
    
  • Store the client secret outside of source control. Either provide it via authority.clientSecret (environment variable CONCELIER_AUTHORITY__CLIENTSECRET) or point authority.clientSecretFile to a file mounted at runtime.

  • Cron jobs running on the same host can keep using the API thanks to the loopback bypass mask. Add additional CIDR ranges as needed; every bypass is logged.

  • Export the same configuration to Kubernetes or systemd by setting environment variables such as:

    export CONCELIER_AUTHORITY__ENABLED=true
    export CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=false
    export CONCELIER_AUTHORITY__ISSUER="https://authority.example.org"
    export CONCELIER_AUTHORITY__CLIENTID="concelier-jobs"
    export CONCELIER_AUTHORITY__CLIENTSECRETFILE="/var/run/secrets/concelier/authority-client"
    export CONCELIER_AUTHORITY__REQUIREDSCOPES__0="concelier.jobs.trigger"
    export CONCELIER_AUTHORITY__REQUIREDSCOPES__1="advisory:read"
    export CONCELIER_AUTHORITY__REQUIREDSCOPES__2="advisory:ingest"
    export CONCELIER_AUTHORITY__CLIENTSCOPES__0="concelier.jobs.trigger"
    export CONCELIER_AUTHORITY__CLIENTSCOPES__1="advisory:read"
    export CONCELIER_AUTHORITY__CLIENTSCOPES__2="advisory:ingest"
    export CONCELIER_AUTHORITY__REQUIREDTENANTS__0="tenant-default"
    
  • CLI commands already pass Authorization headers when credentials are supplied. Configure the CLI with matching Authority settings (docs/09_API_CLI_REFERENCE.md) so that automation can obtain tokens with the same client credentials. Concelier logs every job request with the client ID, subject (if present), scopes, and a bypass flag so operators can audit cron traffic.

  • Rollout checklist.

    1. Stage the integration with fallback enabled (allowAnonymousFallback=true) and confirm CLI/token issuance using stella auth status.
    2. Follow the rehearsal pattern (allowAnonymousFallback=false) while monitoring Concelier.Authorization.Audit and web.jobs.triggered/web.jobs.trigger.failed metrics.
    3. Lock in enforcement, review the audit runbook (docs/modules/concelier/operations/authority-audit-runbook.md), and document the bypass CIDR approvals in your change log.