Learn Multigress - Security Policies & Access Control
Episode 12 of 23

Learn Multigress - Security Policies & Access Control

This episode covers policy-based access control for the gateway, JWT authentication and external auth integration, and mutual TLS and certificate validation to secure routes end to end.

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

Introduction

How tightly do you control who is allowed to call your APIs? Episode 12 covers security policies and access control in Multigress: restricting access with declarative authorization mechanisms, validating JWT and integrating external auth, and securing the gateway path with mutual TLS and certificate validation. An open route without a policy is an invitation for anyone. After this episode, every endpoint will have a clear answer: who may enter, how identity is proven, and whether communication is encrypted from gateway to backend.

Access Control with SecurityPolicy

Declarative Authorization Rules

Multigress provides an authorization mechanism similar to the AuthorizationPolicy in Istio, but it attaches directly to Gateway API objects. The pattern is simple: declare rules in a SecurityPolicy, then attach it to an HTTPRoute via targetRefs.

SecurityPolicy for HTTPRoute
apiVersion: gateway.multigress.io/v1
kind: SecurityPolicy
metadata:
  name: api-authorization
  namespace: platform
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: api-route
  authorization:
    rules:
      - when:
          - key: request.headers.authorization
            values: ["Bearer *"]
        action: ALLOW
      - action: DENY

The policy above applies a default deny: only requests with a Bearer-type Authorization header are allowed, everything else is rejected. The first rule with action: ALLOW matches the Bearer * pattern, then the final rule with action: DENY closes off everything that doesn't match.

Evaluation Order and Default Deny

Rules are evaluated in order from the top. The first matching rule determines the final result, so arrange rules from most specific to most general. Closing the list with action: DENY means a configuration mistake can't turn into a security gap.

Apply policy
kubectl apply -f security-policy.yaml
kubectl get securitypolicy -n platform

The kubectl apply -f security-policy.yaml command applies the policy, then kubectl get securitypolicy verifies it's recorded. When an Authorization header doesn't match any rule, the response is 403 Forbidden.

JWT Authentication and External Auth

Validating JWT at the Gateway

Validating JWT at the gateway means tokens are checked before the request reaches the application. Issuer and JWKS configuration are set up in the authentication policy.

JWT authentication
apiVersion: gateway.multigress.io/v1
kind: SecurityPolicy
metadata:
  name: api-jwt-policy
  namespace: platform
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: api-route
  jwt:
    providers:
      - name: keycloak
        issuer: https://auth.example.com/realms/platform
        jwksUri: https://auth.example.com/realms/platform/protocol/openid-connect/certs
    defaultProvider: keycloak

With the configuration above, every request must carry a JWT signed by the Keycloak realm. Signature and expiry are verified at the gateway, not in the application, so the application doesn't need to implement token validation.

External Auth Integration

There are times when JWT validation alone isn't enough, for example when authorization must check business data. Multigress can delegate the decision to an external service through the external auth mechanism, such as an Open Policy Agent server.

External auth endpoint
apiVersion: gateway.multigress.io/v1
kind: SecurityPolicy
metadata:
  name: api-ext-auth
  namespace: platform
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: api-route
  extAuth:
    service: authz.opa.svc.cluster.local
    port: 8181
    path: /v1/data/platform/allow

This policy sends request metadata to the OPA service before forwarding to the backend. If the external auth service answers with a deny decision, the request is aborted at the gateway and the backend never receives it.

Forwarding Claims to the Backend

Forward claims to backend
apiVersion: gateway.multigress.io/v1
kind: SecurityPolicy
metadata:
  name: api-jwt-policy
  namespace: platform
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: api-route
  jwt:
    providers:
      - name: keycloak
        issuer: https://auth.example.com/realms/platform
        jwksUri: https://auth.example.com/realms/platform/protocol/openid-connect/certs
        claimToHeaders:
          - claim: email
            header: X-User-Email

The email claim is moved to the X-User-Email header, so the application just reads the header without re-parsing the token. This pattern also hides token details from internal services.

Mutual TLS and Certificate Validation

mTLS Between Gateway and Backend

JWT protects the client side, while mutual TLS secures the path between the gateway and the backend. Both sides present certificates, so the backend is confident that only the gateway can reach it.

mTLS to backend
apiVersion: gateway.multigress.io/v1
kind: BackendTrafficPolicy
metadata:
  name: backend-mtls
  namespace: platform
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: api-route
  tls:
    mode: Mutate
    caCertificates:
      - name: ca-bundle
    clientCertificate:
      name: gateway-client-cert

This policy configures TLS mutation: the connection to the backend is encrypted and verified with the CA bundle, while the gateway presents its own client certificate. Mutate mode means the original connection from the client is forwarded as a new TLS connection to the backend.

Validating Client Certificates

On certain listeners, you can require a client certificate during HTTPS termination. Clients that don't present a valid certificate are rejected at the handshake stage.

Test client certificate
openssl s_client -connect api.example.com:443 \
  -cert client.crt -key client.key \
  -CAfile ca.pem -state

The openssl s_client -connect api.example.com:443 -cert client.crt command tests the TLS handshake with a client certificate. Look for the line Verify return code: 0 in the output to confirm the certificate was accepted by the CA.

Warning

Mutual TLS adds certificate management overhead. Make sure CA and client certificate rotation runs on a schedule before rolling out mTLS widely.

Closing

Episode 12 completed the identity and access security side: authorization policies define who may pass, JWT and external auth validate credentials, and mTLS secures the path to the backend with certificate validation.

The key takeaways:

  • SecurityPolicy applies default deny with declarative rules.
  • Rules are evaluated in order from most specific to general.
  • Validating JWT at the gateway blocks invalid tokens before they reach the app.
  • External auth delegates decisions to a service like OPA.
  • mTLS validates gateway and backend identity mutually.
  • Client certificate validation rejects handshakes without valid credentials.

In the next episode 13 we'll discuss egress & service-to-service routing — directing outbound traffic through an egress gateway, managing external service access, and applying NetworkPolicy. The security policies you built will be extended outward from the cluster.

Learn Multigress - Security Policies & Access Control | Learn Multigress