Keycloak and OPA integration

I am interested in using Keycloak in a cloud native solution. In particular to create users for my applications. For authorization, I have decided on OPA (Open Policy Agent), and I wanted to know what support Keycloak might have for this? OPA needs to fetch a bundle that contains configuration for authorizations. OPA is configured in the Ingress Gateway (Istio Ingress Gateway) of my application and also in the envoy sidecars of the service mesh. It has no storage of its own but pulls or policies can be pushed to the OPA service. https://www.openpolicyagent.org/docs/v0.12.2/bundles/

3 Likes

We don’t have any direct integration with OPA. Although, that might be an interesting idea.

Keycloak acts both as a PIP (policy information) and a PDP (policy decision). Then the PEP (policy enforcement) happens in the client side, but we are also planning support in Keycloak Gatekeeper for this.

It may be possible to use Keycloak purely as a PIP for OPA, but not sure how that would look like.

Another option is I pressume OPA would be able to use claims from within access tokens issued by Keycloak in order to enforce policies defined within OPA.

1 Like

Could you provide more details on what you need in the bundle ? What information from Keycloak you expected to feed OPA ?

Could you provide more details on how your OPA policies look like ?

Which access control methods are you using (rbac, gbac, abac, contextual, etc) ?

Are you basically protecting your API resources (or also using for or also using OPA for data filtering ?

This could be an amazing step for Keycloak, IMHO. Relying on OPA for the enforcing of the authorization policies could drive to less scalability issues for Keycloak (distributed enforcing vs centralized). In our company we were evaluating both technologies (OPA and Keycloak) and we’ve chosen Keycloak due to:

  1. Scalability requirements were covered already by Keycloak (for now)
  2. Not enough time to create a “policy server” as complete as Keycloak authorization services

But in future we’ll see what to do, especially if our scalability needs will become very big…

I have thought about having a distributed enforcing approach, but a Keycloak specific approach, not integrating with OPA. Basically, it would use the authz services engine bits, and cache information from Keycloak. That way it can be scaled independently of Keycloak server itself, and maybe even co-located with apps themselves (as a side-container).

Does the KC java adapter already performs some caching of authorization policies? There should be some flag/options in the realm config file i think…

Here is some information one the bundles:

So a typical environment would be a service mesh based on Envoy. I dont believe that OPA has a datastore at the moment. So the policy information must be pulled from a URL or can be pushed to OPA. Since I already intend to run Keycloak in a secure manner so this was the first level of integration that I was looking for. There are probably some other scenarios too.

Here is the scenario. In addition to this each service runs an Envoy Sidecar. These also are calling to the OPA service:

For main Istio/Envoy gateway

But for individual services the standard envoy integration is used from the envoy sidecar of the service:

Here is another article that describes scenario:https://medium.com/@KevinHoffman/securing-microservices-with-open-policy-agent-fcf04d982b4a

One of the improvements we can do in addition to integrating with OPA is to allow adapters to periodically pool policies from the server and cache them. That would mean bring the evaluation engine close to the adapter and making decisions locally. Other improvements we have in our backlog is cache of decisions (server and client side) and optimizations in regards to JS execution (if using GraalVM)

However, one of the main points of using Keycloak is the fact that we are token-based. You don’t actually need to evaluate and enforce permissions all the time, neither query the server on every single request. Depending on how your clients work, you can incrementally obtain permissions from the server where evaluation will be based on the permissions granted and carried by the token.

1 Like

Something to consider …

Does Keycloak currently have a way to provide a URL that serves json formatted data which I think is the format for OPA. And could we upload json data to Keycloak? or enter it using an existing IDE?

Hi,

If your token already hold the permission set you can just enforce access locally without contact the server.

Clients interacting with your services can interact with the token endpoint and ask for specific permissions. Or even all permissions that should be granted to the subject associated with the token.

If you look this part of docs, you’ll see a superficial reference about “Incremental Authorization”. See the rpt parameter.

When clients already have a token with permissions (current rpt) they can ask for a new one where the resulting token will be a merge of the current permissions (represented by the current rpt) plus any other permission the client is requesting (resource/scope/type).

When doing incremental you can also control the maximum number of permissions by setting the response_permissions_limit parameter.

You could probably implement the RealmResourceProvider (RealmResourceSPI). See this example.

Another thing we could do is to implement a OPA Policy Provider, that would expose bundles as well as interact with OPA for access decisions.

This approach would leverage OPA to fit the token-based model supported by Keycloak. Considering that OPA runs locally the communication with the server should have a good throughput (or maybe not?).

Ok i’ve understood. We’re not extracting the permission of the users once the token reaches our gateway. The authorization checks are mainly done by the Keycloak adapter, used in each microservice. I think that for the solution you mentioned we need to fetch the permissions inside our api-gateway, in order to reach the microservice with the permissions already set. But this includes some sort of coupling between api-gateway-services-keycloak clients. I mean: how the gateway can be aware of for which client request permissions, based by the fact it is routing the request to a particular microservice? (we’re using a separate client for each microservice)

The API Gateway would need to be smart enough to identify the service being invoked as well as the resources associated with their path. That way, the gateway could ask for permissions incrementally and control the permissions within the token based on your API usage.

Without a gateway in the middle of your clients and resource servers, the clients are responsible for doing this.