How to Secure Microservices: A Presentation from Lukasz Marchewka
Lukasz Marchewka, a senior Scala developer and cybersecurity expert at Scalac, spoke as part of our digital microservices event, “Between Business & Tech”. The digital conference featured six speakers who shared their experiences about creating effective and secure microservices architecture. Follow this link to watch Lukasz’s talk or watch the whole conference.
Lukasz discussed several solutions on how to secure microservices from attacks and other potential cybersecurity issues. Lukasz is an expert in Functional Programming (FP), Domain-Driven Design (DDD), and Scala, with over ten years of experience as a software developer.
In his presentation, Lukasz illustrated the importance of understanding microservices. He explained the main points that require consideration during the development process, explored common mistakes, showcased a selection of innovative designs, and also talked about ready-to-use components. In addition, Lukasz covered authentication, authorization, encryption, single sign-on, and backups for security.
Lukasz kicked off his presentation by talking about cyber incidents. Cyber incidents are incredibly costly to businesses and can quickly ruin a long-established reputation. Yahoo’s data breach of three billion accounts, for example, cost the company three hundred and fifty million dollars.
Lukasz mentioned the following types of cyber incidents, to which microservice architectures are vulnerable:
- Data breaches
- Denial of service attack (DoS)
- Unauthorized reads
- Unauthorized writes
Factors to Consider When Securing Microservices
Microservices form the basis of lightweight software architectures that have autonomy, flexibility, and reduced coupling. However, poorly executed microservice systems invariably lead to problems and inefficiencies.
There is no universal model or design that can be applied to secure microservices. Instead, dev teams must consider a variety of factors.
Lukasz listed five main factors that businesses should think about when creating a microservices security plan:
- Specific risks to the business
- Resources (including developer time) available to the business
- Type of business
- Of potential cyber incidents
- Of the implementation of a cybersecurity plan
- Time to Market
In practice, businesses have limited time and resources. They always need to seek a balance between the ideal security strategy and organizational needs and limitations.
Monoliths and Microservices
Before the widespread adoption of microservices, engineers largely relied on monolith architectures. Monoliths are easy to implement because they contain everything in one place and combine features such as business logic, security, tracing, and metrics.
A diagram of a monolithic architecture.
Nowadays, dev teams are more likely to use microservices. And while this has mostly been a positive change in the industry, developers often fall into a trap. They erroneously create microservice systems using the same pattern on which monolith networks are based, especially when it comes to cybersecurity.
A diagram of a microservice architecture.
Dev teams often implement security mechanisms using middleware and microservice plugins.
This practice has three consequences:
- It breaks the single-responsibility principle (the main reason dev teams use microservices).
- Developers implement microservices using various technologies and languages, and thus require different tools to create a secure network.
- To maintain security, developers must maintain and patch disparate elements. This requires extensive testing of each microservice.
This can create a problem for front-end users when they access different microservices for different actions. For example, after authenticating themselves on one app interface, they are forced to re-enter security details when they transition to another activity.
It’s also common practice for developers to build sharing stations between components. In conjunction, they may create a new application that communicates with all the components that have security protocols. Unfortunately, this generates a large amount of traffic to the connected app. In addition, this approach creates a single point of failure that can cause performance issues.
A diagram of a microservice architecture with a single security service.
On the positive side, this approach is easy and doesn’t require any other supporting architecture. In addition, dev teams can utilize tools to combat various issues.
Next, Lukasz turned his attention to the topic of securing communication between microservices and security infrastructure.
OpenID Connect is a protocol for implementing authorization. It allows one server to authenticate users. Users provide their credentials to the authorization server, and it returns a signed token.
This process is similar to starting a new job. First, an individual goes to a specific department, shows their ID, and signs authentication documents. Then they receive a card from the department. This card allows them access to all departments without any other verification.
With OpenID Connect, authorization tokens give users permission to access specific services. Users essentially “show” whenever they send requests to servers. A dedicated resource server then verifies the token by communicating with an authorization server and decides whether to allow or reject the request. This approach minimizes communication between resource and authentication servers.
A diagram of user authentication using OpenID Connect.
However, if a dev team uses a microservice architecture rather than a single resource server, it can cause problems. Problems arise because both systems use the same verification pattern and security code.
Microservices eliminate a single point of failure and performance issues. But the single-responsibility principle, presence of different implementations, and the fact that many services are communicating with a single security app present ongoing problems.
To create a system that solves all the problems that come from utilizing microservices, developers need to take advantage of modern security tools. Many of these tools are widely available and don’t require development from the ground up.
Tools for the Implementation of Microservice Security
Lukasz elaborated on the following tools, all of which can be used to bolster and streamline the security of microservices architecture:
Identity providers are application components that are responsible for the creation, storage, and maintenance of user identity information. There are many different identity providers available. These include Keycloak, Okta, WS2, Cognito, and Auth0. In addition, cloud services typically offer their own identity providers.
Identity providers have the following features:
- User registration portals
- Social logins
- User federation (LDAP, AD)
- Single sign-on/off
- Multi-factor authorization
- UI management tools
- Login pages
Lukasz was keen to point out that while identity providers simplify applications, other elements are also required for optimal efficiency.
There are various API Gateway providers that often offer their own security implementations, like Kong, Apigee, 3Scale, Amazon API Gateway.
API Gateway architecture.
These component services provide implementations of specific functions, including:
- Rate limiting
Developers can utilize API gateways instead of coding their own versions of the above features. API gateways provide various functionalities which are especially useful for microservices.
Developers can position API gateways as intermediaries between users and microservice-based apps. It’s also possible to move security features from the microservice architecture to the API gateway.
This solves several of the security problems inherent in microservice architecture:
- API gateways fix the broken single-responsibility principle.
- API gateways prevent developers from requiring different security implementations.
- Services do not all need to communicate with the main security app.
The API gateway consolidates security into a single unit and enables development teams to suspend security for certain operations. However, such an approach does require extra infrastructure.
“Trust the Network” and API Gateways
Lukasz used the term “trust the network” to describe how dev teams configure their networks using API gateways to create a single point of entry to various microservices.
“Trust the network” prevents intruders from communicating with microservices outside of the network. However, if a malicious actor does hack into the network, they can access everything. As such, API gateways present many of the same obstacles as previously-discussed solutions.
An example of a “Trust The Network” system.
To combat this, developers add security mechanisms to microservices. But this approach introduces new problems into the system.
Typically, developers create a system in which an authenticating token communicates with individual microservices. The client sends the token to the API gateway and the API gateway passes it on to the microservices. In addition, there must be communication between microservices.
An example of a microservice architecture using API gateways and tokens.
It is possible for software engineers to create communication channels that pass tokens between microservices. However, in practice, applications tend to rely on async operations and cron jobs.
It’s also possible to create another endpoint to get around token expiration when communicating between microservices. And this approach is easy for developers to execute. However, it can lead to unsecure communication between microservices. Ultimately, the endpoints are unprotected.
Diagram of a network with a vulnerable endpoint.
Encryption and Transport Security Layers
Two secure microservices will likely leverage typical cybersecurity features like auth tokens. However, without encryption, an intruder can still observe the communication between the services.
Example of unprotected communication.
Lukasz argued that developers should introduce Transport Layer Security (TLS), thus enabling encryption between microservices and thereby preventing intruders from snooping on data.
In practice, developers typically use SSL termination. SSL termination puts API gateways or load balancers between the client and services. This means that encryption and TLS operate solely between the API and the client (not the API and the microservices).
To prevent the network from being unencrypted, developers can add another TLS inside the network. This secures the network and adds a further layer of encryption.
Inter-service communication forces developers to add tailored security systems to microservices. Often, however, security on microservices is implemented as code, which creates a range of issues.
An example of the failings of TLS for microservice communication.
TLS alone isn’t enough to protect a network because it only encrypts communication between services. Intruders can still send a request to a microservice to modify or read data.
Lukasz was quick to point out that there is a solution to this problem, however.
Mutual TLS (mTLS)
Mutual TLS (mTLS) encrypts communication like TLS. It ensures that only trusted services with proper certificates can send requests. This means that extra security doesn’t need to be implemented as code. Therefore, mTLS prevents intruders from sending requests to a network.
Comparison of TLS and mTLS.
To add mTLS, developers use tools like Kubernetes. Another option is to create a distinct application on the same service on which the network runs.
A popular alternative is to introduce a proxy. The proxy receives encrypted requests and then communicates with the application and vice versa. Developers don’t need to encrypt the communication between the proxy and app in the system. However, this system is complicated to build.
A diagram of mTLS communication using a proxy.
Service Mesh / Sidecar Container
Service meshes and sidecar containers are two other patterns developers can use. There are numerous service meshes and sidecar containers available, including HashiCorp Consul, Linkerd, and Istio.
Service mesh patterns offer a range of features, including the following:
- Secure service-to-service communication using mTLS
- Load balancing
- Service discovery
- Observability (metrics, logs, tracing)
Service meshes simplify application creation and allow developers to focus on domain logic.
Example of a network using a service mesh.
In the example above, four new components are introduced for security: TLS, service mesh, IdP, and an API gateway.
Can We Trust Other services?
After exploring the various security components available to developers, Lukasz turned his attention to the question of whether or not it’s possible to trust them.
In the example depicted below, a client sends a request to a microservice application. An mTLS encrypts communication between services A” and “B”. The client sends the request with a permission token. Service A sends the request to service B with the same permission token, and service B accepts the request.
Example of a request being accepted with two working services
However, if service A is broken, Service B will not be able to verify which request is valid. To fix this, a JSON web token (JWT) is passed between services.
Example of a network using JWTs
This architecture is much more secure than earlier examples. However, it is difficult for developers to build as it requires extra infrastructure.
Sync vs. Async Communication
When building microservice networks, async communication is preferable to sync communication. Sync communication can be secured using mTLS, TLS, and several additional security mechanisms in the application.
However, developers often implement security solely on the consuming application when using async communication.
Async solutions can be built with tools like Kafka, Amazon SNS, and RabbitMQ. Developers typically use the pattern shown in the image above. However, in this example, an intruder can send requests to Kafka to slow it down or pull requests. To fix this, mTLS is implemented between the producer and consumer.
“Producing” and “pulling” are central features of async communication. However, when utilizing mTLS to secure a service, it is organized in the same way for both async and sync communication.
This kind of architecture guarantees secure communication between microservices and external networks. However, Lukasz pointed out that, even then, there is still more that can be done.
Dev teams still need to secure infrastructure components such as databases and messaging platforms. Each time a new component is added to a system, TLS or mTLS should be applied. Data and storage should also be encrypted on an ongoing basis.
Lukasz also briefly spoke about trust. He said that many elements in a network can’t be trusted. These include the following variables:
- Third-Party Applications
If a dev team concludes that nothing can be trusted, a “Zero Trust” model can be introduced.
Teams must decide where their application falls in terms of cost and security. A more secure network is more expensive to produce. Therefore, Zero Trust may be too costly in the early stages of app development. However, developers can increase protection incrementally.
Conclusion: Deciding on the Right Model
There are many factors that need consideration when picking a security model for microservice-based applications. These include known risks, business needs, costs of potential attacks, time to market, and more. It’s also essential to keep in mind that there’s no “gold standard” cybersecurity infrastructure that will guarantee safety.
Security is a complex issue. Engineers need to commit time and resources to managing microservices architecture effectively to maintain a fully-shielded network. Fortunately, however, various tools are available that simplify this task.
If you found Lukasz’s presentation informative, please don’t hesitate to get in touch with us at Scalac. We’ve worked with a wide range of organizations to implement cutting-edge cybersecurity solutions. We would love to speak to you directly or schedule a corporate workshop to explore the various options available to you.
See also presentations by other speakers at the Business & Tech Conference. Episode 1: Microservices
- Should Startups Be Using Microservices? A Presentation From Zuka Kakabadze
- The Hype and Hope of Microservices: A Presentation by John De Goes
- Is Microservices Architecture the Silver Bullet? Mary Grygielski at Scalac’s Event