Learn Envoy Proxy - Secure Service-to-Service Communication
Episode 12 of 23

Learn Envoy Proxy - Secure Service-to-Service Communication

This episode secures communication between services: Envoy as a microservices gateway, TLS contexts and certificate validation, and authorization policies using Envoy's RBAC filter.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

After securing the transport path in episode 6, it's time to secure who is allowed to talk. Episode 12 covers secure service-to-service communication: Envoy as a trusted gateway for microservices, TLS contexts and certificate validation, and Envoy's RBAC filter for authorization policies. By the end of this episode, you have a basic security pattern: encryption at the transport layer, verified identities, and role-based authorization that can be extended.

Envoy as a Secure Microservices Gateway

The Per-Service Gateway Pattern

In a service mesh architecture, every service communicates through the Envoy in front of it. Envoy acts as a secure gateway: all incoming and outgoing traffic must pass through it, so security policy is enforced at a single point.

Pola sidecar Envoy untuk satu service
listeners:
  - name: sidecar_inbound
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 15006
    filter_chains:
      - transport_socket:
          name: envoy.transport_sockets.tls
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
            require_client_certificate: true
            common_tls_context:
              tls_certificates:
                - certificate_chain:
                    filename: /etc/envoy/certs/service.pem
                  private_key:
                    filename: /etc/envoy/certs/service-key.pem
              validation_context:
                trusted_ca:
                  filename: /etc/envoy/certs/ca.pem
        filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              stat_prefix: service_ingress
              route_config:
                name: service_routes
                virtual_hosts:
                  - name: service_vh
                    domains:
                      - "*"
                    routes:
                      - match:
                          prefix: "/"
                        route:
                          cluster: local_service
              http_filters:
                - name: envoy.filters.http.router
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

The require_client_certificate: true configuration forces every client to present a certificate when talking to this service. Traffic without a valid certificate is rejected before reaching the application.

With this pattern, security doesn't depend on every developer's discipline. A policy in one Envoy config applies to all traffic — the main reason service meshes attach a sidecar to every pod.

TLS Context and Certificate Validation

Verifying Upstream Identity

When Envoy talks to another service, it verifies the counterpart's certificate:

Transport socket dengan verifikasi SAN
clusters:
  - name: orders_service
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        common_tls_context:
          validation_context:
            trusted_ca:
              filename: /etc/envoy/certs/ca.pem
            match_subject_alt_names:
              - exact: orders.internal
            match_typed_subject_alt_names:
              - san_type: URI
                matcher:
                  exact: spiffe://example.org/ns/prod/sa/orders
    load_assignment:
      cluster_name: orders_service
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: orders.internal
                    port_value: 8443

The match_typed_subject_alt_names part shows the SPIFFE pattern — the standard identity URI in the service mesh world. This verification ensures Envoy only talks to the orders service in the prod namespace.

Certificate Validation as Identity

The strongest pattern uses SAN identity rather than just checking the certificate chain. With SPIFFE, the service identity lives in the certificate itself, so TLS verification becomes identity verification at the same time.

Authorization Policies with RBAC

The RBAC Filter in Envoy

RBAC (Role-Based Access Control) lets Envoy enforce attribute-based access policies:

Filter RBAC untuk service
http_filters:
  - name: envoy.filters.http.rbac
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
      rules:
        action: ALLOW
        policies:
          admin_policy:
            permissions:
              - header:
                  name: ":method"
                  string_match:
                    exact: GET
            principals:
              - authenticated:
                  principal_name:
                    exact: spiffe://example.org/ns/prod/sa/admin
  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

The rbac filter with action ALLOW rejects all requests that don't match. The admin_policy policy allows only GET requests from the admin SPIFFE principal; everything else automatically receives a 403.

RBAC at the Network Level

For protection at the connection layer before HTTP is processed:

RBAC pada filter network
filters:
  - name: envoy.filters.network.rbac
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
      rules:
        action: ALLOW
        policies:
          internal_only:
            permissions:
              - destination_port: 8443
            principals:
              - authenticated:
                  principal_name:
                    exact: spiffe://example.org/ns/prod/sa/*

The network.rbac configuration rejects TCP connections from unknown principals even before an HTTP request is formed. It's a cheap first line of defense.

Testing Authorization Policies

Uji akses dengan dan tanpa sertifikat
curl -s -o /dev/null -w "%{http_code}\n" \
  --cert ~/envoy-lab/certs/client.pem --key ~/envoy-lab/certs/client-key.pem \
  --cacert ~/envoy-lab/certs/ca.pem https://localhost:10443/orders
curl -s -o /dev/null -w "%{http_code}\n" \
  --cacert ~/envoy-lab/certs/ca.pem https://localhost:10443/orders

A request without a client certificate should fail at the TLS layer, while the first request is evaluated by the RBAC filter. The curl -w "%{http_code}" command prints only the status code — a clean way to test policies.

Monitoring Authorization Decisions

RBAC Statistics

Envoy records RBAC decisions in metrics:

Lihat counter RBAC
curl -s localhost:9901/stats | grep "rbac"

The rbac statistics show how many requests were allowed and denied per listener. If denials jump suddenly, a service's identity probably doesn't match — check the principal in match_typed_subject_alt_names.

When drafting a new policy, enable decision logging first. Envoy supports shadow_rules, which records decisions without actually rejecting requests — perfect for testing a policy in production risk-free.

Closing

Episode 12 assembled the service-to-service security layer: Envoy as each service's trusted gateway, TLS contexts with SAN and SPIFFE verification, and the RBAC filter enforcing access policies.

Key takeaways:

  • Every service can be wrapped in an Envoy that acts as a secure traffic gateway.
  • require_client_certificate forces clients to prove their identity.
  • SAN verification, especially the SPIFFE pattern, makes TLS an identity check.
  • The RBAC filter with action ALLOW rejects everything that doesn't match a policy.
  • RBAC can be applied at both the HTTP and network levels.
  • Test with curl using and without a client certificate to see the difference.

In the next episode, episode 13, we'll discuss API gateway patterns and edge proxy — Envoy as an edge proxy and API gateway, virtual hosts and rate limiting, authentication and CORS, and when to use a gateway versus an internal sidecar.