 OK, thanks for everybody for being here. I'd like to introduce our next speaker. As you know, security is essential to the cloud. And there's lots of tools out there. Not all are equal. And Peter O'Neill will be talking to you about Open Policy Agent or OPPA. Take it away. Cool, thank you, Tim. Cool. Yeah, so today's topic, securing a cloud native stack with Policy as Code in Open Policy Agent. Open Policy Agent is a tool kind of at the center of Policy as Code. So my name's Peter O'Neill. I'm the community advocate at the Open Policy Agent project. So I spent a lot of my time with the community in Slack and on GitHub and working with the contributors to the project and the maintainers. You can find me just about anywhere on social media with at Peter O'Neill, Jr. Today's agenda, we're going to talk a little bit about the challenge with policy in trying to enforce policies across your stack. We're going to talk a bit about what it means to have unified policy enforcement throughout each of the tools that you're using. We're also going to talk a bit about the policy development lifecycle, so being able to work on your policies independently of the rest of your application. Then I'm going to go over a quick demo of how OPPA works and how to write Policy as Code. And then we're going to finish it off and kind of talk about the Kubernetes Admission Control use case, this being an open source event. Kubernetes comes up a lot, so I just wanted to briefly touch on what it looks like to implement OPPA with Kubernetes. So the challenge with policy, it becomes more and more challenging to implement your policies in your systems as they are continuously changing and all of your tool sets are always growing. We have a number of languages that developers like to use and your application may have any number of these sprinkled throughout them. You may have Python for one part of it. You may write Go for another part. So you have all of these languages. And then these are going to be sitting on different types of infrastructure. You have different tools to control that infrastructure. You could be running on containers. In Kubernetes, you could be using Terraform to control this or CloudFormation. So now you have your infrastructure piece, which is a new set of tools. And then these run on top of clouds. And then you're connecting databases to all of these. So now we have an application that has a large number of tools that you're going to pull together in order to build your cloud-native stack. So now we have a very complex system where all these tools have to talk to each other. And so now trying to implement policy along the stack now, you have this question of how do I actually implement this policy? So just looking at the cloud-native landscape, you have over 1,000 tools to choose from in order to build your stack. So now let's look at kind of a little more visual how this looks. So now we have on the left-hand side here, we have your CI-CD pipeline. Then you may choose Kubernetes for container management, the actual application, microservices themselves, and the databases. You have all of these different components. So now any one of these pieces are all of these pieces need policy enforcement to some degree. So this is where a tool that's going to do unified policy enforcement comes in. This is now we're talking about open policy agent being this common tool set that's going to help you work with this large number of tools, or work with a complex tool set. So now looking at this again, what this is going to look like is OPA will start to intercept these requests from these services. So now all of a sudden when your Jenkins pipeline needs to make a decision whether it can access your databases, this can be farmed out to OPA. So you don't have to hard code these decisions inside of that application. When your microservice A wants to talk to microservice C, you can say, oh, is this within the policy that I've defined for my organization? So now these questions can all be defined very clearly in a policy that's written inside of your code base, written inside of Git. These are not just theoretical things or things that you're just blocking arbitrarily. These are things that you are defining with policy and writing them down and storing them in Git. And so how exactly does this work with OPA? So with OPA, we have this policy decision model. And so this is the construct of how OPA is going to integrate with these other services. So OPA itself is a general purpose policy engine. General purpose being that it is going to work with all those tools that we talked about, all those languages, all those databases, the infrastructure tools. And so to do this, what it has to do is it has to be able to take a query from any of those services at the top and those get sent down to OPA. So anytime there is a change that needs to happen or a decision for if users should have access, all of those decisions that your service needs to make can now be offloaded and sent to OPA. So OPA receives these queries. These queries are received as JSON. And so JSON is the reason that OPA is general purpose, because most applications are able to create a JSON object. So now all you have to do is reach out to OPA with this JSON object and the data that you are using. So this data could be user data, it could be information from your SSO, like authentication data, it could be the JWT tokens you're using to secure the service. These are, you can feed all this information into that JSON object, give it to OPA. OPA is then going to compare the data that it received to the policy that it has and any other database or any other data that it has on hand. So now it has the policy and the data going to compare that to the query in order to decide how to proceed. So this could be a question of should an EC2 instance be created? And so the information that might come in is a JSON object that might say, oh, we have the user, we have the timestamp, we have the location and we have their role. And then we compare that to the policy and return a decision to that service. Yeah. And then so how exactly do you deploy OPA? So OPA itself is a small go binary. So you're able to deploy it in a number of different ways. You also want to deploy it as close to the service as possible. So if this is, so you can deploy that directly on the host, you can run it as a sidecar or a daemon in Linux or, right, because what you're gonna want to do is remember, get that as close to the service as possible. Then most applications are going to talk to OPA via the REST API, being able to ask OPA, sending those queries to OPA over HTTP. We also have a go library if you're building a go application so it will feel very native to that application. And then we also have integrations for like Envoy and Istio and we also have a compiler if you wanna run the policies with WebAssembly, right? So we have a number of things that the community is working on in order to kind of help you get these policy decisions throughout different areas of your cloud native stack, right? So we want OPA to be this very flexible tool that works for your applications, not trying to make it so you have to adapt or what you're doing to OPA, right? And so let's look at really quickly here the Rego language. So the Rego language is the language that comes with OPA, right? And so Rego is a purpose built policy language, right? Purpose built meaning that it was developed alongside OPA as a partner so that you are able to define your policies in a language that is built for them, right? So we decided not to use YAML or JSON or other configuration languages because we needed something that's going to be very robust and be able to handle very complex policies, right? Being able to say, hey, right? We are working with very specific data types. We have those JWT tokens. We have the SSO data. We have the stuff. How do we modify? We don't have to start rewriting how to work with cryptography, right? Like you just want that stuff to kind of work. You want built-in functions that are gonna handle this, right? If you are working with GraphQL, you want to be able to take that data in, have a built-in function that's kind of just let you work with that data. So you're not consistently rewriting things that already exist, right? And so the Rego language has about 150 built-in functions. A lot of them community contributed. So as community members pick up OPA and Rego, they start to say like, oh, these are our use cases and these are how we want to use the language. And so they start contributing back and saying, here, we've written these new functions so that other people don't have to do it, right? And then so kind of just eat some high-level constructs here, right? Each policy is placed in a package and these packages allow you to call upon these rules from other packages, right? And so here we see example.rules and then we have one rule inside of this, which is just any API networks, right? Equals true. And so that's equals true is the default for any rule inside of Rego. And this is a declarative language. So we're declaring that this is true when the lines inside of it are met, right? So as long as everything inside of this rule is true, then the rule is true, right? And so it doesn't necessarily have to equal true. That is the default. It can equal anything that you want it, any other type of variable or other type of construct as well. It could be a string, a number, a float, Boolean, or just null. And Rego is a fully featured programming language, right? So it also comes with unit tests, which are a very big component of it, right? Being able to write proper code, being able to write tests, what you're writing as you're writing it, so that when you do commit this to get and you do want to deploy this stuff, right? You are confident with the changes you're making, being able to say like, oh, right, we've added three new rules, we've added 10 new tests, and we know that everything is working as of this point, right? And then so we have very extensive docs with the Open Policy Agent Project, you can check those out, openpolicyagent.org slash docs. And then we also have a fun tool that's very popular with the community called the Regal Playground. So with the Regal Playground at play.openpolicyagent.org, essentially what you can do here is you can take the Regal policies that you're writing, you can drop them in, right? You can add your inputs and your data files as well, and you can work with this information live right on the site, and then you can share these playgrounds with other people as you are working with these policies and trying to figure out how to write them. We use this very extensively in the community to say, oh, when someone's asking for help, writing a policy or authoring something that's kind of complex and they're just like, we are working with this kind of data, the easiest thing to do is to say, okay, drop it into the playground and share it with us, and then we can view this information and then work with you, right? And then so this just ends up being a nice medium for community members to communicate with each other and kind of show what they are working on and how exactly it behaves, right? Being able to hit this evaluate button to see which policies are executed and being able to see how it performs in real time, making those adjustments and then kind of sending them back. Right, and then so now let's talk a little bit about the policy development life cycle, right? And so a big part of being able to write policy as code is being able to separate the writing of your policies from writing the rest of your application. You shouldn't need to rebuild your application every time you make a policy change, right? And so being able to write these policies independently is kind of like step one, right? Having your policies written in version controlled, writing your regular policies, right? And then deciding what you're going to actually do or what you actually want these policies to do, right? And then committing these to some sort of CI process where you say, oh, let's now take these policies, build this bundle and have this policy artifact, right? And so this policy artifact is gonna say like, hey, at this date, at this time, these are what our policies were and this is how they would have performed, right? So being able to always have that version rollback and being able to say like, look, this is what we know, this is how we know it was working and right, if something does actually go wrong, we could always rollback to an older version or an older artifact before they are deployed, right? And then having that deployment process, right? Being able to say like, get ops practices and saying like, yeah, I've checked this in, I have my build artifact, I've rolled it out, right? And then checking to make sure everything is healthy, right? Making that full deployment where checking that all your OPA servers have those latest policy bundles, right, just flowing through this process, right? And then as I said, monitoring, making sure that everything is up to date, all the OPAs are working as expected, they have the latest policies and then logging, right? And I think logging here is something that is very important to most people who are looking at policies. If you're concerned about policies, you're very concerned about the historic view of these policies because at some point someone's gonna ask you, why did this happen, right? And so with policy, especially OPA, right? Being able to track what is a large number of decisions you want to pipe this out somewhere and so all of these things are manageable via the OPA management APIs. So each one of those little OPA servers has management APIs that you can tie into and allows you to modify and work with each of these components, right? So there's a logging API, there is a policy API for bundles, get them in there, there is management APIs for all of these things, right? And so now we're gonna do a quick little demo. Open this up. Cool. All right, so here I have my VS code that's very small. Let's make this big. Yeah, that looks good. Okay, and yeah, as you may remember from the previous little screen that I showed with the diagram that showed on the bottom there, there was an input and there was a data and there was a policy, right? So the input is the query that we would have received from a service. And so you could think of this as someone reaching out to the API, we are doing a get HTTP get request on the path CNCF, right? And the user doing it is Peter and he has these two roles, right? And so you can imagine this as an API endpoint, you basically just pull that information out and then it will get sent to OPA and then this is the policy that OPA has, right? And so we have the package policy, right? This is just the structure of how you contain all of your rules, all of your rules are, right? And so this might be like, you could also say policy.getrequest or something, right? And so, but this just has one package. And then in here, right? We have the default rule, allow equals false, right? And so allow is just a variable, right? It doesn't have to be allow. This could be enabled or required or any other word that makes sense for the service that you're working with, right? And so in here, we're actually saying that for this allow, remember allow would be equals to true is the default, but you don't have to specify it. It is the default, right? And then so we see there are two conditions that need to be met in order for allow to be true. The first one here is the input method needs to be get. And then the second one here I'm showing is input request dot path in data public paths. And so I've actually commented out this line here. So we've recently added some new keywords. I think about three versions back where this line here input request path equals data public paths. And then this is kind of a loop. It's saying that it exists inside of these paths, but I don't know which one. So just loop through them all. But now we've added this nifty keyword called in. So now you can just say the input request path is in the public paths, right? And then so that's why we're importing this keyword here. And then so let's actually look at these, right? So input request path, right? So in our input JSON, the request method is get, right? And then the request path is slash the NCF, right? So here, so in our policy when we see is get, and then is, so we're expecting it to be inside the data public paths. And so this one is not inside these public paths. So I would expect this to not be true. So we can actually run this, right? And so here I'm just doing an open eval, putting in that policy, putting in that data, putting in that input file, and we see that the output here is false. So we're saying, oh, right? No, this was not allowed, right? So now we can say, oh, let's actually, right? We decided that that is now a public path, so we can run that again, right? And that would become true, right? So being able to roll these things out in kind of a semi-fast fashion, being able to modify our policies pretty much on the fly. Right, and then the second rule here that we might wanna test here is just being able to say, allow these changes if the user is an admin, right? And so if I remove that rule again, save that, right? Go back and that should be false again, right? But now let's actually just make the user making their request an admin, right? Just kind of showing that, right? This is the expected outputs that we are seeing, are the outputs that we're seeing are expected, right? And then, right? So the next thing here that we should start doing is authoring some tests for these policies, right? And so now let's actually say that with any good rule we're gonna be able to test that what we're seeing is what we're expecting, right? So with OPA, how you're gonna write a test, it's very simple, you just have to preface the rule with the word test, and that's how OPA is going to know that the rule that we're looking at is a test and not an actual rule in the policy. And so here we see tests allow if public path, and so allow, right, this maps to our policy, allow rule here, right? And we're saying, we're basically saying this is true without saying that, that's kind of disimplied. And so with the input, and so the input is this input.json, we are now mimicking that in our test file. So we're saying, hey, with input as this JSON object. So now we're swapping out, it knows that for this block that we are looking at this object instead of the actual input. So now instead of OPA eval, where OPA is evaluating the policies, we can just run an OPA test. Testing in this file and we can see that, oh, this one test is true, and so. But we probably want a couple of different tests, right? This isn't the only test that we would want, right? Let's actually run another one here. Let's do the opposite side case and say, let's deny a public path if it's, if it's not, or let's deny the request if it's not a public path, right? So slash secret is not defined, is not defined as one of our public paths. And so test and I, we're expecting this to be denied, so not allow or denied, right? So we test that and see that that is also true. And then the last thing that I'd probably want to test here is just saying allow if admin, right? And so as we stated in our policy, basically the only thing that it needs to be allowed is if the user is an admin, basically that is, that will allow them to do just about anything. So allow with input, delete on slash admin, right? As long as the user role is admin, and that will be the, gotta save the file, right? And that'll be the last test here now we can see, right? All three of our tests are passing here, cool? And with that, right, that's kind of just a very simple overview of how OPPA works and how it works with structured data. And so this is, yes. Right, and so with that, right, we can actually just, right, there are a lot of helper commands here, right? And so, let's see here, makes us a little bit bigger. Good question, right? And so we can actually just, I think dash v is the one that I want, right? And so we can see just a little bit better view of like, okay, it's actually saying like in our data, in policy package, right? This is the actual rule that passed and how long it took. So you can kind of do a more verbose output, right? So depending on, if you're running in this like a CI CD or get or something, right? Depending on how much information you actually want to pull out of it, right? You might want verbose or you might just want a pass fail. But yeah, great questions. Yes, right, sorry about that. And yeah, the first question I answered before was how do you see which test failed? So showing that with just the dash v command here. Second question here is when I was running opa eval, how did opa know what data it was taking in? And so with that opa eval, right? I actually pass these in with these flags here, right? So the dash d, each dash d is just saying like, evaluate with this data. So dash d, I'm passing in the policy, I'm passing in a data object, data.json, and then the input, right? So I'm just mimicking the entire flow there by passing in those three objects. And so it knows that the dash d is data and dash i is input. And so the difference there is just like how it's looking at working with that data and how to actually structure it. Test didn't need it because I'm actually replacing the input file with this with input command, right? So the data object is actually pulled in there automatically because I'm doing opa test and I'm just doing dot on this file, right? So it's just like, it's pulling everything in, right? So yeah, question was why did opa test not need it but opa eval did? And so opa test, I'm just passing in the entire folder structure here. Cool, awesome. Thank you for the questions everyone. Yes. Yeah, so the question here is this example was using path-based routing and what other types of policies can we use that are not path-based? Right, and so a very common one is Terraform, right? So Terraform is one where they aren't paths but they are saying like what types of resources can be created. And so with those, you're actually passing in the Terraform plan, right? Where you're taking a bunch of objects that will be created and then you're going to look at them and say, oh, evaluate this against a policy that I've defined that says you are allowed to create resources maybe only during working hours or maybe only up to a certain amount, right? There might be certain resources that you're just like these are absolutely out of policy, you cannot create them. And so you can build guardrails around that type of data as well, right? Structured data is kind of key to opa where as long as you're able to have some sort of structured data and convert that to JSON then it's very easy to feed into opa. And so things like creating resources or just doing like microservice to microservice communication where you want to say like, oh, I want to send data and then you can actually analyze that data and say like, oh, this is or is not within the policy. Cool, does that answer the question? Okay, awesome, sweet. And then yeah, I'm gonna go back to my slides real quick and then kind of cover one more use case here which is Kubernetes Admission Control. A lot of Kubernetes fans in the building so I figured this was a good one, right? So with Kubernetes Admission Control, right? We're once again talking about structured data because each of the YAML files obviously YAML is very structured data. And so let's talk a little bit about what happens when you're actually creating an object in Kubernetes, right? So on the left hand side here we have a user applying some file app.yaml, right? And then before that file is actually stored inside of SED, right, a number of things have to happen, right? That user needs to be authenticated who they are. That user needs to be authorized for the action that they're doing. And then that file itself goes through a mutating admission controller where it's going to say like, what is it actually going to look like when it's created? And then once you have that final form, you have that validating admission controller that's going to say, yes, you can be created or no, you cannot, right? So each of these modules happens in order and they can happen more than once depending on what you actually want to do. So then you might be chaining multiple modules together in order to have the desired effect that you're looking for, right? And so here are a handful of built-in modules that are pretty popular, right? With like OpenID Connect, you might want to use Aback or RBack for your authorization. You may want to have some very standard, like always pull images on the mutating admission controller or right, limits on the validating admission controller, right? And so if the built-in modules aren't what you wanna do, what you can do instead is set up a webhook, right? And so with a webhook, this lends itself very nicely to how OPPA works because now you're able to use that HTTP endpoint with OPPA and direct this webhook directly to OPPA. So now OPPA is able to help out with these modules and be able to pass back those decisions, right? And the most common one to extend is this validating admission controller simply because this validating admission controller is the last step and it also allows you to build guardrails around what resources can actually be created inside of your cluster, right? And so these are going to be a handful of things that are very common, right? Like people using it to block certain images from certain repositories, being able to look for uniqueness across the host and path, being able to replace pod security policies, right? Just a bunch of very common things, a very bunch of common like guardrails that people want to put up around Kubernetes while resources are being created. Yeah, and so with that, right, here's kind of a simple example, right? Showing the creation of a pod on the left, saying like we have a simple deny rule in the center here saying, right, we're looking at that not input.request.object.metadata.labels that cost center, right? So we're just looking inside of this object for this metadata and then we're looking for a label for cost center which is not there, right? So then inside of Kubernetes we would actually see this error message, right? You're able to return error messages through the validating admission controller and then so the user would actually see this message and be able to adjust their YAML files and then reapply them. Cool, and then thanks for watching. Here are some resources to help you get started. We have on the OPA community, Slack and GitHub is where we hang out a lot. So they're conversations every day in Slack and we use GitHub discussions and GitHub issues to answer questions for the community. You can get a response very quickly there on social media, Twitter and LinkedIn. And then we have the OPA docs. As I mentioned before, great place to get started. It is very, very thorough. There are a lot of pages of docs there and then if you get lost in the docs, come over to Slack and ask us for help and then if you want something a little more structured, the Styro Academy is a free course online that shows how to start authoring Regal policies and working with that type of, or working with Regal and starting to do that type of work. And then this is me. You want to add me on Twitter, test my QR code. Yeah, and thanks for watching. Thanks for stopping by. Mm-hmm. And any other questions before I close it up? Yes. Yeah, and so as I mentioned, it's structured data that we're looking for. So if you have that business data in even just like a CSV, you can then convert that into JSON and then feed that into OPA and then you're able to evaluate against that. And then so depending on what kind of policies you want to write against that business data, being able to say like, oh, only authorize these users with these access permissions to do something like that. You can do a lot of filtering. And so we see a lot of using Regal to filter the data in order to do some sort of transformation on it and then being able to use that for your rule set, right? And so that is something that we do see quite a lot. Mm-hmm, cool. Thank you. Any other questions? Awesome, why? Thank you, everyone. Have a good conference.