Securing an application is a common task that many developers will embrace during the Architecture design and coding phase of a project. Although the securing of a Web Service or RESTful endpoint could be achieved easily when the modules of a project are deployed within the same Java container, when they rely on the same Security Spec (JAAS, WS-Security, WS-Trust, JAX-RS) or Security Framework (Apache Shiro, Spring Security, …) the design could become really complex when we have to build a distributed application.
As the current trend is to split a Monolithic application into a collection of Microservices exposing the service as a RESTful endpoint, or Web Service interconnected to each other, our security officer will be very embarrassed to guide and provide recommendations for the actors of such a project.
The difficulty is not related to the Microservice Architecture itself but because:
- The number of Services to be managed within such a project is multiplied by a factor of 10x, even 100x;
- Each service, which is part of a logical/business domain, could be managed according to different Security Governance Rules (Basic Auth, Digest, and Encryption).
- The information transported between the services belong to a different confidentiality level (public, private, …).
For all these reasons, the security and the governance will become even more critical for the success of a Microservice Architecture. From a technical point of view, we will be faced with the following concerns: as the modules will be deployed within different types of Java Container (Apache Tomcat, JBoss WildFly, Apache Karaf, JBoss Swarm, Vert.x, …), that each container addresses a specific need (non-blocking, high throughput of connections, http/2 protocol, …), and that they don’t necessarily support/follow the JavaEE spec or JAXRS/JAXWS standards, different security patterns or frameworks will be required to resolve our security challenge.
To help architects and developers adopt the security approach that best fits the company requirements, practices, Microservices Architecture, and their skills, we will investigate within this blog some patterns that you could easily implement within your project in order to secure your Microservices:
- Web Container
- API Gateway
We will now present, detail, and mitigate the approaches in order to measure the consequences of the adoption of the different patterns.
The use case that we will discuss is very simple and consists of securing a RESTful Service which has been created using the Java Integration Framework Apache Camel. As we can see within the following picture, the REST Service or Endpoint is exposed by a local HTTP Web container created using Eclipse Jetty. A client which is our HTTP Agent will issue HTTP requests using an HTTP method (GET, POST, DELETE, …) and a URL to access the Web resources of the service (“/rest/myservice/”).
The goal of the interceptor is to include within the flow of the code a class responsible for collecting/handling the information passed through the HTTP Request like the Authorization Header, the HTTP URI, URL, and the credentials provided by the HTTP agent. The principle is presented within the next picture
Within the flow describing how a request or an exchange is processed, an interceptor is added before or after the call to the processor responsible for handling the logic declared within the application. This interceptor wraps your code and will act as a security guardian. This pattern is supported by the Apache Camel Framework using a Policy.
The interceptor can use the existing Security Frameworks/Technologies to handle the authentication/authorization process like JAAS, Apache Shiro, Spring Security, Apache WS4J, …) but you can also create your own Interceptor and plug it within the flow as we will demonstrate here.
An Apache Camel interceptor will look at the SimpleAuthenticationPolicy class where the wrap method will be called when the framework will consume an Exchange that corresponds to an HTTP Request received by the Jetty Server acting as a consumer.
The SimpleAuthenticationProcessor class contains the logic needed to access the content of the Exchange when the processor will be called and of course, it will call the class/method responsible for authenticating / authorizing the incoming request applySecurityPolicy.
The last thing to be done is to register the interceptor within the Apache Camel Route definition in order to secure your Microservice.
As you can see this approach is very flexible as you can plug whatever technology you prefer to use to secure the access to the REST service exposed as an Endpoint by the Jetty Server.
We can also enrich the architecture and use the features offered by the Jetty/Netty HTTP Server in order to
- Enable the SSL/TLS Security layer to encrypt the data exchanged between the HTTP Agent and the Server.
- Setup mutual TLS.
- Restrict access to the Web Resources using a SecurityConstraint associated with a user’s role.
- Authenticate the user using some JAAS Plugin (HashLogin with Property file, LDAP, JDBC)
As you can see in the next diagram, the security architecture proposed is more robust as managed by two distinct levels if you combine the Interceptor pattern with the HTTP Security model :
- The Web HTTP Container will be responsible for Authenticating the user and restricting the access to the Web Resources.
- The Connection between the HTTP agent and the Server is more secured as the data will be encrypted and the confidentiality of the data exchanged will be guaranteed.
- The interceptor will become responsible for authorizing the access to the Service.
Time to Mitigate the Approach
It is time now to review the approach from a Security Officer point of view and to mitigate the approach. He/She will be very pleased about the solution as:
- It offers a great level of flexibility to support the Java Standards (JAAS, WS-Security, …) or standards enacted by the company.
- The applications developed will be independent of any third party tool or vendor to support the security.
But they will certainly complain that the approach is really intrusive, as it will require developing some home security code to support the interceptor pattern. The management of the collection of the Microservices will be very difficult as we will suffer from a lack of governance & centralized capability as proposed by an API Management platform to define in one place the security rules applied to the different services, the services secured, …
|No product lock||Intrusive|
|Great Flexibility||Low Management Capability|
|Spec Managed||Lack of Governance|
The gateway pattern as depicted in the next diagram delegates the responsibility of managing the security aspect to an external player, which is an interceptor acting as a proxy. This actor, which is an API Management Actor, can be part of the same network segment where the Microservices are deployed or can be deployed behind a firewall to reenforce the security of the Services hosted by the Java containers.
The Apiman project has been developed to support this pattern and has the advantage that it can be deployed on premises. The role of the API Management platform will be to:
- Define centrally the different services/endpoints to be secured (REST, Web Service).
- Select using the available plugins the Policies to be applied (Basic Auth, OAuth2, …).
- Map the Web Resources, the Web Actions (GET, POST, PUT, DELETE) with the Services.
- Deploy within one to many Gateways (HTTP Web Server, Vert.x) the policies that the Server will use to intercept the HTTP requests.
The management of the services and the governance is simplified for the Security officer using the Apiman Server.
This Web Console will allow him to:
- Manage the services according to an organization that abstracts the related services.
- Select the services to be secured and assign to an API.
- Group using a plan the policies to be applied to the different services.
- Select the plugins to be used; Basic Authentication, Authorization, Black-listed IP, White IP list, Throttle, Keycloak - OAuth2.
- Manage the different versions of the APIs published.
- Integrate the gateway where the policies are applied on top of the requests received.
- Collect the metrics/statistics of the usage done.
The adoption of an API Management Platform will certainly offer more possibilities to govern the Microservices deployed in different Java containers and potentially non-Java containers as offered by the Node.js technology.
Some additional benefits about this technology concern also :
- The disappearance of the coupling between the Services and the frameworks required to authenticate/authorize the access to the Microservices.
- The centralization in one place of the APIs and consumers of the services.
- The collection/aggregation of the metrics/statistics about the usage of the services which is required in some institutions where Security Audits are performed regularly.
There are nevertheless some drawbacks as summarized within the next table; as a new technology must be investigated and adopted within the company, the performance could be impacted as a Proxy HTTP Server will interrupt the normal flow between the HTTP Agent and the Service, the project will become dependent of the API Product used and new processes will be defined within the company to support the API platform like also the actors in charge to maintain the security governance and the infrastructure.
|Centralized governance policy configuration||Performance|
|Loose coupling||New Architecture Brick|
|Tracking of APIs and consumers of those APIs||Plugins available|
|Gathering statistics/metrics||Product locked|
|Simplify security audit|
While the usage of the Interceptor completed with the Web Container Security Model will be adopted by many companies when the number of the Microservices to secure is not important or when few security standards should be supported, it is evident that the Gateway Pattern will become the de facto standard within large institutions where the security audit and the governance aspects are non-negotiable.
Another benefit of the API Management Platform when it is used on top of a Virtualized environment as proposed by the OpenShift/Kubernetes Cloud platform is the fact that the microservices deployed and running as pods will be automatically discovered!