At the company I work for; we're planning a custom entitlement service (using Open Policy Agent as the policy engine) for fine-grained authZ decisioning.
The high-level architecture looks like the following:
Basically entitlements-enabled microservices pass identity (JWT subject), operation (GET/POST/PUT/PATCH/DELETE), and resource (/thing/12345
) to the entitlement service to get an authZ decision. The decision is just an boolean allow/deny response. Entitlements persists information about users, groups and roles (that it receives asynchronously from IDP and other systems), so it is able to look up this information from it's local data source and pass it through to OPA (using the overloaded input pattern). Entitlements/OPA is just running as a stand-alone service - we're not running OPA as a side-car or anything fancy like that...
The problem we're trying to solve is that for most routes the resource-owner is not part of the resource path, but we still need the resource-owner to be able to make an authZ decision.
I can think of 3 ways to get the resource owner through to entitlements. I'm looking to get some advice about what would be the best approach.
- Include resource owner information in all resource paths e.g.
/user/{id}/thing/12345
. TBH not sure how viable this approach would be in our ecosystem, so this would probably be my lowest preference. - Entitlements-enabled services need to look up the resource-owner (for a given resource) and pass this through to entitlements (along with identity, operation, and resource).
- Sync resource-identifiers (mapped to resource owners) through to entitlements as resources are created, so that entitlements-enabled services can subsequently just pass identity, operation, and resource to get authZ decision.
This usually boils down to requirements around memory consumption and the frequency of which the data is expected to change. To try and summarize:
Lookup of permission data with request or in-policy
Pros:
Cons:
Keeping permission data in memory
Pros:
Cons: