Getting started
Start to learn the main concepts of Mia-Platform and how to use to develop your services
Start to learn the main concepts of Mia-Platform and how to use to develop your services
Discover more
Discover all the benefits of becoming a Mia-Platform's partner entering the program.
Discover more
When it comes to managing enterprise data in a platform used by many different people, sooner or later, you will face the need to have these people work on a restricted set of data with a different set of capabilities. For example, some users may need read-only access to data, while others may require write access to only certain resources or APIs; lastly you will surely need people with administrative capabilities on all of the available resources.
There is an authorization mechanism that is designed for such cases, and it’s called Role‑Based Access Control (RBAC). In this article, we will cover how we implemented this solution within Mia‑Platform, and how we faced all the challenges that such a solution brought us.
RBAC is an authorization mechanism that defines the concepts of Roles, Permissions, and User Groups as building blocks. These building blocks allow you to create your access‑security model based on the real function that people have in your organization, rather than the specific actions they need to perform.
RBAC is often mentioned together with Attribute‑Based Access Control (ABAC), another authorization mechanism built on top of RBAC. ABAC allows you to define your security model also on user or request attributes, that may include things like the location, timezone, authentication mechanism, device type or any cookie that the user has while accessing your services.
RBAC is now one of the most popular access control models. Although in the design phase an in-depth study of permissions is required, once in place, RBAC brings several benefits:
So, why did we choose to adopt RBAC at Mia‑Platform?
Within our platform, users can perform several actions: they can view and collaborate on different projects, configure their microservices, create new repositories, view consumed resources, restart Kubernetes Pods, and so on and so forth. It is obvious that we can’t allow anybody to perform any action without making sure they can actually do it because it is their job or responsibility.
Here are the main steps that brought us to define how to build the RBAC.
For this reason, we started modeling our RBAC solution by identifying Permissions and Roles we already had in our platform, in order to create the entities on which the RBAC should have been modeled.
Identified Permissions were:
Identified Roles were: Project Administrator, Editor, and Viewer.
For example, an Editor can view project information, can perform deploy operations, but cannot manage secret variables, since we want this responsibility to be held only by the Project Administrators.
Now that we have modeled our RBAC entities, we had to integrate it in our software, but how could we do it? We had to face many challenges before finding a definitive answer on how we wanted our RBAC to work.
The first issue we had to address was that we did not want to embed authorization controls in each API. In fact, this would have meant having repeated code within our software, and also having to distribute authorization configurations throughout the code, leading them to be hardcoded and hard to maintain in the long run. Also, our APIs are developed across several microservices written in different languages; so, the controls should have been written in different languages, and thus becoming harder to abstract in software libraries.
For this reason, we wanted to move RBAC outside our current codebase. This first decision led us to our second issue.
Since RBAC was managed outside the microservices, there should be another microservice in charge of this. Developing a RBAC service that every other service has to contact in order to find out whether to authorize or not the incoming request could have been a viable solution, but any design that had the standalone RBAC manager API led to an architecture suffering for a single point of failure.
For this reason, leveraging Kubernetes Pod definition, we decided to adopt the Sidecar Container Pattern: every service in need of RBAC had to host an extra container in charge of implementing the authorization controls. The sidecar container intercepts all the incoming requests, and proxies them to the actual microservice only if authorization controls are successfully passed.
Now that we’ve found a viable solution for our architecture ‑ that is language agnostic and has no single point of failure ‑ we had to yet address another issue: how shall the authorization controls be defined and implemented?
We did not want the configuration to be decentralized because it could get hard to maintain. At the beginning, we thought about a possible solution: to implement a service connected to a database, where it can perform a query to fetch the user permissions, and then reject or accept the request.
However, we found that this solution could limit what we could do with our RBAC. What if we wanted to implement a specific permission that allows the user to manage certain properties of a document that otherwise are kept reserved? This solution wasn’t enough.
For this reason, we decided that our RBAC service would need to support some user‑defined policies to evaluate whether the request shall be accepted or not. Since we didn’t want to implement a new language for policy evaluation because it would have been long and expensive, as well as difficult to maintain, we decided to adopt Open Policy Agent (OPA) in our infrastructure. Our RBAC service uses OPA to evaluate specific policies (written in the Rego language), and with these policies we can achieve much more than simple permission checks: yes, we can verify whether a user has a certain Role or Permission, but we can also enhance the policies with request and user information (to fully support ABAC verifications), or even the API payloads to allow for property filtering or data enforcing.
After several months in which our RBAC has been running successfully in production environments, we realized that it is a complete and reliable solution. Therefore, after expanding its functionality, we decided to release our RBAC solution in open-source under the name Rönd. If you want to find out more about this project, read the announcing blogpost and visit the official Rönd website.
This is how we implemented the RBAC within our platform. To recap, we firstly identified Permissions and Roles, defining the RBAC entities. Then, we decided to keep RBAC outside the codebase, because we wanted it to be language agnostic and easy to maintain. Next, we created a Sidecar Container within every service that needed RBAC: in this way, the architecture is free of single point of failure. Lastly, thanks to OPA, we ensured a centralized policy configuration that is easy to maintain.
Our RBAC solution improves data security, while giving you full independence and a 360‑degrees Permissions governance. Starting from Mia‑Platform v9.0, our RBAC solution will be generally available for everyone using the platform, and you will be able to use it in your projects by defining your own policies, premissions and roles.
The article was written by Federico Maggi, Senior Technical Leader.