 Thank you for joining us for this talk on dynamic authorization and policy control for your Kubernetes cluster. My name is Ash Narkar. I am a software engineer at Styra, and I'm one of the maintainers of the Open Policy Agent. I care about developing software that can be easily deployed, scaled, managed, and is secure by default. In today's talk, we'll learn a little bit more about the Open Policy Agent, look at its features, and then we'll dive into a use case around Kubernetes Admission Control. So let's get started. Before we look at what OPA is, let's look at OPA's community. The Open Policy Agent was started in 2016, and the goal of the project has been to unify policy enforcement across the stack. One of the earliest adopters of OPA was Netflix, and they've been using OPA for authorization over their GRPC and HTTP APIs, and companies like Pinterest, Intuit Capital One, and many, many more use OPA for a variety of use cases like mission control, RBAC, ABAC, data filtering, and so on. Today, OPA is a graduated project at the CNCF with more than 150 contributors on Git, a healthy Slack community of more than 4,000 members, more than 5,000 stars on GitHub, and OPA has been integrated with more than 20 of the most famous open source projects out there, some of which we'll see later on. What is the Open Policy Agent? OPA is an open source general purpose policy engine. When you use OPA, you are decoupling the policy enforcement from the policy decision making, so your services can now offload policy decisions to OPA by executing a query. So let's understand this a little more using this figure. Imagine you have a service, and this can be any service at all. It can be your own custom service, it can be Kafka, Kubernetes, an API gateway, Envoy, Istio, any service at all. Whenever your service gets a request, it's going to ask OPA for a policy decision by executing a query. OPA is going to evaluate this query based on the policy and the data it has access to and send a decision back to your service where it gets enforced. So you can see that we have decoupled the policy decision making from the policy enforcement. The policy query itself can be any JSON value. So for example, if you're doing admission control, the policy query could include the pod manifest, for example. Or if you're doing HTTP API authorization, the policy query could be your request path, your method, the user and so on. The policy decision itself can also be any JSON value. So and then it's up to your service how to interpret that decision. So this is an overview of how your service works with the open policy agent to decouple the policy decision making to OPA. Now let's look at some of OPA's features. At the core of OPA is a high level declarative language called as Rego. And with Rego, you can write policy decisions which are more than just allow deny through false Boolean. Your policy decisions could be sets or objects or strings or any collection of values. So OPA can help you answer the question, can Bob access a particular field. And it can also help you answer the question, which fields can Bob access OPA is written in go. And it's designed to be as lightweight as possible. So all the policies and all the data OPA needs for evaluation are stored in memory. You can deploy OPA as a sidecar as a host level demon, or you can now compile Rego policies into bosom executables and use them to evaluate your queries. So you can think of OPA as a host local cache for your policy decision making. OPA does not have any runtime dependencies, which means it does not have to reach when external service to make a policy decision, or it doesn't need to talk to an external database to make a policy decision. However, you can extend OPA to do that, but it's completely optional. OPA does provide you with some management APIs that allow you to pull policies and data from your server. Every decision that OPA makes is long and OPA can upload these decisions to your remote server, which you can use for offline auditing purposes. OPA will also upload the status, its health to an external service as well. Along with the core policy engine, OPA provides you with a rich set of tooling to build, test and debug your policies. OPA provides a unit test framework which you can use to unit test your policies before actually deploying them. OPA is also integrated with IDEs like WIM, VS Core IntelliJ to help you with the policy authoring process. And also the Rego Playground, which is this awesome online interactive tool which you can use to author policies and share those policies with the entire world. And we'll see the playground in the next part of this talk. So these are some of OPA's features, a high level declarative language, multiple deployment models, you have management APIs for control and visibility, and you have a rich tooling set. So if you look at the cloud native landscape right now, you have all these different projects, each have their own way of controlling access, each may be written in a different programming language. And so if you're trying to build a system which comprises of all these different projects, you're going to have a lot of moving parts in your system. And if you think about authorization or security in general, with all these moving parts in your system, there ends up being no visibility into the security profile of your system. And so what we need is a uniform way to control or to man security across all these diverse systems. And this was one of the motivations behind creating the Open Policy Agent. So this is just a snapshot of all the projects OPA is integrated with. There are much more, which you can find on the OPA website. And if you have your own integration, if you have your own project that you want to feature, please do contribute to the project. The cool thing I mentioned about the slide is that you can take any of these projects out of the box, any of these integrations rather out of the box, and use OPA to enforce custom policies in your system without having to write a single line of code. Like I mentioned before, OPA is a general purpose policy engine. And the reason for that is that it is not tied to a particular data model. So as long as you give OPA some kind of structured data, and you write policies that make sense for that data, OPA returns a decision back to you. So it's not tied to any kind of data model. And that's why it's a general purpose policy engine. So this is just an overview of some of the projects OPA is integrated with. I highly recommend you check out the ecosystem page on the OPA website to learn more and contribute your own integrations. Okay, so now let's look at one of the most hottest use cases for OPA around Kubernetes admission control. So for those of you are not familiar with admission control, it is basically a piece of code that intercepts requests to your API server before that request is persisted into HCD. So admission control is a great way to enhance the security profile of your Kubernetes cluster. OPA as an admission controller, these are just some of the policies that you can enforce with OPA as an admission controller. So for example, you may not want images to be pulled from any random external registry. You may only want images to be pulled from your specific internal registry and you can enforce that policy with OPA. You may also want that your containers must specify CPU and memory limits. You can enforce that policy with OPA as well. And we'll see how these two policies in particular are implemented using OPA further in the stock. There are other policies like do not run containers in privileged mode or any of the pod security policies can also be easily implemented using the open policy page. So the way admission control works is whenever you do something like coop cartel create pod. The best is sent by the web hook to OPA and the input OPA gets is a structure that you see on your left called the admission review object. And now OPA has to evaluate this input based on the policy and data it has access to and send a decision back to the API server. And even the decision that OPA sends in this case is not a bullion, it's sending an object behind and it's telling the result of the policy, as well as why that result was made. So you have more context into OPA's decision making process. And again, you can see the decoupling happen here. OPA does the policy decision making, while the web hook does the enforcement. This is an overview of how you can use OPA as an admission control. Next, let's look at an actual admission control policy. So the policy we want to enforce says that all images must come from a trusted registry. And to make this more concrete, let's say that all images must come from a trusted registry called holy.com. So only images from this particular registry should be allowed, the rest should be denied. So let's imagine the input coming from Kubernetes is shown in the box on the left side, and you can see it's an admission review object, you can see it's a pod. And the pod specifies an nginx container, which is using the nginx image. And that's not coming from holy.com. So the way you would write this policy to check for this violation would be to first define a package name for that policy. Packages allow you to scope the regular policy. We will next define a rule called deny. And deny will return the violation back to the user if the policy is actually denied, if the violation actually occurs. And so the first thing that we do is we are going to walk down this deeply nested structure using the dot notation and look for the kind of the object. In this case, it's a pod. Next, we'll iterate over every container inside that pod, and then fetch the image used by each container. Then we'll check if the image does not start with holy.com, because if it did, that's the violation. So we'll check if the image does not start with holy.com. And finally, if each of these expressions is satisfied, we will return a message saying that the image comes from a bad registry. So in these four lines, you can simply write a policy that will prevent images coming from anywhere other than holy.com. So let's see how this policy works in action. So what you can see here is the regular playground. It gives you nice syntax highlighting to read your regular code better. It allows you to write your policies. It allows you again to provide input and data to your policy. And then you can evaluate your policies. And you can also share the policies from the regular playground. So this is the same policy that we wrote in the previous slide. And so now you have an example input here. You have a pod with two containers. One is the nginx container, which is pulling the nginx image. And the other is a MySQL container pulling an image from holy.com slash MySQL. So now if I evaluate this policy, we know that there is one violation with the nginx container. So let's see what happens. There you go. So I evaluated the policy and OPA, since there was a violation, OPA returned the policy decision saying that the image comes from bad registry and the name of the image is nginx. The second image for the MySQL container did not clear the violation because it's coming from holy.com. So in this way you can see that OPA's policy decision is a pretty expressive and it's a collection of values which tells you why a particular decision was made. Let's look at another example. Another example is a popular policy which prevents your CPU and which asks for your CPU, your containers to have CPU and memory limits. So if you have a container and the container does not specify a CPU limit, it's a policy violation. So again, let's look at the input. This is the input. Let's make it bigger. So you have your input and you can see it's a pod object. The pod has multiple containers. You have the MySQL container which does not specify a CPU limit. You have a nginx container which does specify a CPU limit. So now if you evaluate this policy, there is one violation with the MySQL container. If we catch that. So there you go. So it says the policy MySQL backend is missing CPU limits and OPA returns that policy decision back to you without just being allowed in that kind of a decision. So now let's say you wanted to extend this policy. You wanted to say your containers must specify both the CPU and the memory limits. So what you need to do, you can simply take the same policy and instead of checking for the CPU limits, you can check for the memory limit and then you can update the message saying that the memory limit should be provided as well. So if you look at the input again, your nginx container specifies both, but your MySQL container specifies nothing. So again, if I evaluate this policy, you can see that your MySQL container is missing a CPU limit and your MySQL container is also missing a memory limit. And so now if you're super excited to share this policy, all you need to do is click the publish button and share this beautiful link with the entire world. So in this way, you can use OPA as an admission controller and you can write these very expressive policies which return not just allow deny like a Boolean decision, but which return more than a Boolean decision back to your service. Thank you so much for attending this talk. If you want to learn more about OPA, check out the OPA website. If you'll have any questions, join us on Slack to discuss any use cases as well. And check out the project on GitHub. And if you like what you see, please do start the project. Thank you so much for sharing your time with us today.