 Alright, hello everyone and welcome to the first talk of the beginner track for the day Thank you all for for coming and to learn about policy as code and readable rego Quick show of hands who here is doing some sort of policy as code already in there in their stacks All right, cool. And how many of you are are using open policy agent? We got a couple it's pretty good. All right. Well, this is the beginner track So this is going to be a very like introductory a Talk on how to use open policy agent what it is why it came about and then we're trying to go over some quick examples of how to how to write Regal policies and how to clean up the code so starting off My name is Peter O'Neill. I am a senior DevOps engineer and evangelist for a company called WebRite We helped do digital transformations and helping companies Move their legacy technologies to the cloud Cool so today's agenda talk a little bit about why Open policy agent came about the difference between off then and off Z But about what it means for something to be policy as code then we'll dive into the open policy agent project And then we'll get into writing rego and doing some unit testing. So Let's get started. So you've probably already seen something similar to this where right? We've been moving to the cloud We've taken these monoliths that we had and we break them down into these Microservices right and like breaking them into their smallest components. And so when this happens, right? There are a Lot of points now that you have to make decisions, right? Now that we have all these different services all these services have API endpoints all of and then you have more users using These services and all these services have more components. So now you can see the complexity here of all these points now You have thousands of interactions that need some sort of authorization check when they happen, right? And so this is now why we move into the space why we need a more fine-grained access control system or authorization tool and so The reasons that a coarse-grained system, right? We're talking very simple like our back policies or just users Where you can just have one simple rule around what a user can or can't do won't work Right it kind of lacks a lot of the complexities that our cloud native systems need, right? And so when we talk about this, right like these these policies end up being Right like hard-coded directly into the application then it being very air-prone, right? There's a lot of things that just don't work very well for the complexities of the systems that we want to create and so With that right like we we want to now Extend extend and expand what we're doing to be more dynamic and to be more inclusive of The systems that we're creating right and so this is kind of the model that we want to move into So with that we'll move into Authent versus Authz and this ends up being a Question that comes up quite a bit when People are trying to adopt an authorization system because they think I already have an SSO provider I already know right already have something that Identifies my users, but right this is the off-end side of the problem and when we have But we need both sides of this coin right that only do we need to identify the user But we need to grant permissions in a way that is very modular, right? So you you need to solve both sides of this coin in order to have it through Authorization system right and so when we're on the off-end side that is our SSO provider That could be LDAP that could be active directory right and then on the other side of that is when we're actually setting up Our authorization system right and this could be as simple as our back right once again with that very coarse-grain just Understanding what users belong to what groups and giving them and giving them permissions based on that and then you have right? You move into a little bit more complexity where you have like an aback system or Attribute-based access controls where you start defining more attributes around each specific user and each Interaction that they're doing and it gives you a little bit more of that fine-grained nature or something like I am like directly in your cloud Where you can control right individual components with it within the cloud right and so it's giving you more and more Control over the interactions that need to happen right and so when we think about this right we can think about Right all the different places that that these interactions are happening right you can have things at the Infrastructure layer, you know directly on Kubernetes or Docker or right you can think of this as like inside Kubernetes You have your admission controller. This is when Kubernetes is actually going to create resources, right? We are admitting those resources into Kubernetes right so we need to have that that modularity to say hey I Want specific users or specific service accounts or specific x to be able to create Some type of resource in this cluster and you want to be able to control what that looks like right same thing with Terraform You want to be able to say When I run my Terraform plan, I know what is in scope and what is out of scope right? I know that when users are creating resources VMs Maybe entire clusters right you want to know exactly How they should be created not just saying Because you are an admin you can create whatever you want right this ends up happening a lot in CICD pipelines where those permissions end up getting like the star value admin and those those Those CICD pipelines end up being overpowered for what they need to do right and then on the on the application side of this right you can think of this as When you are defining your applications when you are building these services What exactly are you going to allow your users to actually do when they're interacting with the system right? And so these are all different types of authorization decisions that need to happen both on the infrastructure side and on the application side and so What's needed right like and so this is kind of where we start getting into this policy as code Mindset right where now that we're looking for this dynamic find-grain authorization right we start wanting to Standardize this by using some sort of framework right by having a framework now We know for all these different components from the infrastructure all the way up to the application right? We can start defining what these policies look like in one language Right and we want to be able to say a little how do we do this in one place right? How do we actually get these policies to apply to all of these different areas? And we do this by decoupling the policy logic from the tools that we're using Right and so this is where we start actually doing policy as code because now that we have decoupled what? Authorization checks need to happen now. We can start defining these and Putting them into our policy or start checking these into git as if like we will with the rest of our code base right and so now we know a little bit About policies code or sorry Sorry, one more one more slide here right and so the evolution of policy right and so this is kind of Where we started to how we got to policy as code and so right? Once upon a time right like I remember my first job my first Systems job where they gave me access to all the systems when I started right they created all my accounts And it's basically just root access to everything right it was basically them saying hey When you're working with our systems make sure you don't do this and everything was written in a wiki and Who really reads the wiki every time they go to do something right like you sound something that you're going and manually checking to Make sure you're doing the right thing every time and so it's very error prone and then so right as things kind of moved along We started saying well, okay Well now I can just kind of put some guard rails up and just kind of say let the system block a few things here and there Right and make sure the system stops you from doing anything. That's like crucially bad and Then right and then this worked fairly well But we ended up defining things like who is my admin group in a dozen different places right and so we had that we had this hard-coded Policies that needed to be rewritten time and time again right and so this is where we've now moved into right like okay Well, then how do we define this in one place and Spread it out everywhere right giving us this more of a policy as code mindset Right and so when we're doing this what we're doing is we are extracting that policy Writing it in some sort of policy language and then having a policy engine and force this for that service right and so now we have Whatever that service is being able to call out to that policy engine right maybe it's running directly on the service Maybe it's running next to the service, but that service now is able to make that call to say hey I don't know what to do In this scenario and you don't want it to know right you want your policy system to be able to make those decisions for it Right, so this ends up taking away complexity from the service and speeding up Speeding up that check every time it needs to happen right and so as we're doing this right what we're doing is We are applying the same principles that we use for software development for our policy Right, and so when we typically think about The how we've come to build applications We have this very standard idea of what the software development lifecycle is and those same practices work for your policy development Life cycle right you want to be able to define things up front you want to be able to Author and create things and check them in to get Before you're actually deploying them so that you can run your unit tests your integration tests right you can verify Everything that's happening before it goes into your systems because right like you don't want to check in a policy That's very restrictive and have it you know Block access that you need or turn off access that's already there Causing things to happen that are unintended right and so you're able to use that same CICD pipeline to deploy policies that create the security guardrails But you're able to use this with the same Tools and mindset that you're used to for when you're doing your software development Right, and then it gives you additional things like monitoring and logging all the other additions to the life cycle that you want to see and so with that Right, we have this tool called open policy agent right and open policy agent has been around for quite a while It is a graduated project in the CNCF and right it came about to solve this problem of How do we enable authorization? Across the the tech stack or across specifically your tech stack that you're using right and it Does this by creating that standardized policy framework that we talked about earlier, right and so Opa or opa for open policy agent is a general-purpose policy engine right that general purpose meaning that it's able to be used for all those tools and services right and so This tool right by by decoupling We'll get to the next slide right is gonna allow you to really optimize your policy performance Your policy performance for the rest of your your stack right, and so how exactly Does this work right and so As I mentioned you we are decoupling here So the service at the top here is going to make right maybe this is gonna be an HTTP call Maybe this is gonna be running as like a sidecar right, but you're gonna have these various options so that your service Right can ask a question and what is a question a question is going to be all of the input and data that your service has and it's going to ship that as a JSON object to open policy agent right and So we are calling this a question but realistically this is just understanding the data in and returning a data block back right and so at It's simplest level which you might be returning back is like a Boolean like a true or false But this could be much more complex than that as well, right? You might be you might want to send some sort of JWT token that you want to encrypt or decrypt You might want to hash these values or create certificates on the fly right so opa being this Being being the decision engine Just understands how to take in this JSON and then you're going to define with your policies What needs to be sent back right and so The magic happens inside of the policy itself because the policy is going to transform this data into what you need right and so Right like as I mentioned right there's a bunch this is going to work with pretty much any of the tools in your tool stack because as a cloud native tool Everything basically speaks on the HTTP protocols you're able to send these requests and then opa will be able to Compare the question coming in with the policies that are defined in any external data that you want to give it as well Right that external data might be user data. It might be Right just just situational data. It could just be right like anything that's going to augment that policy to allow To allow opa to make the correct decision for what needs to happen and so right like we Typically are going to start at one place inside of your tech stack But right these decisions once again happen throughout the entirety of your application. So you're going to Insert where these policies happen at all of these different components, right? You're going to check when right things are being created in your CI CD pipeline The policies are going to be applied there so that you know things are created in the right way You're going to include policies in between your services, right? like so if you're using some sort of service mesh or Something that that is giving you that telemetry between all of your services You want to know that what's happening when those calls go from one from service a to service b that Everything is happening as you expect it to right and then down on the infrastructure layer You want to make sure that things are always in the form and fashion That they should be right understanding what this state of your system looks like and How? Yeah, and how it should look right and how you're going to want it to be right? So you can see how very quickly all these different components are requiring some sort of policy That you're going to want to put in place and so you also want to Define what those look like And be able to reuse them right you want to keep your policy infrastructure as simple as possible and once again We're doing this by decoupling Where that policy enforcement happens right and we're handing it off to open policy agent So that all the tools you see here on the screen can speak one language when they want to make this decision Right and here's some some very common use cases and patterns. I've kind of touched on these already right but Right kubernetes with the admission controller is a very popular one If you've seen if you if you've if you've been involved with the open policy and project you've probably heard of gatekeeper and gatekeeper is essentially a Framework on top of open policy agent which turns your regular policies into crd so that you can apply them in the cluster Right and then there's tools like terraform Which you can run either directly in like terraform cloud where they have an open policy agent Run task or you can do this on your own in your cacd pipeline by introducing opa as like an action or Just a component within your cacd Kind of process and then with envoy right we Interact directly with envoy through their api so that we can understand what's happening and make decisions From service to service very quickly so we can implement those policies without introducing a distant additional legacy or latency right or right Open policy agent is a very small go binary so you can actually run or you can create things that are very performant for your specific use cases, right? we have a We have a go wrapper around open policy agent, which is very performant. We've seen some very interesting deployments of this one of the one very recent one that I saw was a mirror basically Understanding all the interactions on a mirror board and then shoving them through a data pipeline to Understand what the permissions are on the mirror board in real time, which is Very impressive when you think about it because there may be dozens or you know hundred users interacting with the board with 1,000 components so the complexity there of who's allowed to mess with which components at which time Ends up, you know scaling into the thousands of decisions a second very quickly So you need to be able to create something that or create a pipeline of authorization decisions. That's very robust right and so when we're doing this right like this was the kind of kind of This was this was what I showed earlier right and we're basically just replacing a Policy engine with open policy agents specifically right opa is the tool that we want to use and rego is the Purpose-built policy language that we want to write things in and so Now we're gonna dig into Now we're gonna dig into open policy or sorry rego, which is as I mentioned the purpose-built policy language right and so when I say purpose-built what I mean is that it was created alongside open policy agent to Define what our policies look like right and so there were There was large discussions in the beginning around what should a policy language look like should we just Repurpose Python or JavaScript or Golang or just try to write things in a language that people already understand the problem with that was that You're bringing in all of the baggage of that language that people want to write things in a specific way and so trying to stick to a cloud native mindset is Having a declarative language ended up feeling much more natural to solve this problem right and so now we have this declarative language where we want to Define what our policy is going to do And you're able to you state this state this in a clear fashion that now open policy agent figures out what it needs to do and so Since most most people in this room haven't Written any regal before what we're going to do is we're going to write a simple policy here Which is just around our back and controlling our defining what? What a specific user can do right and so here on the screen? I'm showing some data in these pink boxes at the bottom I'm going to abstract a lot of this away, but that's kind of just like the small data block that we're working with here and so With that right on the left-hand side here We have a package name right and this package name is a naming convention right the naming convention We are is just a logical boundary between your policies right so this is a full-featured Coding language and so we have this logical boundary in order to say like oh I have a package of policies for My aws features. I have a package of policies for my Microsoft or Azure resources right so you just want to be able to have that Logical boundary so that you can call policies from one side and reuse them maybe between teams or just between policies Right and then next up we have these this word called import and so With import what we're doing is we are protecting backwards compatibility Right and so this is very important when you're dealing with policies and you want to know that what you're doing Is not going to break what already exists right because breaking things that exist in the with a policy could have catastrophic effects and so what we end up doing is as we Advance the language we wrap all of these all these features into this future keywords import and so this ends up Allowing us to read the policy and a much more and in a language or make it seem much more like English as you're reading the policies And then so next up is right We have a declarative language and declarative languages don't really like when things are undefined and so you end up wanting to set a baseline for for what each of your rules is going to be at the beginning right and so very typically you're gonna have like and Allow equals false as a default and this kind of just says right fail closed don't allow things to happen that aren't intended and then Now that we have our defaults and we're starting to abstract more of the policy way at the top, but it's all still there right so now Right this very simple rule of like allow admins. What we're doing here is Right we have one rule, which is that allow rule, but we are now calling out to a helper function This helper function is going to be what actually Runs the logic and so in here we can see User is an admin if admin is in data user roles and we're checking for that specific input dot user right and so that Input user on the right hand side there in the white box, right? This is going to be what is shipped from What is shipped from the service asking the question so in this case? We're thinking about like an API request for a user trying to perform some sort of action On a specific object with that idea and the type dog, right? And so what we're doing now is we are basically looking up that user that we see is Alice in the box and Trying to and understand seeing what role Alice has assigned and so in here we can see that Alice is an admin So this rule would become true right and so but what if Alice isn't an admin right and so Now we end up having to be a little bit more granular around What this rule is going to do and so this is right so now we're breaking this down a little bit further And we're actually checking for these specific grants that are tied to this user, right? And so remember all of the information coming in is JSON So we're able to navigate this JSON tree just by doing this like dot notation, right? And so we can see in this allow if statements, right? We are checking for a grant In this user is granted Kind of rules are in this rule called user is granted, right? And so at the second part of this rule We could see that we are We are kind of going through going through the list of roles and Through in that list of roles. We are checking for grants, right? And so What's we are looking for here in the input box, right? We see Bob is trying to do an action called update on object ID four five six with type cat, right? And so we are looking through We're looking through this data set on the right-hand side and we're seeing that it doesn't quite match up, right? Bob doesn't have this type cat assigned to him, right? So as we are cycling through the rules and grants that Bob has assigned to him We are seeing that doesn't quite have the permissions that he needs and so as Rego is going through this list, right? And when these things don't match these rules become right defaults back to that Default equals allow equals false, right? And so With that right like that is just a very simple policy that we've written, right? And so this is typically what we end up telling people to do is like start really small find one very small Rule or around what you want to define or protect with this policy and then expand from there And so now that we have our first rule written, right like with any good Coding practice we're going to write our unit tests around the rule So with with these unit tests We the language makes it very simple, right? And we normally recommend that you separate out your unit tests Into a separate folder so this one is just our back dot tests, right? and you're doing to define these tests with this test underscore keyword at the front and What I'm doing here is Supplying it with like a mock data, right? So before we had the input that was coming in and that json object here. We are just essentially saying Imagine that this is the input and we're saying what we're expecting to happen, right? And we're expecting this allow to be true when the input input shows Alice update and then type cat right and so You if you're doing any sort of good test or driven development, right? You're going to have to be able to define all of your unit tests up front to do this and so With the inverse of that right being able to see that this negative test not allow is also going to to Right not allow being true because we're expecting it to be false and so With that the very last section here is kind of just improving your rego, right? So these are just common things that we see Right so on the left-hand side is as people are kind of learning the language It ends up not being super clear, right? The left and right hand side here both do the exact same thing but you're gonna see as You progress in your learning of the language, right? You start using more of the features you start using Annotations instead of just comments you're now also like using rule names that make more sense, right? It ends up being Very common that When you write your first rules you write something that sounds very easy to remember But then maybe isn't super clear when you're looking at it and reviewing it, right? So having a super user rule may not be the clearest thing when you're trying to review the audit logs, right? But using rule names like allow lets you know that okay, so this rule was trying to Allow something to happen right and so The second thing here is reusing expensive computations, right? And so from the left-hand side here are in the red box, right? We're gonna see that in both of them We're doing the same check instead of using a helper function, right? This helper function is what's actually going to When you're scaling out and you're doing things at a At a much bigger scale you're gonna want to be able to use these helper functions to reduce the number of Iterations and calls that you're making right and so these Reusing expensive computations isn't just for iteration But also when you're making like HTTP calls or using external data to pull that information in and then My last one here is just nested iteration right and this is something that also very common when you write your first rules Is it ends up being very simple to just loop through your loops when you're checking for things? but right then you end up with these coding problems where Things take much longer than you expected and you end up trying to solve performance problems later down the line instead of defining Defining a list that you are a set that you can reach out to right and so making making information reusable is a big part of writing code that is very performance and And so with that I just want to say thanks. This is a quick primer on opa and rego and yeah, thanks for attending And I think we have one minute if there's any any questions Yes Cool. All right. So the question was how would you measure? performance right if as you are introducing these policies right how do you how do you see what's happening? And so there are two things there right one is on the On the opa side of things as you are defining them you can run what we have a Policy benchmarking performance tool built into the CLI so you can actually see like how much time down to like the nanosecond that each policy Takes to run and this is where you can very easily see spikes when you have like nested iteration These become very apparent that certain rules take much longer than expected and then on the other side of that is what you Wanting to kind of measure just end-to-end latency to see if anything has changed with these policies or kind of to Two places that you could look when you are trying to measure what the performance impact is like What do you mean by export? Got it. Yes, and so with dashboarding Yeah, you can you can you can set it up to export information right like opa has management API So you can pull all this information out of Okay, not with that. I think I'm actually at time. So thank you everyone You