Skip to content

bug(secrets): C1 blocked — SLM cannot authenticate to System-vault /system routes (#10436 HMAC service-auth vs SLM X-Internal-API-Key, no signer) #10492

Closed

Description

@mrveiss

Summary

Phase C1 (#10153) — migrate SLM SSO client secrets into autobot-backend's unified-secrets System vault — is blocked by an authentication-scheme mismatch in the System-vault service path delivered by #10436 (merged in PR #10478).

The /api/v2/secrets/system/* routes authenticate the caller via service_principal → validate_service_auth, which requires HMAC X-Service-ID / X-Service-Signature / X-Service-Timestamp headers signed with a per-service key stored in Redis (service:key:{service_id}).

The SLM (autobot-slm-backend) — the intended non-user caller — has no HMAC service-auth signer. Its only cross-backend credential is the shared X-Internal-API-Key (AUTOBOT_INTERNAL_API_KEY, validated in autobot-backend/auth_middleware.py:819 and api/auth.py:702, sent by autobot-slm-backend/api/voice_proxy.py). There is no provisioned service:key:slm-backend and no code path that signs X-Service-* requests.

Net: #10436's "System vault for non-user callers" path is, as merged, not callable by the SLM — defeating its stated purpose ("SLM=system/no-user can't call → needs System-vault service-auth path").

Evidence

  • Backend endpoints + auth: autobot-backend/api/unified_secrets.py (service_principal, /system routes) → autobot-backend/security/service_auth.py:validate_service_auth (X-Service-* HMAC, Redis service:key:{id}).
  • SLM has no signer: grep -rn "X-Service-(ID|Signature)|validate_service_auth" autobot-slm-backend/ → only a doc-string mention in models/manifest.py.
  • SLM's actual credential: autobot-slm-backend/api/voice_proxy.py (X-Internal-API-Key: AUTOBOT_INTERNAL_API_KEY).

Why this is the §4.1 surface

The enterprise-SSO design (docs/superpowers/specs/2026-06-15-enterprise-sso-federation-design.md §4.1) explicitly flags the cross-backend boundary as a Phase C prerequisite to settle with the #10088 owner before C1. #10436 picked HMAC service-auth without wiring an SLM-side signer or deploy-time key provisioning, so the surface is still unsettled.

Resolution options (owner decision)

  • Option A — accept X-Internal-API-Key on the /system routes. Map the existing shared key to a synthetic service_id (e.g. slm-backend). Reuses already-provisioned credentials (zero deploy change), minimal surface. Trade-off: one shared key, coarser than per-service HMAC + replay protection.
  • Option B — give the SLM an HMAC service-auth signer + provision service:key:slm-backend. Per-service key, 5-min replay window, more granular. Trade-off: new SLM signing client + deploy-time key provisioning (Redis + role manifest), larger surface.

Acceptance

Activity

  1. mrveiss commented on Jun 26, 2026

    @mrveiss
    OwnerAuthor

    Update — surface is smaller than first assessed; resolution = Option B (per-service HMAC), foundation mostly exists

    The HMAC service-auth infra is already shared and tested — no new crypto and no new auth scheme are needed:

    • Shared signer already exists: autobot_shared/http_client.py:sign_request(service_id, service_key, method, path, timestamp) produces exactly the X-Service-ID/Signature/Timestamp headers that autobot-backend/security/service_auth.py:ServiceAuthManager.validate_signature checks. Pure, no-I/O, importable from the SLM.
    • Key provisioning already exists: autobot-infrastructure/shared/scripts/generate_service_keys.py mints service:key:{id} into Redis; export_service_keys.py exports per-service .env files for Ansible; a service loads its own key via SERVICE_KEY env → config.service_key (ssot_config.py:1546).

    Precise remaining gaps (all additive):

    1. slm-backend is absent from the SERVICES lists in generate_service_keys.py and export_service_keys.py → add it so its key is minted + exported.
    2. No SLM-side client calls the /api/v2/secrets/system/* routes → add autobot-slm-backend/services/secrets_vault_client.py that signs with the shared sign_request using service_id="slm-backend" + config.service_key, base URL AUTOBOT_BACKEND_URL.
    3. Deploy: distribute the minted key to the SLM .env via the existing export mechanism.

    Resolution is folded into C1 (#10153): the vault client is wired into SSOSecretsManager behind a default-off backend selector with backward-compatible local reads, so existing deployments are unchanged until the key is provisioned. Closing criteria unchanged (round-trip proof that an SLM-signed request passes validate_signature and reaches a /system route).

  2. github-actions commented on Jun 26, 2026

    @github-actions
    Contributor

    PR #10498 (merged to Dev_new_gui) references this issue with a close keyword.

    feat(sso): migrate SSO secrets to unified vault + rotation (#10153, #10154)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  3. github-actions commented on Jun 27, 2026

    @github-actions
    Contributor

    PR #10558 (merged to Dev_new_gui) references this issue with a close keyword.

    fix(secrets): accept X-Internal-API-Key on System-vault routes (Option A) + SLM LLM key→vault (#10492, #10503)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  4. mrveiss commented on Jun 27, 2026

    @mrveiss
    OwnerAuthor

    Merged to Dev_new_gui (1040d6490, PR #10558). Option A implemented: backend service_principal accepts the shared X-Internal-API-Key (→ synthetic service_id=slm-backend, System-vault scoping preserved); SLM unified_vault_client sends it + is_configured() gates on AUTOBOT_INTERNAL_API_KEY. Documented in design spec §4.1. Unblocks #10153/#10154. Batch #10440.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions