checkId: check.security.authority-signing-key plugin: stellaops.doctor.security severity: fail tags: [security, auth, keys, jwks]
Authority Signing Key (JWKS)
This Doctor check verifies that the Authority service publishes at least one usable, non-expired token-signing key via its JWKS endpoint. If Authority’s signing-key source is unavailable, JWT issuance fails and OpenIddict is disabled, breaking all downstream authentication platform-wide — so this is a platform-wide blast-radius check.
It is a live, out-of-process probe. It replaces the dead, fully-simulated check.auth.signing-key (in the unwired StellaOps.Doctor.Plugin.Auth), whose CheckSigningKeyAsync returned a hardcoded ActiveKeyId = "key-2024-01-15" and always passed — a dangerous false-green. That dead plugin is a separate dead-plugin/wiring cleanup item (DOC-TRUTH-004); this check supersedes the concept with a real probe and does not revive the dead plugin.
What It Checks
Resolves the Authority issuer from the canonical manifest entry integration.identity.authority-signing-key — config keys Authority:Issuer / Authority:Url / StellaOps:AuthorityUrl / Oidc:Issuer (AUTHORITY_ISSUER is the env form). It then:
- Fetches the OIDC discovery document (
<issuer>/.well-known/openid-configuration) and readsjwks_uri(falling back to well-known JWKS paths/.well-known/jwks.json,/.well-known/jwks,/jwkswhen discovery omits it). - GETs the JWKS and inspects each key’s public parameters: a key counts as a usable signing key when it has a recognized
kty(RSA/EC/OKP/oct), is not markeduse=enc, and — if it carries anx5ccertificate chain — the leaf certificate is within its validity window.
| Condition | Result |
|---|---|
| Issuer not configured | skip |
Discovery has no jwks_uri and no fallback JWKS path responds | fail |
| JWKS endpoint unreachable / non-2xx | fail |
| JWKS is empty or no published key is usable for signing | fail |
| Every signing-key certificate is expired | fail |
| At least one usable signing key, some present keys carry expired certs | warn |
| At least one usable, non-expired signing key | pass |
Air-gap/on-prem safe: it talks only to the configured (local) Authority — no external network, no cloud-managed KMS, no key generation/rotation. A JWKS publishes only public key parameters; private key material is never read or emitted. Certificate chains are inspected for expiry only.
Why It Matters
The Authority signing key signs every JWT the platform issues. If its source is unavailable or empty, no tokens can be issued and authentication stops platform-wide. The only other real signing probe today targets the Attestor — not Authority — so without this check an Authority signing-key outage was invisible to Doctor.
Common Causes
- Authority is down or its signing-key source (
Authority:Signing:KeySource/KeyPath/ActiveKeyId) is unavailable - All signing keys have expired without rotation
- The Authority issuer URL is incorrect, so discovery / JWKS cannot be located
- Authority is misconfigured and not serving OIDC metadata
How to Fix
Never auto-generate or auto-rotate Authority signing keys from Doctor. Repair the key source, then restart Authority to converge.
Docker Compose
# Inspect what Authority publishes
curl -fsS https://authority.stella-ops.local/.well-known/openid-configuration
curl -fsS "$(curl -fsS https://authority.stella-ops.local/.well-known/openid-configuration | python -c 'import sys,json;print(json.load(sys.stdin)["jwks_uri"])')"
# Repair the signing key source (on-prem / Vault only — no cloud-managed KMS default),
# then restart Authority to reload it:
docker compose -f devops/compose/docker-compose.stella-ops.yml restart authority
docker compose -f devops/compose/docker-compose.stella-ops.yml logs --tail 100 authority
Bare Metal / systemd
# Confirm Authority:Signing:KeySource / KeyPath / ActiveKeyId resolve to a loadable, non-expired key
# (e.g. /etc/stellaops/authority.appsettings.json), then:
systemctl restart stellaops-authority
journalctl -u stellaops-authority --no-pager -n 100
Kubernetes / Helm
kubectl get pods -n stellaops -l app=stellaops-authority
# Repair the signing-key Secret / Vault reference, then roll Authority:
kubectl rollout restart deploy/stellaops-authority -n stellaops
Verification
stella doctor run --check check.security.authority-signing-key
Related Checks
check.platform.identity-envelope— the gateway↔service identity-envelope HMAC key (a different signing dependency)check.security.jwt.config— JWT signing/validation configurationcheck.integration.oidc— external OIDC provider discovery (this check applies the same discovery pattern to the first-party Authority)check.auth.signing-key— the legacy, dead/simulated signing-key check this probe supersedes (deferred dead-plugin cleanup, DOC-TRUTH-004)
