Skip to main content

Overview

Access management in the ODJ is implemented with a central authorization service that uses SpiceDB underneath. SpiceDB is an open-source implementation of Google's Zanzibar paper. The main idea behind Zanzibar is to model permissions based on the resources and relations of the application. Relations that are relevant for authorization are replicated to the authorization database (SpiceDB) and kept up-to-date whenever they change in the application.

Request flow

Users have to obtain a token from MyAPI either via the Authorization Code Flow or the Client Credentials Flow (see Authentication Overview). The ODJ API and the UI are protected with an Envoy sidecar container which validates the token. The token is passed to the corresponding service either via cookie or Authorization header. Each service can then parse the JWT and extract the user identity with the sub claim. That user identity is then used for authorization checks with the Access Management.

Architecture

The Access Management consists of three components:

The Access Management service (AM) guards all access to SpiceDB itself. All other components of the ODJ only talk to the AM, not to SpiceDB directly. This allows us to closely mirror the Architecture Runtime Model (ARM) in the API for the AM and encapsulate the whole permission model in one central place.

Propagating updates

The AM mirrors all the resources and their relationships that are relevant for authorization. If any of these relationships changes, that change needs to be propagated to the AM. In our architecture, this happens via synchronous REST endpoints exposed by the AM. Currently, the following operations need to be synced between the ODJ and the AM:

  • User creation/removal (adding them to the global all role)
  • Team creation
  • Adding/Updating/Removing team members
  • Application creation/deletion
  • Registering deployment workers with applications and the global all role

These syncs should happen synchronously and in a transactional way. If writing to the access management fails, the transaction in the source service should also be rolled back.

Consistency with ZedTokens

By default, SpiceDB caches subproblems for about 5 seconds. This means that access checks can be up to 5 seconds out of date. This leads to some problems in read-after-write scenarios such as team or application creation. SpiceDB returns a so-called ZedToken when relationships are written. ZedTokens are opaque but encode a database revision. By providing a ZedToken in a CHECK request, we can force SpiceDB to only use the cache if it already contains the latest changes. The AM stores the latest ZedToken for a resource in Redis. During CHECKs the latest ZedToken is read from Redis and then provided to SpiceDB with the at_least_as_fresh consistency level. If no ZedToken is stored for a resource, we fall back to minimize_latency, since we are more concerned with latency than with the New Enemy Problem.

Checking permissions