Foto Source: Life of Pix (www.pixels.com)
Role-based Access Control (shortly RBAC) is one of the first things that come to mind if you think about security. But how can you do this consistently, without overburdening developers and IT-operation? And how can this be done in the context of micro-services architectures or – more generally speaking – for applications involving a large number of independent services?
In this blog series, I’d like to showcase several options how to implement RBAC for applications with multiple services. The implementation is done with Quarkus (“Supersonic, subatomic Java”), because it is optimized for extreme developer speed and allows us to showcase the different options with only few modifications. This helps to get the big picture and not get lost in programming details.
To keep things simple, the basic architecture consists of only 2 services (serviceA and serviceB) that each have multiple REST endpoints (“publicService”, “userService”, “adminService”). The endpoints of these 2 services are programmatically chained together, e.g. publicService endpoint of ServiceA calls publicService endpoint of ServiceB.
The goal of this blog series is to implement multi-service RBAC for these 3 end-points. Thus, we want to enforce that:
- everybody is allowed to call public endpoints
- only person with role “users” are allowed to call user endpoints
- only person with role “admin” can call admin endpoints
Different approaches to secure our application
The interesting part is how trust can be established between the 2 services and how the access control is propagated from one service to another. We will start with the most basic set-up and then gradually dive into more advanced concepts around authentication and authorization, including JSON Web Token (JWT), OpenID Connect, Proxied Authentication through an API Gateway and a Service Mesh.
The presented options differ in the following aspects:
- Do you need a 3rd party component or do you implement RBAC in the application itself?
- Are you using standard protocols or do you have bespoke approach per secured application?
- If you change anything, do you need to redeploy the applications?
- Could you apply this option to any application or is it programming-language specific?
See below an overview about the different approaches. Each of them are explained in a separate blog (click on the :
|Blog||Implementation Option||Description||Other components required?|
|(2/7)||http Query Param||This is the most basic module where the “role” is transferred as a HTTP Query Parameter. The server validates the role programmatically.|
|(3/7)||Basic Authentication||A user agent uses Basic Authentication to transfer credentials.||External database to store user credentials|
|(4/7)||JWT||A JSON Web Token (JWT) codifies claims that are granted and can be objectively validated by the receiver.||Public/|
|(5/7)||OpenID and Keycloak||For further standardization, OpenID Connect is used as an identity layer. Keycloak acts as an intermediary to issue a JWT token.||Keycloak|
|(6/7)||Proxied API Gateway (3Scale)||ServiceB uses a proxied gateway (3Scale) which is responsible for enforcing RBAC. This is useful for legacy applications that can’t be enabled for OIDC.||Keycloak, OpenShift, 3scale|
|(7/7)||Service Mesh||All services are managed by a Service Mesh. The JWT is created outside and enforced by the Service Mesh.||Keycloak, OpenShift, Service Mesh|
The whole code base is located in this git repo. Each option can be found in a respectively named directory.
- The focus of the blog series is not on any programming specifics or products, but to showcase the various approaches to RBAC – with their advantages and disadvantages.
- Each of the concepts has a magnitude of options. In this blog series, we are only working with a simplified configuration.
- This blog series assumes good knowledge about Authentication and Authorization concepts.