Transcript
This transcript was autogenerated. To make changes, submit a PR.
Hello everyone and welcome to my session.
Today we will talk about Polisys code and how to use this approach
to build RBAC and OpenPolicyAgent.
Let me introduce myself.
My name is Graziano Casto and I'm a Developer Relations Engineer at MIA
Platform, an Italian company that, among other things, is the creator of
the tool we will be discussing today.
Feel free to check out my website and follow me on LinkedIn.
Before diving in, let's start with the basics and understand
what we mean by policies.
When we think about policies, we often immediately associate
them with roles and users.
And this is correct.
A rule that governs a specific role access to a particular
resource is in fact a policy.
However, even an instruction that defines the behavior of a system based
on the value of a certain property can also be considered a policy.
And applying this to real life, even rules like the age limit for purchasing alcohol
can, in a way, be considered a policy.
In general, a policy is simple.
simply a set of rules that govern the behavior of a system by describing the
invariance that must hold will in it.
Policies are not necessarily limited to the world of authorization.
Authorization policies are just a subset of a broader category and they specify
which users or machine of course are allowed to perform certain actions or
on specific resource within a system.
The first thing we need to think about when considering API
authorization is which strategy to use.
There are different strategies to define the access control on our system.
Let's take a look at a couple of them.
Let's take the example of an internal developer platform.
In this context, we may have senior developers who are allowed
to access project configurations, commit changes and deploy them.
Then we have a group of junior developers who are allowed to access
the project configurations and commit changes, but not deploy them.
And finally, we have the platform administrator with full permissions.
They can do everything senior developers can do, but in addition,
they can also create new projects.
In this situation, even if we used a simple example, scaling by
directly assigning each user the specific set of actions they are
allowed to do becomes really complex.
One way to simplify this process is by categorizing users into roles.
This way, we only We will only assign the user to a role and the permission
will be inherited directly from the role.
This means that whenever we need to add a new user to the platform, for example,
we just need to identify its role.
And if we need to add the new features that require new permissions, the
only thing we need is to assign this permission to the roles that require it.
In this way, all the users associated with that role will inherit the permission.
This strategy is known as Role Based Access Control, RBAC, and it is useful
for abstracting out the complexity of assigning permission to users by using
an intermediate level of assignment.
Another popular strategy is called Attribute Based Access Control,
ABAC, which focuses on the use of attributes instead of roles.
In this access management strategy, each user is directly assigned to
attributes, which are used to determine whether the specific user's methods
certain conditions for accessing a resource or performing an action.
Both strategies have their pros and cons.
On one hand, the airbag strategy is certainly simple, but compared to an
ABAC approach, it lacks of granularity.
On the other hand, using attributes allow for more granular
definition of access points.
specific access, but implementing such a strategies requires more
time and expertise to define correctly the attributes you need.
The ideal solution could be to use a hybrid approach, using roles for
a high level access control and then using attributes for more granular
management of access to specific access.
Let's look at some example of this hybrid strategy.
Suppose our users have roles and corresponding permissions as
described in the previous example.
And we have also assigned them attributes like the environments, which describe
the environments they are allowed to work on, and the project, which is
the list of projects they work on.
In this case, a senior developer having the permission to deploy
as part of their role will be able to deploy to any environment for
the project they are assigned to.
On the other hand, the same senior developer will not be able
to deploy anything to projects they are not assigned to.
In other words, even If they inherit the deploy permission from their role, if
they don't have the project attribute associated, they will not be able to
deploy any changes to that project.
Now let's analyze the case of a junior developer.
They don't have the permission to deploy, so it doesn't matter which
projects they are assigned to.
They will not be able to deploy any changes to those projects.
In this case, if we want to give a specific junior developer the ability
to deploy changes, but only to the dev environment, for example, for the project
they are assigned to, a poorly error back approach wouldn't allow us to do that.
However, with this hybrid approach, we can assign the
environment attribute to the user.
Even if the junior developer doesn't have the deploy permission in their
role, by assigning them the development environment attribute, we can make an
exception that allows them to deploy only the development environment for
the projects they are assigned to.
This provides a more flexible and granular way to manage access to specific, specific
assets like the environment and the projects now that we know the strategies
available to us and all that's left to figure out how to implement them.
The old approach of keeping everything inside the code base works well and
that's why it is always being used.
This approach involves having the code responsible for enforcing the
authorization policy co exist within the same code base and the same
code base as the business logic.
Handling authorization this way has its pros and cons.
On one hand, it's convenient because it is the simplest and
quickest solution to start with.
Start developing our system.
On the other end, it exposes to several problems such as the repetition, for
example, if the same policies need to be used in other services, especially
in a distributed application, it has to be repeated and this lead
to difficult code maintainability in the larger scale application.
A better way to manage our policies is to decouple them from
the code base that contain the business logic of our services.
The way to do this is by adopting a policies code approach.
this is involved, this involves, extracting the policies definition code
into a separate repository from our application code and using an agent that
sits between our APIs and the users to handle the enforcement of these policies.
The tool that allow us to do this is Open Policy Agent, OPA, an open source
tool graduated by the Cloud Native Computing Foundation, the CNCF, and
it provides an high level language called RIGO for defining policies
and an agent for the enforcement.
What you are seeing on the screen right now is a snippet of a simple
regopolicy that only authorizes post requests on the slash order route,
where the value of the store property inside the body matches the store
assigned to the user making the request.
Returning to the previous example and implementing it to using Rigo for policies
definition, what we would have is that all the code in our code base responsible
for enforcing policies is managed through Rigo code, outside our code base, okay?
This way the policy enforcement logic is decoupled from the business
logic of our services and managed independently, making the system
easier to maintain and more flexible.
By analyzing the Rego policy code, we have these two allows blocks,
which are the actual entry point for the authorization logic.
With each request, if one of these two blocks returns true,
then the request is authorized.
These blocks use functions defined above to evaluate, for example, the
role of the user making the request.
To retrieve the user's role, the JWT token is decoded.
Which is retrieved from the editor of the request itself.
This approach does indeed add a first level of decoupling of
decoupling, of the policies from our code base, of our code base.
However, the problem is that hope can be deployed as arrest service,
which means that our application with.
We still need to communicate with the services, with the service, and
therefore a minimal level of coupling remains in our application doing so.
So we want more, we want to do better, to do it better.
And to further the couple, the policy from our code base, what we can do is
using R Round is an open source project, is a lightweight side car container for
API protection that used OPA and Rigo for authorization policy validation.
natively allows building airbag solutions by defining the concept
like roles, permissions, user groups as binding blocks inside the project.
For its configuration, ROND uses open policy, open API compliant files.
Therefore, to add RON to our project, all we need to do is modify these
files to add the XRON property to the routes that we want to protect.
Inside this property, we will declare the name of the regopolicies that we intend
to use to protect the specific route.
We just need to do In addition to protecting routes with
authentication rules, ROND offers two other powerful features.
The first one is query generation, which allows us to filter the results.
response of our APIs before returning it to the client.
In this case, we can define a policy that will be executed before returning
the result to the client, allowing us to filter the response dataset
we will return to the client itself.
The second feature is the ability to define a policy that modify
the structure, the response schema before returning it to the client.
In this case, let's suppose, I don't know, we have the response
payload for our request to fetch the customers of our application.
Using the same endpoint, for example, the get slash users, we can use run to
ensure that, Power users, so the user with more privileges, can access the full
payload, while users with fewer privileges receive just a filtered payload, without,
for example, sensitive information.
Now, we get to the point.
Let's start, let's talk about why ROND was created and how
it is used at large scales.
At MIA Platform, we created ROND to manage the entire authorization flow of our EDP.
And it is also provided as an authorization mechanism for the
workloads managed by our platform.
From our clients.
For the ADP alone, ROND is currently running on more than 30 microservices,
managing over 5, 000 policies across more than 300, 300 routes.
ROND is a project designed to be integrated into existing distributed
application without the need to modify the existing services thanks to the use
of the sidecar pattern and the open ABI specification compliant configurations.
This design make it easy to integrate into existing system by design.
ROND also exposes various metrics to track the usage of policies, such as the
number of time each policy is used and the average evaluation time from them.
additionally it provides metrics to monitor the resource usage of the
sidecar container, including resource utilization at the container level.
We have reached the end of the presentation and thank you for following
me this far and I invite you to connect with me on LinkedIn and start using Roam.
Thank you all and see you next time.