Concelier Authority Audit Runbook

Last updated: 2025-10-22

Audience: Stella Ops operators and SREs responsible for the Concelier ⇆ Authority integration.

This runbook explains how to verify and monitor the Concelier ⇆ Stella Ops Authority integration. It focuses on the /jobs* surface — which requires Authority tokens once enforcement is active — and the audit and metric signals that expose authentication and bypass activity.

1. Prerequisites

Configuration snippet

concelier:
  authority:
    enabled: true
    allowAnonymousFallback: false          # set true only during initial staged rollout
    issuer: "https://authority.internal"
    audiences:
      - "api://concelier"
    requiredScopes:
      - "concelier.jobs.trigger"
      - "advisory:read"
      - "advisory:ingest"
    requiredTenants:
      - "tenant-default"
    bypassNetworks:
      - "127.0.0.1/32"
      - "::1/128"
    clientId: "concelier-jobs"
    clientSecretFile: "/run/secrets/concelier_authority_client"
    tokenClockSkewSeconds: 60
    resilience:
      enableRetries: true
      retryDelays:
        - "00:00:01"
        - "00:00:02"
        - "00:00:05"
      allowOfflineCacheFallback: true
      offlineCacheTolerance: "00:10:00"

Store secrets outside source control. Concelier reads clientSecretFile on startup; rotate by updating the mounted file and restarting the service.

Resilience tuning

2. Key Signals

2.1 Audit log channel

Concelier emits structured audit entries via the Concelier.Authorization.Audit logger for every /jobs* request once Authority enforcement is active.

Concelier authorization audit route=/jobs/definitions status=200 subject=ops@example.com clientId=concelier-cli scopes=concelier.jobs.trigger advisory:ingest bypass=False remote=10.1.4.7
FieldSample valueMeaning
route/jobs/definitionsEndpoint that processed the request.
status200 / 401 / 409Final HTTP status code returned to the caller.
subjectops@example.comUser or service principal subject (falls back to (anonymous) when unauthenticated).
clientIdconcelier-cliOAuth client ID provided by Authority ((none) if the token lacked the claim).
scopesconcelier.jobs.trigger advisory:ingest advisory:readNormalised scope list extracted from token claims; (none) if the token carried none.
tenanttenant-defaultTenant claim extracted from the Authority token ((none) when the token lacked it).
bypassTrue / FalseIndicates whether the request succeeded because its source IP matched a bypass CIDR.
remote10.1.4.7Remote IP recorded from the connection / forwarded header test hooks.

Use your logging backend (e.g., Loki) to index the logger name and filter for suspicious combinations:

2.2 Metrics

Concelier publishes counters under the OTEL meter StellaOps.Concelier.WebService.Jobs. Tags: job.kind, job.trigger, job.outcome.

Metric nameDescriptionPromQL example
web.jobs.triggeredAccepted job trigger requests.sum by (job_kind) (rate(web_jobs_triggered_total[5m]))
web.jobs.trigger.conflictRejected triggers (already running, disabled…).sum(rate(web_jobs_trigger_conflict_total[5m]))
web.jobs.trigger.failedServer-side job failures.sum(rate(web_jobs_trigger_failed_total[5m]))

Prometheus/OTEL collectors typically surface counters with _total suffix. Adjust queries to match your pipeline’s generated metric names.

Correlate audit logs with the following global meter exported via Concelier.SourceDiagnostics:

3. Alerting Guidance

  1. Unauthorized bypass attempt

    • Query: sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", status="401", bypass="True"}[5m])) > 0
    • Action: verify bypassNetworks list; confirm expected maintenance windows; rotate credentials if suspicious.
  2. Missing scopes

    • Query: sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", scopes="(none)", status="200"}[5m])) > 0
    • Action: audit Authority client registration; ensure requiredScopes includes concelier.jobs.trigger, advisory:ingest, and advisory:read.
  3. Trigger failure surge

    • Query: sum(rate(web_jobs_trigger_failed_total[10m])) > 0 with severity warning if sustained for 10 minutes.
    • Action: inspect correlated audit entries and Concelier.Telemetry traces for job execution errors.
  4. Conflict spike

    • Query: sum(rate(web_jobs_trigger_conflict_total[10m])) > 5 (tune threshold).
    • Action: downstream scheduling may be firing repetitive triggers; ensure precedence is configured properly.
  5. Authority offline

    • Watch Concelier.Authorization.Audit logs for status=503 or status=500 along with clientId="(none)". Investigate Authority availability before re-enabling anonymous fallback.

4. Rollout & Verification Procedure

  1. Pre-checks

    • Align with your rollout plan and record the target dates in your change request.
    • Confirm allowAnonymousFallback is false in production; keep true only during staged validation.
    • Validate Authority issuer metadata is reachable from Concelier (curl https://authority.internal/.well-known/openid-configuration from the host).
  2. Smoke test with valid token

    • Authenticate (cached): stella auth login.
    • Mint a scoped token for curl (example):
      • TOKEN="$(stella auth token mint --service-account concelier-jobs --scope concelier.jobs.trigger --scope advisory:ingest --scope advisory:read --tenant tenant-default --reason \"concelier auth smoke test\" --raw)"
    • Trigger a read-only endpoint:
      • curl -H "Authorization: Bearer $TOKEN" -H "X-StellaOps-TenantId: tenant-default" https://concelier.internal/jobs/definitions
    • Expect HTTP 200/202 and an audit log with bypass=False, scopes=concelier.jobs.trigger advisory:ingest advisory:read, and tenant=tenant-default.
  3. Negative test without token

    • Call the same endpoint without a token. Expect HTTP 401, bypass=False.
    • If the request succeeds, double-check bypassNetworks and ensure fallback is disabled.
  4. Bypass check (if applicable)

    • From an allowed maintenance IP, call /jobs/definitions without a token. Confirm the audit log shows bypass=True. Review business justification and expiry date for such entries.
  5. Metrics validation

    • Ensure web.jobs.triggered counter increments during accepted runs.
    • Exporters should show corresponding spans (concelier.job.trigger) if tracing is enabled.

5. Troubleshooting

SymptomProbable causeRemediation
Audit log shows clientId=(none) for all requestsAuthority not issuing client_id claim or CLI outdatedUpdate StellaOps Authority configuration (StellaOpsAuthorityOptions.Token.Claims.ClientId), or upgrade the CLI token acquisition flow.
Requests succeed with bypass=True unexpectedlyLocal network added to bypassNetworks or fallback still enabledRemove/adjust the CIDR list, disable anonymous fallback, restart Concelier.
HTTP 401 with valid tokenrequiredScopes missing from client registration or token audience mismatchVerify Authority client scopes (concelier.jobs.trigger) and ensure the token audience matches audiences config.
Metrics missing from PrometheusTelemetry exporters disabled or filter missing OTEL meterSet concelier.telemetry.enableMetrics=true, ensure collector includes StellaOps.Concelier.WebService.Jobs meter.
Sudden spike in web.jobs.trigger.failedDownstream job failure or Authority timeout mid-requestInspect Concelier job logs, re-run with tracing enabled, validate Authority latency.

6. References