Microservices Security Testing

Microservices architectures distribute functionality across many services, and each service boundary is a potential attack surface requiring security validation.

Introduction

A fintech company migrated from a monolithic application to microservices, expecting to improve scalability and development velocity. Security testing remained focused on the public-facing API. Internal service-to-service communication happened over a private network, so the team assumed it was safe. When an attacker compromised a low-priority notification service through a vulnerable dependency, they discovered that internal services trusted each other implicitly. The attacker pivoted through the network, accessing the payments service and exfiltrating transaction data—all without touching the hardened public API.

Microservices architectures multiply attack surfaces. Instead of one application to secure, organizations have dozens or hundreds of services. The boundaries between services become critical security points.

Microservices Attack Surface

  • Service-to-Service Communication: Function calls become network requests, each a potential interception point
  • Distributed Trust Boundaries: Services must authenticate and authorize each other; implicit trust enables lateral movement
  • Configuration Sprawl: Each service may have its own configuration, secrets, and access controls
  • Dependency Multiplication: A vulnerability in any service's dependencies can compromise the system

Testing Service Mesh Security

Service meshes like Istio provide infrastructure-level security. Test that controls work:

mTLS Enforcement: Verify mutual TLS is required:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT

Test by attempting unencrypted connections—they should fail with STRICT mTLS.

Authorization Policies: Verify only authorized services communicate:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: payment-service-authz
spec:
  selector:
    matchLabels:
      app: payment-service
  rules:
    - from:
        - source:
            principals: ["cluster.local/ns/production/sa/order-service"]
      to:
        - operation:
            methods: ["POST"]
            paths: ["/api/payments"]

Test by attempting unauthorized access from other services.

Testing Inter-Service Authentication

Even without a service mesh, services should authenticate each other:

# Test service-to-service JWT validation
def test_service_authentication():
    # Valid token
    valid_token = create_service_token("order-service", "payment-service")
    response = requests.post(url, headers={"Authorization": f"Bearer {valid_token}"})
    assert response.status_code == 201
    
    # Forged token should fail
    forged_token = create_token_with_attacker_key("malicious-service")
    response = requests.post(url, headers={"Authorization": f"Bearer {forged_token}"})
    assert response.status_code == 401

Testing Authorization Between Services

Verify services only access what they need:

def test_service_authorization():
    token = get_service_token("order-service")
    
    # Should succeed
    response = requests.post("/api/payments", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 201
    
    # Should fail - order-service shouldn't have refund permissions
    response = requests.post("/api/refunds", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 403

Testing Network Policies

Kubernetes Network Policies control pod communication:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes: [Ingress]

Test that unpermitted traffic is blocked and egress restrictions prevent data exfiltration.

Testing Container Security

# Check for dangerous capabilities
kubectl exec -it pod-name -- capsh --print
 
# Check if container runs as root
kubectl exec -it pod-name -- id
 
# Scan images for vulnerabilities
trivy image payment-service:latest

Testing Secrets Management

# Check environment variables (secrets shouldn't be here)
kubectl exec -it pod-name -- env | grep -i password
 
# Check secret mount permissions
kubectl exec -it pod-name -- ls -la /secrets/

Verify services only access secrets they need and handle rotation gracefully.

Observability and Detection

Use distributed tracing to correlate requests across services. Test that security events are captured—trigger authentication failures and verify alerts are generated.

Conclusion

Microservices security testing requires covering service mesh configurations, inter-service authentication, authorization policies, container security, and network controls. Manual testing of distributed systems is time-consuming and error-prone.

On-demand security testing helps teams validate that microservices architectures are properly secured, identifying misconfigurations and trust boundary violations across complex systems. RedVeil's AI-powered platform can assess your microservices alongside traditional applications, providing verified findings across your distributed architecture.

Start testing your microservices security with RedVeil today.

Ready to run your own test?

Start your first RedVeil pentest in minutes.