 Hello, my name is Omri Gazeet. I'm the co-founder and CEO of Acerdo, an authorization company. And I'm very excited to spend the next 30 or so minutes with you talking about fine-grained authorization and why everybody's so excited about it. First, a little bit about myself. I've spent well over three decades building software for developers, the last 15 years of which were really focused on cloud platforms, and identity and access in particular. I love doing startups. This is my third startup. And when I'm not start-uping, I'm skiing. I was super fortunate to have worked on some really cool projects over my career. I was one of the co-founders of the .NET project at Microsoft, as well as the Azure project, where I worked on Azure Access Control Service that became Azure Active Directory. And then the last 10 years, I spent a lot of time in the open source space working on things like OpenStack, and specifically I am an OpenStack, Cloud Foundry, where I was a board member, Puppet, and Kubernetes. So let's start by talking about the differences between authentication and authorization. Some people talk about them as being the same thing, off, but they really are two distinct processes. Authentication is really about proving that you are who you say you are. So in the old days, we used to do it using emails and passwords. And these days, we have password lists and biometrics and magic links and two-factor. But ultimately, it's the same process. And the ecosystem at this point is pretty mature. We've had standards in the space for almost 20 years now. SAML is the OG, the original gangster of single sign-on standards. And OpenID Connect has been around for about nine years. OAuth 2 a little bit longer than that. And we also have some fairly mature developer services. So you can use Octa or Auth0 or Azure Active Directory or Cognito to be able to implement login without having to write it yourself. In fact, no one writes login anymore. Everybody uses a developer service. So this is mostly a solved problem for developers. Authorization, not so much. Now, authorization is once you're logged in, what can you do in the context of this application? And specifically, do you as a user have this particular permission on this particular resource? Now, there are not any real standards in the space as of yet. Certainly, there are patterns like RBAC and ABAC, which we'll talk about later. And there's also no implementations at scale, at least, of developer services. Every framework, every language has a set of libraries. Every framework has a set of libraries that help you build authorization. But really, every one of these implementations is fairly inconsistent. That creates a lot of problems. The first one is bad security. And the case in point is that number one on the OWASP top 10 list of application security issues is broken access control. So they've tested a whole bunch of applications and a whopping 94% of the applications that they tested have had some sort of broken access control vulnerability. So this is a huge problem in terms of security. Now, not to mention the fact that if every microservice implements permissions differently, you have a bunch of inconsistency in the application. And it's really hard to reason about the authorization surface area of your application. Not to mention the opportunity cost. Imagine that you had to go build login by yourself or text messaging or payments or things like that. That's just a whole bunch of wasted effort. And that is unfortunately still the state of the art with authorization. Every application essentially rolls their own. Now, things are not all bad. It turns out that a lot of technology organizations in the last couple of years have been looking at authorization as something that they need to centralize. And they've been giving it to their platform services teams or central services teams to go build a single consistent implementation. And they're writing about it. So a lot of technology organizations have written papers or blog posts or have given talks about how they do authorization. And if you look at all the different patterns that they've written about, they're really five that bubble up to the surface. And we contrast those here with some of the old school or anti-patterns. The first one is that each service does its own authorization. This one's kind of obvious. And the modern best practice is that these technology companies are basically empowering their central services teams to go build a purpose-built authorization service that all the other microservices can actually go rely on. The second anti-pattern is to use coarse-grained roles that are baked into the applications. And the modern best practice is to replace that with fine-grained access control, really adhering to the principle of least privilege. What that principle means is you want to basically give as much permission to the user as they need to be able to do their job, but no more than that. And the reason why is because if you have a compromised identity, you want to limit the blast radius of what that user can do. And so it just makes sense to lock down permissions as much as possible. And that really is the impetus for fine-grained access control. The third one is that you find in the old school way of doing things, authorization built as a bunch of if and switch statements in each of the microservices. So authorization spaghetti code is what we call it. And the best practice is to extract the authorization logic out of the microservice, out of the application, and store and inversion it separately, really achieving a separation of concerns that enables, in turn, another important security principle called separation of duties. So you have the application developers worrying about the application code. Then you have people who really reason about the authorization surface area able to go look at all the authorization policy altogether and figure out whether that authorization policy makes sense. The fourth anti-pattern is treating scopes that are baked into access token as permissions. And the modern best practice is to make a real-time call to an authorization service right before you want to grant access to a protected resource, a real-time access checks. Why is relying on scopes baked in access tokens bad? Well, for a number of reasons. First of all, they basically have a lifetime. So as soon as you mint that access token, it's good for two hours or two days as long as that access token is good for. And so if you want to actually take away permissions, that's not quite possible without token revocation, which is a really complicated thing. If you're making a real-time access check right before you grant access to a protected resource, you don't need to rely on essentially kind of stale tokens. The other thing that these tokens don't really give you the ability to do is fine-grained access control. So let's say that you wanted to grant somebody the right to read a document. If you put a read document scope in an access token, well, the calling application can go look at that scope and say, OK, the user can read a document. But which document? All the documents? Are you going to go create a scope for every document that the user has access to at login time? Clearly, it's just not a scalable practice. And then lastly, most applications, sadly, barely even have a trace of the folks who have logged into them, much less any kind of fine-grained auto trail of what users have done in the application. And the modern best practice is to have comprehensive monitoring, basically record the decision log for each decision that the application made and be able to centralize that for compliance and forensics. Again, a breach is not a matter of if. It's a matter of when at this point in time. And so once you detect that something happened, you really want to know why it happened. You want to have the forensics to figure out how the application did the authorization, what the application authorized the user to do. And of course, it's also very important for compliance. You need to be able to prove that users were only able to do what they were allowed to do within the scope of the application. Great, so let's dive into each one of these. The first one I want to dive into is this idea of purpose-built authorization service. It seems like it's the new hotness. Everywhere we look, there's some tech company that's writing a paper about it. So it started out about three years ago with Google, writing about their Zanzibar system. Zanzibar is basically their distributed system for access control for a wide variety of Google services. Google Docs, Google Drive, Google Calendar, Cloud, and so on and so forth. And it's a large-scale, planet-scale service. And one of the things that they've done is they've created, essentially, this new model that they coined the term relationship-based access control for. And we'll talk about that in a couple slides. Intuit, built one that's based on a different set of principles, more of an attribute-based model. Himeji from Airbnb was inspired by Zanzibar. In fact, the architect for Himeji was one of the folks on the Zanzibar team. Steve from Carta was also inspired by the Zanzibar paper. Netflix is, again, more of an ABAC model. So we have different types of implementations, but all these folks are basically building these centralized services and so that every one of their application teams doesn't have to reinvent that wheel. The next principle is fine-grained access control. And so let's go down a trip down memory lane here and talk about how that's evolved over the years. So back in the 80s and 90s, we had Unix systems and later on Linux systems and NT. And those were lied on access control lists. Basically, the type of question that you answered with an access control list was, does Alice have read access to this file? A file system had read, write, and execute bits for users and groups and other. And that was basically the as fine-grained and access control models you could get with Linux systems. Now in the 90s and 2000s, we saw this new idea called the directory. LDAP, and later on Active Directory, basically ushered in this idea of role-based access control. So roles were typically implemented as groups. So you, for example, had a group in LDAP or Active Directory that you put users in. And that would correspond to a role in a business application. And you could answer questions like, is Bob in the sales admin role by seeing whether Bob was in that group? You had this idea of nested groups. And life was kind of simple but pretty clunky and very much course-grained. The problem there was that you had this group explosion where at Microsoft, I remember we had, let's call it, 50,000 users at one time and 250,000 groups. So it was impossible to reason about what permissions users actually had. In the 2000s and 2010s, we had this new idea called attribute-based access control. And the idea there was that you basically computed access control decisions based on attributes, either on the user or on the resource, or even environmental attributes. So you could answer questions like, is Mallory have access if Mallory is in the sales department and the document is in the sales folder and it's currently working hours? So you could write a policy that evaluated all those attributes and gave you a yes or no answer. The original system that implemented this was known as ExactMall. That's kind of like the original gangster of the ABAC systems. And of course now in the last five years, we've had successors to that and I'll talk about that in the next slide. And lastly, we have relationship-based access control. Like I said before, it actually predates the Google's ends of our paper but Google really repopularized that model. And the idea is that you basically have relationships defined between subjects and objects. So for example, a subject like Eve is a user and she can be in a group and that group can have say view access on a folder and there can be documents inside that folder. And so we can answer questions like does Eve have read access to this document by chasing the edges that link between that subject, Eve and the object, that particular document and see whether those edges carry the read permission. So after the history lesson, let's fast forward to the present. Over the last five years, we've seen two different ecosystems emerge around fine-grained authorization. The first one I call the policy as code camp and the flag bearer for that is the open policy agent project which basically started from the ABAC view of the world. And so there's a lot of stuff going for it. It's a CNCF graduated project that graduated about two and a half years ago. So there's a single mature open source implementation. It's a general purpose decision engine, fairly flexible and primarily used today for infrastructure authorization scenarios like Kubernetes admission control. And it's really tailor made for policy-based access management and ABAC. It's essentially the successor to XACNL. Now there are some drawbacks as well. The language has a high learning curve. So unless you're a prolog head, this is a side effect free data log derivative and you have to kind of go build your authorization model from first principles. It's really an unopinionated language. So you have to kind of design your authorization model from scratch. And it's a little like, you know, writing something in the Semblr language. And furthermore, you really don't have much help with how to manage data in the system. OPA has an effective policy plane, but it doesn't really have a data plane. So if you want to start with OPA, you have to kind of roll that out on your own. On the other side, there's the Zanzibar model. I call this the policy as data camp. And like I said before, Google built their model over an abstract model called REBAC, relationship-based access control. They didn't invent it, but they certainly popularized it. If OPA has no opinions, REBAC has plenty of opinions. It's a very opinionated model. And the idea is again, like I said, you're modeling your access control rules essentially as data, as a set of relationships between subjects and objects. And so if your domain looks a lot like Google Docs, you have subjects like users and groups and objects like folders and files, you can very much use this as an opinionated model that you can start from. Now it's a fairly immature ecosystem. There are at least half a dozen competing open source implementations because Google didn't open source anything. They didn't even write a spec. They wrote a technical report. So there are a bunch of different open source implementations at this point. And they don't really share any common schema language or a common data language. And it's also hard to extend the REBAC model into attributes, although some of these projects are starting to do that. They each do it in kind of an inconsistent way as well. Now, fortunately, there's a third path. We call this the don't succumb to the tyranny of the or. A lot of people think of these as competitive ideas, but we think of them as complementary. And so Topaz is a project that a sort of my company maintains. But the idea there is to take the best of both worlds. You take the decision engine from OPA and so you have a policy-based access control model that supports attributes. And you take the Zanzibar directory and you kind of put them together in a single open source project that's delivered as a single container image. So here I have a reference, a URL to Topaz. Go check it out. The QR code will also take you to the GitHub repo. The next principle I want to talk about is policy-based access management. And as a reminder, this is the idea of lifting the access control logic out of the application where it's expressed as if or switch statements. And instead expressing it in its own domain-specific language and storing and versioning it as code just like any application artifact. So we're here to have a policy written in Rego which is the surface syntax for the open policy agent. This happens to be a Topaz policy because it has a little bit of an Easter egg here that basically makes a call to one of the Topaz built-ins that computes the policy based on a relationship between a subject, the user, and an object, one of their reports. So this policy has two allowed clauses, one of them uses attributes. So basically you're allowed if the logged-in user's property is a department property, I should say, equals operations or you're allowed if you're the manager of this particular user. And so it's important to note that it's not just OPA that adheres to this principle. Any Zanzibar-based system also equally believes that you should extract that policy logic, don't express it as if in switch statements inside of your application, instead store and version it as a domain model. But what does that get you? Basically, instead of having to go, again, like I said, write if we're switch statements to express authorization logic, you can go use a middleware. So here we have this checkout Z middleware that we've placed in the dispatch path of this route handler for this node.js, this express.js route handler. And all we have to do is just tell the developer to make sure to call that middleware. That middleware makes a call to an authorization service that computes a decision. If that decision comes back as access denied, the whole route gets basically returns an access denied, otherwise you dispatch to the next handler here. What does that give you? It allows you to store and version that policy artifact just like you do application code. And every policy change is part of a get change log. So every access control change that you wanna make in the policy is logged just like any other get change. So that means that the policy can evolve from using a different team. So a different team like the security team can own that policy and it's decoupled from the application logic. The application delivery team doesn't have to worry about how to evolve that access control logic. And the security team can reason about the entire surface area, authorization surface area of the application. Lastly, we think of these policies as something that you should treat just like any application artifact. So application code, you build into an immutable image, typically a docker container. That's how you distribute it. And that's the same thing that you should do with policies. You should build them into OCI images and sign them using something like cosine to secure the software supply chain for these artifacts. And in fact, here I have a reference to a project called the Open Policy Containers Project which is a CNCF sandbox project. A service also involved with that. And you can build not just topaz policies but also any generic OPA policy into a container image, sign it with cosine and verify the signatures. And lastly, I wanna talk about real time access control. So this is where I kind of go into my infomercial about authorization actually being a distributed systems problem. And I'll explain what I mean by that. You really need to do authorization locally. Authorization is different than any other developer service because if you think about things like Stripe or Twilio or even Auth0, those are hosted services and it's fine for them to be hosted because you basically make a call to them and it's important that that call complete and it's important that they maintain a high SLA but it doesn't really matter if it happens in a second because it turns out that it's not really in the critical path of every application request whereas authorization is, if you're doing it correctly, you're basically making a call to the authorization system right before you grant access to a protected resource and that can happen one or more times for every user request. So it's gotta be fast. It's gotta be done in around a millisecond and it's gotta be 100% available to the calling application. So it can't really be a hosted service. But you also wanna be able to manage all of the policies and the data that's used for authorization in a centralized manner. So you really need to have some kind of control plane that allows you to manage the life cycle of policies and as well as all the data, all the user and group and resource data that are used for policy decisions and relationships and be able to mediate those decision logs back to a centralized control plane. So data about users comes from an identity providers, data from the source code for policies comes from a source code control system and then decision logs really want to end up in your scene tool, in your log aggregation tool. So you really need kind of this central control plane that allows you to manage all this stuff at scale. So as we bring this presentation to a close, I wanna close with what we call the five laws of authorization. If you're building an authorization system for your entire organization, you wanna have it have the following five properties at the very least. You wanna be fine grained and you wanna be also flexible enough to support all the different types of authorization models. So RBAC, ABAC, REBAC, any combinations of them. You wanna make it policy-based. So you really wanna make sure that you give the opportunity to the application developers to not have a bunch of switch and if statements in their code and instead allow them to extract the authorization policy out of their applications and store and version it as its own artifact that you can actually go build into a signed image. Make sure that authorization is done in real time as a local call executing over fresh data. And yet you wanna have central management of the policies and all the resource data that are used in authorization decisions. And finally, you wanna aggregate, centralize and aggregate all the decision lines that come out of these authorization requests so that you can use those later for compliance and forensics. And if you're building a system like this, you also want some non-functional requirements. You wanna make it super easy for your developers to adopt. So you wanna have a system that allows you to do authorization to an external system with a single line of code. You wanna be able to have it integrate with all of the systems you already have. So identity providers, source code repositories, artifact registries, logging systems. And finally, it's important for it to be open. So you get a lot of ecosystem effects from betting on Kubernetes native technologies like Open Policy Agent and Topaz. Now, this is a lot of work to do and fortunately there are some places to start. There are open source projects that you can start from. OPA is one of them. Topaz is one that I've talked about as well. It's the project that my company maintained. So we're very partial about it. This is a QR code for getting to the repo. And Topaz, we'd like to say that it's fast, flexible and easy, fast. It does authorization in under millisecond, flexible. It supports all the different access control models, all the backs as we like to say are back, aback and reback. It runs in any cloud. And finally easy, it has SDKs, it has GRPC APIs, it has REST APIs, GraphQL APIs, SDKs from every language. So it's super easy for your developers to incorporate no matter what language they're using. And lastly, my company, Asurdo, basically builds commercial solutions for authorization. So if this is not something that you want to roll out by hand using open source, we're happy to provide you ready-made solutions. Thank you so much for listening over the last almost 30 minutes. Please come find me on social, Omri G at Twitter. Omri at asserto.com. If you have any questions or comments, we'd love to answer. Join our Slack, it's at asserto.com slash Slack. Check out our repo. That's asserto-dev slash topaz on GitHub. And let us know what you think. Thank you so much.