-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: OPA as service sidecar and data/policy acquisition #718
Comments
In v0.8 you can configure OPA to pull bundles of policy and data from remote HTTP servers. Using this feature, you could implement a small service that serves up bundles for your agents. If you don't want to implement this service, there are a couple options.
If you can share more details on your use case(s), I can follow up with more details. Also, if you want, feel free to join slack.openpolicyagent.org. We can chat on there. |
Thanks for the quick response, @tsandall. Give me a bit to consume your post and I'll give an update tomorrow with a better example of what we are trying to accomplish (or at least the thoughts we have on how it might work). Cheers! |
Let's assume the following diagram is a simplified MSA application comprised of an API Gateway, an AuthN Service, a User Service, a Photos Service and a Kafka cluster. MSAEach service contains its own data store and talks to the API Gateway over gRPC. In addition, each service fires events about any data changes that have happened within that service (CRUD events). We need to implement authorization on the Photos service so that only photos uploaded by the user can be edited. In order to do this, the photo service needs to know the policy, and have access to the user data to apply a policy. It can gather that info from the events fired by the User service and cache them.
All of these services are deployed using Docker into a Kubernetes cluster. Let's assume this is a 4 node worker cluster with a pod distribution as follows. NodesMy initial thoughts are to have an OPAgent as a Daemonset on each node so that all pods on that node can share the OPA instance, something like this. DaemonsetThe thing I'm trying to understand is how to get the policies and necessary data out, and in sync, across all the OPA Agents. Assuming this is a very busy application, data is constantly changing at a volume of change that creating a zip file and storing it somewhere doesn't really make sense. Calling the APi would be much better, but having to keep track of all the agents in order to call all them means writing a server that can interact with the Kube API to get all the IPs. I'd like to avoid that if possible. Option 1One thought is to use OPA as a library and write a Go wrapper application that listens to the events coming out of Kafka to keep each node in sync with the data, something like the following diagram... This could work, but each Agent would have to subscribe to multiple partitions and topics, manage offsets, etc. And if new Daemon comes up on a new node, or one goes down, they would need to start reading from offset 0 in Kafka to rebuild a full current state. Compaction would need to be turned on as well to ensure all keys had a current state value. Option 2Another alternative we might try is to create a new service, the Policy Service, that consumes the data, manages the policies, and keeps the state in a document store. Agents can then connect to the Policy service using a streaming GRPC connection so as new data comes in it can be pushed to the agent in real-time, or when new agents come up and connect, they can get a current state. Something like this. This seems like a better approach but still requires using OPA as a library and writing all of the code necessary to communicate with the Policy service. Again, completely doable. My question is, given an environment like this, is there a better way? Or, is there something around OPA plugin's that might be worth exploring? The docs aren't very clear about how plugins work. I hope this better explains the situation we are in and some of the things I'm thinking. Just hoping to get a little bit of guidance around OPA and if we are totally off target here. Thanks for your time! |
This is great writeup. Thanks for sharing the details. Another approach that comes to mind is to have the service (e.g., Photos) provide all of the information required by the policy as input when it executes the policy query. This avoids the need to replicate and maintain a copy of the user/auth/service state inside OPA (and all of the burden that comes along with that.) If you follow this approach, the service would:
With this approach, the policy could make the authorization purely from the This is the approach that I would recommend. My guess is that you can hide the details of authenticating requests and gathering user/auth data from your services. The additional service-specific step could also be hidden (to some extent) depending on how opinionated your service frameworks are. OTOH, if you think this is too much burden then replication is the way to go. Here are a couple thoughts on replication.
Hope this helps! |
Thanks for the update, @tsandall! I'm definitely leaning towards option number 2 I mentioned. It would give us a way to centralize policies and data, and manage them, but not slow down the policy checks. As for consistency, our entire system is being built on the premise of eventual consistency (our business is not transactionally heavy), so we can withstand a slight delay, and would design to allow for updates to happen as quickly as possible. But, it's a fair point we'll need to consider. Are plugins external or do you need to recompile OPA with the plugin? Sorry, I'm not a Go dev so just wrapping my head around how plugins are loaded. It seems the optimal approach to just write a plugin that is able to handle the gRPC data/policy streaming into OPA without having to modify OPA or use it as lib. |
Yes, today you have to recompile OPA. Go does have some basic shared library support now so we could add support for loading plugins dynamically. If we had this in place then you would only have to rebuild the OPA docker image to include your shared lib. |
Thanks! It's not the end of the world by any means, just most of our devs are Java developers so trying to keep the learning curve low. But still, it's worth the investment since OPA really does help solve a problem I've been mulling over for months (Authz in MSA). Thanks for all your hard work and a great OS project! Cheers! |
I'm just starting to read up on OPA as a way to resolve Authz in a microservice architecture. So far it looks promising but it's not clear to me how you handle data and policies in a microservice (sidecar or daemon set) implementation where there is no single API endpoint to call - there would be many-many instances running across the cluster. I just watched the talk on Netflix and their set-up is very similar to what I'd like to achieve, but it seems the "aggregator" and "distributor" they use to manage the issue described above are homegrown solutions. From this I assume that OPA does not provide any mechanisms for handling this out-of-box... is that correct? If so, do you have any recommendations or third party plugins that can assist in gathering and distributing this data (policy and data) to all instances of OPA currently running across a cluster?
For additional context, we are rebuilding our platform using a microservice architecture utilizing Docker w/ Kubernetes and are trying to find a solution to our Authz problem. We are looking to solve this with minimal latency and no single-service bottlenecks (no single Authz service everything calls). OPA seems to be a fit here, except for the distribution of state data and policies to all active instances.
The text was updated successfully, but these errors were encountered: