Uncover hidden risks

Watch how the Wiz platform can expose unseen risks in your cloud environment without drowning your team in alerts.

Microservices Security Best Practices

Microservices security is the practice of protecting individual microservices and their communication channels from unauthorized access, data breaches, and other threats, ensuring a secure overall architecture despite its distributed nature.

8 minutes read

With the proliferation of new hardware and data center offerings, the architectural patterns for software creation have changed drastically. Microservices are one of those patterns. Though they accommodate the increasing use of containers in cloud environments, microservices increase complexity, which makes securing the system much harder. 

Still, there are actions you can take, no matter your system’s configuration. This article will give you a refresher on microservices and microservices security to get you up to speed. Then we’ll dive into crucial security techniques you can apply.

What are microservices?

An application following a microservices architecture uses multiple services, each solving a specific problem. Take an e-commerce store, for example: One service could take care of the item catalog, and another could handle the shopping cart. 

Another crucial aspect of microservices is isolation. Each service has a separate code base and runs inside its own container or virtual machine. This isolation requires that the services communicate explicitly via well-defined APIs; there is no single database that all services access and use to communicate.

While their use is optional, because microservices are loosely coupled, they make it easier to dedicate a team to each part of an application. Since each service is isolated, teams don’t have to work together in one big code base, where they constantly step on each other's toes. That’s why microservices are a great option for dividing work within organizations.

What are the benefits of microservices?

  • Resilience: Microservices can make your application more resilient. If each service runs in its own container, it’s less likely to bring down your whole application if it crashes. The orchestration layer of a microservices architecture will also manage the availability of the services for you.

  • Streamlined scaling: With a monolithic architecture, you’ll have to scale every part of your application if you add instances, even the ones that don’t need more resources. A microservices architecture allows you to scale just the parts with excessive loads.

  • Flexibility: Microservices allow for more flexibility in implementation. Each of your services can have a bespoke software stack. For instance, you can use a JavaScript-based service for your web-facing services but have a Python-based one that handles your data analytics loads.

  • Portability: The containerized nature of microservices allows for easy deployment on various systems.

  • Agility: Microservices enable you to develop a specific service without waiting for other services to be ready.

What are the main risks of microservices?

The primary risk of microservices is increased exposure. Monolithic services have only one entry point, but you might have dozens with microservices that receive traffic from the internet (also called north-south traffic in microservices jargon). Each of these services carries the risk of misconfigurations that allow unauthorized access or other security issues. 

The next risk comes from inter-service communication (known as east-west traffic in microservices jargon). In theory, service isolation and well-defined APIs should protect you from that. However, the added overhead can lead engineers to overlook some access controls when connecting services under deadline pressure. 

Then, there is the problem of secrets management. In a microservices architecture, you usually have services accessed by several other services. Their protection requires access tokens, which must be distributed to their clients. Planning for the management of these secrets ensures they’re stored in a secure location and distributed only to the services that require them.

Finally, there are risks for the supply chain. CI/CD pipelines, developer environments, code, and dependencies can all become targets of an attack. While this is also true for monoliths, having a bespoke tech stack for each of your services multiplies this issue.

What is microservices security?

Microservices security is the practice of protecting individual microservices and their communication channels from unauthorized access, data breaches, and other threats, ensuring a secure overall architecture despite its distributed nature.

The goal of microservices security is to protect your services from potential threats by securing internal and external communication, secrets, and the supply chain of your application. This means implementing the right mechanisms at each point of your application and including them right from the start of a project. 

What are the best ways to secure microservices?

Several best practices and technologies can keep your services secure, each addressing one or more of the risks we discussed above. Let’s check out the best practices and then the technologies:

1. Encrypt all data

Cloud encryption protects sensitive data from unauthorized access. Only users and services with an encryption key can read the data. Encryption in transit is responsible for the data transferred via a network (e.g., the public internet or the local network), while encryption at rest is responsible for the data in your storage (e.g., databases, object storage, or block storage). Both are required to keep your microservices secure.

If an attacker can access your network data (either north-south or east-west), encryption in transit is the way to prevent threat actors from reading that data. If an attacker gains access to your storage devices, then encryption at rest protects your data from being read.

2. Use secure service-to-service communication

One way to achieve secure communication between your services is mTLS, which encrypts the traffic. Service meshes and API gateways are other methods to control the east-west traffic of your microservices.

Trusted internal networks can also help by containing traffic. You can connect a service to multiple networks, the internet, and one or more internal networks. Internal networks aren’t directly accessible from the internet, so data sent through them isn’t visible to an outside attacker. 

While handling east-west traffic via the internet is possible and sometimes even easier, using internal networking to connect your services is more secure. Even though it’s a bit more cumbersome to set up, it can save you some money because cloud providers bill you for all data you send to the internet.

3. Authenticate all users

Make sure that you don’t have any unauthenticated access to your system. This isn’t always possible since many applications allow at least read access for some parts of their data, but you should think hard about what data you want to be public. 

Authentication is important for north-south and east-west traffic because even for internal communication, it’s crucial to know which service read or wrote particular data.

4. Follow the principle of least privilege

The principle of least privilege is a good heuristic to follow when building microservices. It states that you should dole out as few permissions as possible. If a user or service only needs access to a few files in an object storage, don’t give them access to all files. If a service only reads data, don’t give it write access. And above all, be very stingy with administrator permissions.

5. Validate input and encode output

The primary reason why most applications are used is their ability to turn inputs into useful outputs, but malicious inputs can damage your system. If the system also displays those inputs unencoded to your clients, they can even endanger your users. That’s why you should check all inputs before processing them and encode them before sending them to a client. 

Validating input data means you have to define input formats for each entry point, which is more effort but ensures that you always get the data you want, even if someone connects with a client that you didn’t expect or approve.

As not all use cases can be well validated (i.e., for code editors), encoding outputs is crucial, too. It allows you to accept data with a less strict validation while protecting your users when displaying that data.

6. Apply rate limiting and throttling

As with the principle of least privilege, you should also limit the resources your services can consume, including implementing traffic limits, throttling per user or service, and placing limits on resources like storage, CPU cores, and memory. 

If an attacker gets into your system, they might not be interested in your sensitive data—they might want your computing power or storage space. Limiting resources ensures your services won’t get out of control if a threat actor takes over. 

7. Validate third-party dependencies

Third-party software is a huge part of modern software stacks. Your application uses libraries and frameworks built by external developers you might not know. Then, there are pre-build container images for reusable components like gateways or authentication. These additions let you move much faster, but you should still take the time to ensure they’re clean.

Keep the shift left approach in mind—in other words, secure the code and infrastructure first. Remember: The later in the process a security practice is applied, the more effort it will take. Also, always download your dependencies from a trustworthy source and keep them up to date with the latest security updates. If you can, only rely on signed container images, but if that isn’t an option, use a container scanner to check for vulnerabilities.

8. Use secrets storage

Secrets are the keys to all the services you use. If they leak, your whole system could get compromised. Avoid hard-coding secrets into your application code at all costs, preventing attackers from extracting them from your code repositories via a supply chain attack. And don’t store your secrets inside containers either; they could leak if someone gets access to your block storage.

The best place for a secret is a central storage location that provides encryption at rest and in transit, like a secrets manager or secrets vault.

9. Implement logging and monitoring

You’re probably logging your system status (e.g., network traffic and downtime) to know how your application behaves in production. But this isn’t enough for robust security. You should also have an event log for authentication and authorization. Failed logins, password resets, passwordless logins, and permission changes are all crucial events that help flag atypical user behavior or facilitate reconstructing historical permissions for post-mortems. In some cases, that information is mandatory for compliance.

Runtime security scanners for your containers are another option to keep your services in check.

10. Integrate security assessments and penetration testing

Since your team might not have a security expert, regular assessments and penetration tests might be a good addition to strengthen your security posture. External companies might find issues you didn’t even think about, and while mending vulnerabilities after a release isn’t perfect, it’s still better than ignoring them completely.

11. Structure your incident response

If you apply all the security measures you know and a breach happens anyway, a structured incident response process is an essential means of fixing things as quickly as possible. People tend to panic during a worst-case scenario, but having a plan they can follow step by step ensures an effective incident response.

Microservices patterns and technologies

While the best practices listed above are often very broad in application, a few patterns and technologies provide more ready-made security support:

  • Code scanning: Follow the shift left approach and use scanners for application and infrastructure code. This is a simple way to catch issues early on when they are cheap to fix. 

  • Role-based access control (RBAC) and attribute-based access control (ABAC): RBAC and ABAC are proven access control patterns you can apply in your microservices architecture to handle permissions.

  • API gateways: Adding an API gateway to your architecture that acts as the entry point to your system can simplify code or even architecture related to north-south traffic security. It makes your system look like a monolith from the outside, hiding implementation details from potential attackers.

  • Service mesh: Using a service mesh is like adding a tiny API gateway to each of your services. It helps with east-west traffic security and allows you to normalize service management.

  • Wiz's container and Kubernetes security: Wiz offers an all-in-one security solution for your container-based applications. Our platform’s graph-based risk visualizations make vulnerabilities easy to spot and help correlate production issues with code changes.

  • The Wiz Runtime Sensor: The Wiz Runtime Sensor gives you real-time security insights into all of your cloud-native workloads, from suspicious network connections to IAM issues.

A single platform for everything cloud security

Learn why CISOs at the fastest growing companies choose Wiz to secure their cloud environments.

Get a demo

Continue reading

What is a Data Poisoning Attack?

Wiz Experts Team

Data poisoning is a kind of cyberattack that targets the training data used to build artificial intelligence (AI) and machine learning (ML) models.

Dark AI Explained

Wiz Experts Team

Dark AI involves the malicious use of artificial intelligence (AI) technologies to facilitate cyberattacks and data breaches. Dark AI includes both accidental and strategic weaponization of AI tools.

What is Policy as Code? 

Policy as code (PaC) is the use of code to define, automate, enforce, and manage the policies that govern the operation of cloud-native environments and their resources.