Very simply, "principal" is just a fancy term for a user. For most applications, the terms "user" and "principal" are interchangeable because the application is only ever used by humans. However, Cerbos is not just for authorizing humans; it can also be used to authorize access from other applications, services, bots or anything you can think of. Therefore, we prefer to use the proper computer security term to make that clear.
A resource is anything that you want to control access to. If you are working on an expense management system, some examples of resources would be expense reports, receipts, card details and payment records. You have to define the access rules for a particular category of resources (such as all your receipt objects) by writing a Cerbos resource policy for that kind (receipt). Then you can check access to specific resource instances (say, receipt numbers X12345
and Y54321
) by asking Cerbos to evaluate the policy in the context of those objects.
An attribute is a piece of information about a principal or a resource. Attributes are free-form data specific to your application that are important for making access decisions. Cerbos is stateless, which means that Cerbos doesn’t have a copy of your data. So, when you ask Cerbos for an access decision, you have to provide all relevant information about the principal and the resources as attributes (for example, location=us
, status=pending_review
, quarter=2
).
If you’re used to traditional authorization approaches, you’d be surprised to find that Cerbos is not a library that you can embed into your application. Instead, Cerbos is designed to be run as a sidecar or a service alongside your application. There are several reasons why we have chosen this approach. To provide a bit of background, let’s consider how modern software development works in the era of cloud native computing.
Nowadays, the trend is towards microservice architectures where system functionality is split between multiple services that are fairly independent of each other. They are probably owned by different teams within the organization and even developed using different programming languages and tools. Automated CI/CD pipelines deploy new versions of these services many times a day.
In these dynamic, polyglot environments, the emergent pattern for providing cross-cutting concerns such as service discovery, resiliency, observability and security in a standardized way is through the use of sidecars or other microservices. Frameworks such as Dapr and service meshes such as Istio and Linkerd are examples of software that employ this pattern.
Authorization is one of those cross-cutting concerns that needs to be standardized and centrally managed across the organization. If authorization rules for the same resource are even slightly different between two services, then that creates a security issue. In a polyglot environment, the implementation of access rules would be duplicated between each programming language. This is a waste of effort and an inevitable source of inconsistencies and bugs due to how programmers interpret the specifications or how the particular programming language deals with certain data types or special cases.
Changing access rules for the whole organization requires coordinated effort to develop, test and roll out those changes across the whole fleet. Debugging authorization problems in such an environment is quite difficult because no one has overall visibility of the whole system. The access logic is hidden away in code in multiple repositories. Unless the developers have been extremely disciplined, the quality of debugging aids such as traces, audit trails and tests would vary wildly as well.
Cerbos is designed to address most of the above problems:
By not having to worry about wrapping and shipping Cerbos features into language specific, embeddable libraries, we can focus our time and energy into optimizing the product and building new features using a smaller set of libraries and utilities provided by the language of our choice. We can test these features much more thoroughly because we have full control over all the integration points. We don’t have to be concerned about integrating or being compatible with an almost unlimited set of libraries and frameworks available for every programming language. And we don’t have to expend effort figuring out how to share common code across different languages, fight with language quirks and performance hotspots like foreign function interfaces and concurrency primitives.
We've seen the benefits of these decisions in the ease of integration for our users, but also in our own development velocity.
To stay up to date with all things Cerbos, or if you have any questions or comments on the above, please head over to our Slack community - we look forward to seeing you there.
Thanks for reading!
Book a free Policy Workshop to discuss your requirements and get your first policy written by the Cerbos team
Join thousands of developers | Features and updates | 1x per month | No spam, just goodies.