Once developers start the journey of adopting a modern microservices based architecture they also need to handle other aspects of Cloud Native architecture like Full Stack Observability, microservices authentication and authorization, CICD pipeline etc. Cisco’s DevRel engineering team has been developing all its applications as microservices, and running these on a Kubernetes based Cloud Native platform for 5+ years. As an early adopter of Cloud Native architecture, the DevRel engineering team needs to develop and evolve various core platform capabilities like microservice authorization.
Our microservice authorization framework has gone through architectural update 3 times as Cloud Native ecosystems have evolved. When we’d hit an architectural limitation with an old pattern, we learned and improved the benefit with a new pattern. If your team is starting new on Microservices you can start directly with adopting standard tooling like Open Policy Agent (ref opa_styra, policy as code, istio-k8s-opa ). However, if you are interested in learning other microservices authorization patterns and learn challenges and benefits of each, then continue reading.
What is microservice authorization?
As the number of Microservices deployed in any environment grows there arises need to control which users and microservices can access which microservices with fine grained access control for individual API (Applications Programming Interfaces) endpoints. Access control system includes information about resources that are protected like API endpoints URL, subject requesting access that can be user or another service making service-service API call, policies that allow or deny access along with other contextual information.
Authorization systems typically involve Policy Decision Point (PDP) to evaluate policy & make decision, a Policy Enforcement Point (PEP) to enforcing access control and Policy Information Point (PIP) that supplies added information/context required by PDP to make decision. Refer NIST ABAC policy paper for more information.
Simple example authorization policy of one of Course Management microservices where admin user for course management and DevNet is given access to create new course. In addition, PubHub content publishing microservice is also given write access to make service to service call.
Now let us look at microservices Authorization architectural patterns evolution for DevRel Engineering team.
- Authorization implementation by Each Microservices
- Authorization implementation via centralized API Gateway
- Authorization implementation by microservices Side Cars in Istio Service Mesh
Authorization implementation by each microservices
For first iteration authorization is implemented by each microservices, this requires code to be included by each microservices code. To avoid code duplication it was implemented as Golang middleware for http REST APIs. Every API request made to service from end user or other microservice is first evaluated by go authorization middleware and request is passed to microservice implementation only when access is allowed by authorization policy. But this approach had few limitations:
- Policy rules need to be maintained by each microservice development team and changing policy control code required rebuilding all microservices.
- Updating policy requires redeployment of microservice even policies are externalized as Kubernetes deployment config.
- Difficult to meet infosec requirements for centrally controlling and auditing policy changes.
Authorization implementation via centralized API gateway
For second approach DevRel engineering team moved go middleware logic to separate ABAC microservices, also build UI to ease of policy management. This allowed authorization policies for all microservices to be maintained centrally following central PDP and PIP principle. Policy enforcement (PIP) is implemented in Nginx API gateway using custom LUA plugin that interacts with ABAC service to make access policy decision for each API call by end users. This approach helped resolved limitation of first approach but this implementation has one key limitation:
- API gateway only provides access control only for external user generated API calls, for internal service-service API gateway is typically not involved. To enable service-service authorization we left minimal go middleware authorization module as go middleware.
Authorization implementation by microservices side cars in Istio Service Mesh
As we started to evaluate and adopt Istio service mesh in our Kubernetes Cloud Native platform that host all our microservices team realized that custom Nginx access control plugin can be easily migrated to Envoy proxy sidecar external authorization plugin. Distributed policy enforcement points by sidecar provided multiple benefits
- All API call irrespective it’s from external user or from internal service-service are consistently enforced by side cars acting as Policy enforcement point (PEP).
- All policies are centrally managed and audited as per infosec requirement in ABAC control microservice acting as Policy decision point and Policy information point.
- Even though policies are enforced at each microservices level individual services developer do not need to add any code or policy config, authorization is seamless for service developer.
As the DevRel team evolved an authorization framework based on self-learning and evolution of Cloud Native ecosystem, it seems our custom solution has resulted in a very similar architectural pattern to that of OPA Envoy proxy authorization. DevRel engineering team as an early adaptor of technology had to implement custom authorization solution but for developers now starting their microservices journey can start with evaluating OPA plugin. Let us know if you would like to learn more about it. Or, if you are already implementing micorservice authorization, then please share how your team is implementing it.
We’d love to hear what you think. Ask a question or leave a comment below.
And stay connected with Cisco DevNet on social!