 Hey, thank you. So yeah, as I mentioned, this is a talk about using Wasm to deliver policies across your stack. Wherever you might want to run policy logic, using Wasm to do so, that's what this talk is about. So hello. My name's Charlie. I work on the developer relations team at Styra. That involves working quite a lot with the Open Policy Agent project. But the other part of my role is coming out and speaking about OPA and being a proponent for the project as well. If you want to find me, you can find me at any of these places as my email address. And I'm also going to be around at the OPA store throughout KubeCon too. So what are policies? When I talk about policy, what do I mean by that? I think we've likely all got ideas about policies in our minds when I say that word. And perhaps when the most obvious one that comes to mind in a sort of technical sense or a technical use case is these kinds of policies where we're talking about who is allowed to do what. Particular users within an organization can do particular actions. And this is policy that we, as we know it, and as we interact with it on a usually daily basis. But policy, I like to think of policy as a more general sort of business encoding of business rules and functions. So many of you will have flown here to Amsterdam. And you won't have been able to book a plane seat in row 13. It's common for planes in the Western world, at least, to not feature a row 13 at all. And that's a policy that needs to be enforced in a system that handles the booking of plane tickets. And policies can also be pretty unusual or slightly out there when it comes to, we're not just always talking about whether admins have access to certain data sets and so on. So this is an interesting policy I saw just last week. The idea is that a product can only be sold between January the 1st and the first Sunday after the full moon that occurs on or after the spring equinox. And you might be thinking, oh, this is a bit of a joke. In actual fact, there's a brand of Easter eggs that uses this policy to decide whether or not Easter eggs should be sold in the UK on those between those dates. And I was wondering after our talk earlier whether this would be an interesting Shopify plug-in for vendors who had Easter-related goods that they were selling. So the point I'm trying to make here, really, is that businesses are built on policies. And when we talk about policies, often we're talking about business logic. So we need a way to enforce these policies and evaluate policy logic and enforce them. So to try and give a model as to how we might do that, this is how I like to think about policy evaluation. So we've got a policy enforcement point, which is typically a contact point with some user, an application, web app, mobile app, an API, perhaps, that's been interacted with by another automated service. And it's providing some context information and a request to some of the part of either the same application or another application, which is going to make the policy decision. That policy decision point has been loaded with some policy logic and perhaps some extra data that enables it to make policy decisions. And then it returns a decision result to the policy enforcement point, which then deals with that decision as is required. So depending on what you're used to working with, this might look familiar. This is how I imagine that this is how I've sort of structured it for if we were doing policy evaluation in a single application, we might have a web endpoint handler that was making a call to an authorization module in the same application and returning a result for that decision based on some codified rules and perhaps some extra user role data, for example. And we can do a similar thing in a distributed system where we have a business application which is making a call to an authorization server, which may or may not be OPA or something based on OPA, which is loaded in data and policy in order to help it make that decision. So I alluded to where this was going. Like, we need a tool. We need some way of making policy decisions. And this is where Open Policy Agent comes in. So what is Open Policy Agent? What's OPA? It's a cloud native computing foundation project. And it aspires to be a general-purpose policy engine. Going into a little bit more detail, I like to think of it as a sum of these three parts, really. I see it as a domain-specific policy language, which is a declarative language specifically for describing policy rules, which we'll see a little bit more of in just a moment. Policy server implementation, which has the functionality to run a Riserego language and also a series of language SDKs, both a native Go SDK and various Wasm-based SDKs as well. And you bring all of that together, along with some tooling and the community, and you get OPA. At least that's how I like to think of it. So whatever your use case for OPA is, whether you're running OPA as a server or whether you're running OPA within an application, perhaps using Wasm, as I see it, what brings it together is the declarative policy language called Rego. So let's dig into Rego and have a look at some examples. So this is about the most simple policy I could come up with. It's similar to the first one I introduced around admins being allowed to do a particular action. So in this example, we have a package. It's an authorization package. And by default, nobody is allowed by invoking the allowed rule in this policy. By default, the answer is false. However, if the context information that's provided to this policy contains that the role of that call or some user is an admin, then it's allowed. So that's a fairly trivial example, but hopefully it starts to give you a feel for a little bit about how the language works, where we have a default case and that's evaluated if none of the other cases resolve. So it doesn't have to be a Boolean result though. I think it's important to remember that we're often dealing with human users and we sometimes want to help them understand the results of some policy decision. So this is an example policy. It's a deny policy, which is expecting some input containing an email. And I've declared some different rules, some different policy rules around how we're validating this email address. So instead of saying allow or deny in this case, if we provide an email address like this, we see a series of error messages or validation messages back from the policy. The rules that I've encoded aren't particularly exciting. We're doing regular expression validation. We're checking that nobody's using an example.com domain and we're making sure that people are using lower case for whatever reason. So both of those policies we've seen so far, both the email example and this trivial kind of allow, deny, admin example, you can imagine implementing quite trivially in almost any programming language. But I think Rago actually offers some interesting functionality when it comes to writing policies and policy code. And I'm gonna try and show that with this next example. So imagine that you have an organization chart, which is some data which is structured in this way where you have a series of business units, starting with the boss, human resources, developers, interns and so on, and who they are managed by and what they can access. So here the human resources business unit is managed by the boss and they have access to salary information. We can write some more Rago code which transforms that data such that it's in a different format ready for policy evaluation. So in this first snippet, org chart graph, we're creating a series of edges in effect from one business unit to another business unit in our organization chart. So we find some business unit in the org chart and we find the edges based on other members, other business units in the org chart where the managed by value is the business unit that we selected at the beginning. So we're kind of searching through the org chart and building up a series of graph edges. And then in this next example, or in this next snippet I suppose, we are then aggregating the access permissions based on that organization graph that we generated in this previous example. So we find some business unit and we use the Rago built-in function graph.reachable to walk through the graph and aggregate up permissions or gather up permissions from the reachable business units in the graph by finding another business unit in from the series of reachable business units and aggregating up there the access that that business unit had. And that allows us to write a policy that looks like this. So if I have a request, let's imagine that the boss is trying to view salary information. If the organization chart permissions object for the boss unit contains the salary's value, then that request is allowed, that's okay. But if the interns, for example, who don't have access to salaries were to make the same request, they're not allowed. So hopefully you can see that you would need to spend more time with the Rago language to really dig into this, but hopefully you can see some value in Rago for writing policy code. So this talk is really about bringing that to your application with Wasm, with WebAssembly. And there are pros and cons to using OPA and Wasm within your application versus using OPA as a distributed server that you call. But some of the advantages of running it within your application now that you can get very fast feedback, you can standardize logic in places you wouldn't have been able to before, places you couldn't run over before and use the same logic everywhere and potentially get improved performance for data intensive policies. So I'm gonna give a brief demo now where I've got a demo which is based on the booking of train tickets where I've got an example Go application which builds Wasm modules as they are invoked by these two different services. I've got booking API and I've got a JavaScript web client and they're talking to each other over HTTP. And both of these two services are going to be enforcing policy logic which is evaluated as a Wasm module which has been generated based on some rago code. So I'm gonna show that now. So I come here. So this is my demo application where I'm gonna be building my policy. At the moment it's blank but I have some example policies I'm gonna bring in in a minute. This is my server interface where I'm showing the list of bookings that have been completed and this is my example ticket booking application that I've built to simulate what a trained booking UI might look like. So at the moment there's no validation running. No policy is loaded into either the booking client or the booking server. So if I click book tickets it's accepted immediately the request is sent to the server and I have an invalid booking as created in my booking server. We don't really want that. We want to use open policy distributed to these components with WebAssembly to block such requests. So the first thing that I think we're gonna validate is the email, something that we're all familiar with validating perhaps. So I'm gonna bring in some policy to do that just now. Just going to update this. So it's not very exciting. It's similar to the policy we had at the beginning of the talk. We're validating. We're going to deny where the reason where the reason is associated with the email field if we find that the regular expression the email provided doesn't match the regular expression. And we're also going to provide another message if they're using an example.com email address. So I've now updated my policy in my configuration app and I'm gonna enforce this policy first on the server. So if I reload the policy on the server and now submit the empty form again I get a message from the server saying it might be quite small but from the server saying that the email pattern must match such and such. So I'm gonna put my, put an email address in. Let's just test it out a bit and, immediately can't type as soon as you stand up here. So it's running the other part of that rule as well. So I'm gonna change it and put my actual email address in. Still can't type. And now it's been accepted. And if I reload our bookings you can see that my booking has gone through. But we have some other validations that we want to quickly put in place as well. So the next thing I'm gonna validate is these from and to fields. So I'm gonna show you the policy for this now. It's gonna update this. Okay, so we want to make sure that the departure and destination station are different. So we can write a simple rule that says if they're equal we should show a message. We wanna make sure they're both set. So none is the value that is provided if they're not set. We can return another message in that case. But we also want to make sure that we book stations that are within the same area. So the two areas that I have bothered to define are Europe and Japan. You can't take a train from Europe to Japan. So these are my two areas that I'm using. So we're gonna make sure that people book from and within an area. And we do that by using this object and looking up the area for each of the departure and destination station. And if they're different we produce a message. So I'm gonna reload the policy on the client this time. And we'll see that the validation is happening on the client side now. So if I try and book a train from Amsterdam, it says it's now the policy has been evaluated in Wasm and you see the response is immediate. This hasn't gone through to the server. It's been blocked. And it's telling me that the departure and destination station must be set. If I choose Amsterdam to Tokyo, try and book the ticket. It will show me that the route must be within the same area. So instead, let's go to Paris. So now, that booking's gone through. So we've done, we're now doing validation of these rules on the client and on the server. All based on this Rego code. So I've got some other things that we need to validate as well, though. The first thing we're gonna make sure is we're gonna make sure that users submit at least, they need to book at least one ticket. Because if they do book zero tickets, it doesn't really mean anything. And that's very simple. We're just gonna do a simple comparison with a number and check that that's correct. So if I reload the policy again and try booking the tickets, it says that I must have at least one passenger. The other thing that we want to check though, and this is, I've got a slightly more involved policy, is I want to make sure that users are, so on my trains, I imagine that I'm running this train company. Like, I want people to make sure that they book their seats next to each other, so that people are sitting with their friends and that they aren't leaving odd seats out and making the train fill up in an awkward way. So instead, I've tried to define as a policy that says that it'd be valid to book seats that are next to each other, but it wouldn't be valid to book seats that are all over the place. And so what I've done is I've defined a policy which has a seat adjacency matrix, or graph, if you like, where, and I'm going to use that same graph.reachable function which is built into Rego to determine whether or not the booking of seats is valid. So we find the seats that the user has selected, we then go and find all of the reachable seats, all of the adjacent seats to that one, and for each seat that's selected, if we find that it's adjacent to seats which aren't also in the reachable set, then we can produce another error message saying that we have seats that aren't adjacent. So I've updated that, let's update the policy. So if I book my tickets now, it's going to give me a warning, say that I've got to book at least one. So if I book one seat, that's fine, that should be allowed. You can't book adjacent seats if you're only booking one, but if I want to book two seats, and I should be able to book these two seats, that should be allowed. But if I want to book these two seats which aren't adjacent to each other, that should be denied. So here it's giving me a warning saying seat 12, which is this one, is not adjacent to any other selected seats, and seat one is also not adjacent to any other selected seats. And again, it goes without saying, like I can reload this policy on the server, and if I refresh my page, which will clear the policy that's been loaded in the client, and I submit the empty form now, it's giving me warnings, which are coming back from the server. So I'm enforcing that policy, same policy, the exact same policy in two places. So yeah, that's the end of the demo. That's, I think it's interesting to see how you can distribute the policy as a wisdom module relatively easily to different applications in your stack. I'm just going to jump back to my presentation. So, I want to just take a little bit of time to talk about WebAssembly in the OPA project, and what the history is, and the state of affairs, where we are today, and maybe give some ideas for how people might be able to get involved. So, as this comes with a disclaimer, this predates my involvement in the OPA project, it predates my joining Styra and working full-time with the OPA project. So this has been a little bit of a history lesson for myself in working out how this is pieced together. So rollback to 2018. We have this idea, OPA is this open policy agent. It runs adjacent to applications in a distributed system, and you call it over a local connection, over an HTTP API. This poses a challenge to some users, and it poses a challenge to the goal of being a general-purpose policy engine, which you can use everywhere. Everywhere also includes places where you can't run an arbitrary server container or something like it. I think a good example is a CDN. So, and around this time, we're starting to see some of the content delivery networks provide functionality based on wasm, and when, I suppose the writing then is on the wall saying, look, you're not going to be able to run OPA everywhere. OPA is not going to be able to run here. And so I suppose that was what kicked off the creation of this functionality in OPA. At the same time, like the initial proof of concept that we developed, we saw some good performance improvements for data-intensive policies, which I suppose pushed it on to getting this merged in and into something that we're actually working with and using and adopted in the project. And that also triggered, I suppose, being able to develop the first Node.js SDK for OPA wasm modules. At the moment, we now have the wasm support. It's available. It's ready for people to use in OPA today. We also have a range of SDKs for specific languages. These are the languages that we support today. I've made use of the Python SDK, which is a community-developed OPA wasm evaluation module. I've also made use of the Node.js one, which is officially implemented. And we have good support, depending on whether you have a glass half empty or half full view of the world, good support for the range of the Rego built-in functions. Looking forward into the future, I think it's an interesting point to end on and particularly for this audience. Based on this morning, there's a lot of wasm expertise in the room. And it would be exciting for me to speak to some of you who are interested, if there are any of you who are interested, as to how we might move the wasm support in OPA forward. So the way that OPA works is, in the servers, we load in potentially quite a large amount of data and then have multiple threads of policy evaluation running at any one time, operating on that same data. I think this is an interesting use case for wasm threads. That's something that wasn't really available when OPA was initially implementing wasm support. That's the first issue. Native support for support for Envoy filters. We don't have that at the moment. We already have a lot of people who are using Envoy and OPA together. That would be a really great feature for a lot of them. That's the issue for this one. And also, I think flipping that around, also, we had to talk earlier about extensions and a generic extension interface based on wasm, like being able to extend the regular language, being able to extend OPA perhaps in other ways with WebAssembly is another really interesting idea and that's the third issue that I linked to there. Of course, there's always the list of to-do built-in functions as well. As I say, new contributors would be very welcome. So, yeah, if you want to get the slides or any of these links, this first link, I kind of aggregate them all there. You might want to go and read the OPA docs. My colleague Anders has an awesome OPA list which contains a list of links to various other OPA wasm projects, including the SDKs that I've used today. The code is available at the top of the first link and that initial proof-of-concept blog is available on the Open Policy Agent blog as well. And just a little shout-out, we have an OPA meet-up this evening. I checked before lunch and there were still some spaces. So if anybody's interested, please come along to that as well. So again, you can find me at these places. I'm going to be around or KubeCon. I'll be at the OPA store a fair bit. Thanks very much. Thanks for listening. Yes, this was absolutely fantastic. And I think one of the things I love about this is it really shows the power of WebAssembly, of being able to execute the exact same policy on your front end and back end, down to the literal bites if you want to, shows just how powerful this stuff freaking is. So this is amazing and I definitely have questions but I want to open it up to the audience. Anyone here have any questions about anything that was just discussed here? This is really amazing stuff. Please go ahead and introduce yourself. Hello, I'm Roman from Cosmonic. So I don't know if you've looked at component model at all and wasn't yet, but so one thing currently missing from like with interfaces is something like validation, for example, of your data structures and maybe some more complex policies you could add and like when you can call this function you cannot call this function with kind of arguments, you know, like things like that. So could like the technology you showed be used somehow, maybe close to say, or you can think like say protobufs and there was like protogun validate and not if you used protobufs before but like it's also something like you could like add the notations to validate fields and whatnot. So could this technology be used somehow maybe together with width and close and to kind of validate things on the fly, could it be like a layer in between, you know, between the request going to the host or validating stuff? I think potentially, but maybe not right away. I think like if I'm correct, your question is about sort of using this as a sort of pre-validation step based on some known schema of input. Yeah, so actually a relatively new feature to land in OPA and in Rego, but the go runtime for Rego is JSON schema validation. So you can say if this object that was provided as input to the policy isn't conformant with this JSON schema, then return a result in the same way that I was using these built-in functions here. That's not supported in wasm yet in the way that we've implemented. You could always, we could either support it by adding those functions as external to the SDKs or we could add it to wasm, but it would involve some C code and I'm not sure exactly what's available there in order to do that. I think that's probably like how I would imagine solving that problem, but there may be other ways you could do that as well. I suppose if you wanted to make manual checks against input, you could obviously do that, but JSON schema, I guess, is how we often see people wanting to do that. So yeah, kind of maybe I guess on the answer, I guess, I don't know if that answers your question. It does, yes, thanks. But so like maybe like a quick follow-up. So but you validate JSON then or what is the format of this data? Yeah, the data for OPPA is JSON. Yeah, it's all based on input and output JSON data. Yeah, I'm not familiar with any other. It's all pretty heavily based on JSON at the moment, yeah. Any other questions from folks? All right, and especially like for me is a language narrative. It's so cool to see a declarative language just compiled straight to WebAssembly modules. This is absolutely fantastic. But so can we all give it up again for Charlie? This is fantastic. Thank you so much. Thank you.