Skip to content

Surface Keycloak admin/login events in the EAIStack Audit Log view (read-only) #63

Open

Description

@prometheusgr

Context

Follow-up to #40 (admin user-management surface). #40 ships the minimum bar: docs/USER_MANAGEMENT.md plus a deep link from EAIStack's admin nav to the Keycloak admin console, and turns on Keycloak's own Admin Events and Login Events (Realm Settings → Events in the Keycloak console) so user/role changes and auth events are captured natively, in Keycloak's own store.

That leaves a real but smaller gap: an admin working inside EAIStack's own Audit Log screen (GET /api/settings/audit, issue #45) sees EAIStack's own security-relevant config changes (retention.update, guardrail.config_update, etc.) but nothing from Keycloak's admin/login events — those live in a separate console, under a separate login. Correlating "an admin disabled a user" with "a retention window changed around the same time" requires switching between two UIs.

Why this is polish, not new functionality

No new capability is added — the underlying audit data already exists and is already viewable (in Keycloak's own console, once #40 turns on Admin/Login Events). This issue is purely about where an admin can see it: adding a read-only view inside EAIStack so they don't have to switch consoles. Nothing here changes what is recorded or who can act on it.

Design direction (already scoped during #40's planning)

Two shapes were considered; live proxy is the recommended one — do not build the alternative without revisiting this reasoning:

  • A. Live read-only proxy (recommended): a new admin-gated endpoint calls Keycloak's Admin REST API (GET /admin/realms/{realm}/admin-events and /events) on demand and renders the result in a new tab/section of the existing Audit Log screen. No local storage of Keycloak's events — EAIStack reads, never owns, this data. Requires a Keycloak service-account client role grant (view-events on realm-management — read-only, smaller trust surface than Admin user-management surface (Keycloak integration, no in-app onboarding/offboarding today) #40 avoided by not building the full user-editor) and a repository-free backend service following the existing provider_probe_service.py idiom (outbound httpx call, folded into a result type, no new DB table).
  • B. Ingest/mirror into audit_logs (rejected for now): a poller or Keycloak event-listener webhook copies Keycloak events into EAIStack's own audit_logs table. Rejected because it weakens the single-source-of-truth boundary (a second, potentially stale copy of Keycloak's own record), needs de-dup/backfill/pagination handling, and fails silently (a dead poller leaves an audit gap that's only discovered later — a bad failure mode specifically for an audit trail). Revisit only if a real operational need for a unified single-table view emerges that outweighs these costs.

Scope (if picked up)

  1. Grant eaistack-api's service account the view-events realm-management client role in infra/keycloak/realm-import.json (alongside whatever Admin user-management surface (Keycloak integration, no in-app onboarding/offboarding today) #40 already added there, if anything).
  2. New backend service (no repository, no local table) calling Keycloak's Admin REST API for admin-events and events, admin-gated via require_admin.
  3. New read-only endpoint(s), e.g. GET /api/settings/keycloak-events.
  4. Frontend: a "Keycloak Events" tab/section on the existing Audit Log screen (frontend/src/components/AuditLog.tsx), reusing its existing table/list presentation rather than inventing a new one.
  5. Docs: note in docs/AUDIT_EVENTS.md that this is a read-only view of Keycloak's own event store, not part of the audit_logs table/append-only guarantee.

Non-goals

  • No writes to Keycloak's event store, no acknowledgment/dismissal UI.
  • No mirroring/duplication into audit_logs (see rejected option B above).
  • No filtering/search UI beyond what ships in v1 — add later if needed, same "add query params, not a new repository method" principle as docs/AUDIT_EVENTS.md already states for the existing audit endpoint.

Definition of Done

  • eaistack-api service account has view-events (read-only) granted.
  • New endpoint(s) admin-gated via require_admin, unit-tested against a mocked Keycloak HTTP response.
  • Frontend tab/section added to the Audit Log screen, component-tested.
  • docs/AUDIT_EVENTS.md updated to describe this view and its relationship (or lack of one) to the audit_logs table.
  • Standard merge gate from AGENTS.md's Definition of Done applies in full.
  • RBAC call-out per AGENTS.md's TDD Discipline step 0: this is an admin feature, gated by require_admin, no user-facing surface.

Activity

  1. added
    enhancementNew feature or request
    polishAdmin/UI surfacing or refinement of existing capability, not new functionality
    effort:MMedium: one layer (backend or frontend), a few days
    and removed
    enhancementNew feature or request
    on Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:auth-securityKeycloak, secrets, JWT, timeouts, resilience of external callseffort:MMedium: one layer (backend or frontend), a few dayspolishAdmin/UI surfacing or refinement of existing capability, not new functionalitypriority:P2Valuable, not urgent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions