ADR-0004: Keycloak Admin-Plane Access Control and Operator Authorization
Field | Value |
|---|---|
Status | Proposed |
Date | 2026-07-20 |
Author | Alex Henshaw |
Relates to |
|
Context
BlueGuardian is currently a single-operator organisation — Alex is the sole architect, developer, and Keycloak administrator. Today, "admin access control" is trivial by default: there is exactly one human who needs administrative access to the realm. But the platform is designed with future operator hires in mind, and admin-plane access control needs a model ready to expand before the first additional hire arrives, not designed reactively once a second person needs realm access.
This ADR is deliberately narrower than backend ADR-0005 (UMA 2.0 device resources): that ADR governs consent-based access to customer device data. This one governs access to the Keycloak realm and admin plane itself — who can create/modify realm clients, adjust authorization policies, manage users at the platform-operator level, and so on. Conflating the two would be a mistake: a support agent with a scoped device grant should never need or receive any realm-admin capability, and a future platform operator with realm-admin needs should not automatically inherit blanket access to every customer's device data.
FGAP V2 (Fine-Grained Admin Permissions v2) is confirmed as the default authorization model on RHBK 26.6.4. This matters because it means admin-plane permissions can themselves be scoped (e.g. "manage clients in realm X" without "manage users in realm X") rather than operators needing full realm-management roles just to perform one narrow task.
Decision
Edge gating (implemented now): Cloudflare Zero Trust gates the /admin path via a path-scoped Access application. This is an interim, coarse control — it restricts who can reach the admin console network-path at all (currently: Alex only), independent of and prior to any Keycloak-native authorization decision. This closes an immediate exposure gap and is already in place.
Operator authorization model (deferred, gated on first hire): The fine-grained within-Keycloak authorization model for future operators — i.e., which FGAP V2-scoped permission sets a given operator role receives — is explicitly not designed in detail yet. It is gated on the first additional hire, at which point the actual scope of that role (what they need to do day-to-day) will inform the permission set, rather than speculatively designing roles for hypothetical future hires with unknown responsibilities.
Design principles that will govern the eventual model, decided now even though the model itself is deferred:
realm-managementclient roles and UMA 2.0 resource/scope model remain conceptually separate. FGAP V2 scopes administrative capability (what an operator can configure/manage in the realm); UMA (backend ADR-0005) scopes consent-based access to customer device data. An operator role should never implicitly grant UMA-scoped device access, and a UMA grant should never implicitly grant realm-admin capability.No bundled over-grants.
manage-usersand similarly broadrealm-managementroles are avoided in favour of the narrowest FGAP V2-scoped permission set that lets an operator do their actual job. This mirrors the same over-grant avoidance already established for customer-facing access in backend ADR-0005.Edge gating and Keycloak-native authorization are complementary, not substitutes. The Cloudflare Access gate restricts network reachability; FGAP V2 restricts what an authenticated admin can actually do once they reach the console. Both layers are kept even after the operator model is designed — removing the edge gate once fine-grained in-Keycloak permissions exist would be a downgrade, not a simplification.
Alternatives Considered
Design the full operator authorization model now, speculatively. Rejected — with zero additional hires today, any role design would be guesswork about responsibilities that don't exist yet, and would likely need rework once a real hire's actual scope is known. Deferring is the same phased/staged-approach pattern used elsewhere (prove before scaling).
Rely solely on the Cloudflare Zero Trust edge gate, skip Keycloak-native fine-graining entirely. Rejected — edge gating controls reachability, not in-console capability; once a second operator legitimately needs to reach
/admin, coarse "can reach it or not" is no longer sufficient and FGAP V2-scoped permissions become necessary.Give any future operator a full realm-admin role for simplicity. Rejected — directly reintroduces the over-grant problem this ADR (and backend ADR-0005) are structured to avoid; "it's simpler" is not sufficient justification for standing broad access to a system that gates access to all customer device data.
Consequences
No detailed operator role/permission design exists yet — this is accepted as intentional, not a gap, but it does mean this ADR's Decision section will need a follow-up amendment (not a new ADR) once the first hire's actual responsibilities are known.
The edge gate provides real protection today with very low implementation cost, which was worth doing immediately rather than waiting for the full model.
Keeping FGAP V2 (admin-plane) and UMA (customer-data consent) conceptually separate adds a small amount of ongoing discipline — anyone designing a new operator-facing feature must consciously decide which model (if either) it belongs to, rather than reaching for whichever is closest at hand.
Open Items
Full operator role/permission design — explicitly deferred until the first additional hire; owner of this decision is Alex, timing is hire-driven not calendar-driven.
Whether the Cloudflare Access application will need per-operator identity (vs. today's single-identity gate) once there is more than one legitimate admin — likely yes, needs revisiting at the same time as the operator model.
Audit logging requirements for admin-plane actions once multiple operators exist — not yet specified; single-operator today makes this less urgent but it should be designed before the first hire, not after.