flexway
FRENTalk to an expert

Client certificates (mTLS)

GuideOperationsSince version 0.1.0

Markdown

Operations guide: configure, deploy and observe the gateway. What the capability does, product side: product guide; calling it: developer guide.

For a partner server that presents a certificate. Two ways to verify it, either or both:

Where the certificate is verified Configuration When
The edge (Envoy, an ingress) terminates mTLS and vouches for it in x-forwarded-client-cert server.trusted_proxies = the edge's range The usual case in a cluster
The gateway itself, on its TLS listener server.tls (cert_file, key_file, client_ca_file) No edge terminating TLS

Each certificate is declared - by its URI SAN (preferred: it survives a renewal) or by its subject - and bound to a tenant and to operations:

server:
  trusted_proxies: [10.0.0.0/8]      # the edge, and only it: from anyone else the header is ignored
auth:
  mtls:
    clients:
      - { id: bank-settler, uri: "spiffe://bank.example/settler", tenant: bank, operations: [settle] }
      - { id: legacy-batch, subject: "CN=batch,O=Acme", tenant: acme, operations: [getSettlement] }

The gateway's own TLS listener, when there is no edge (port FLEXWAY_TLS_ADDR, :8443 by default, next to :8080):

server:
  tls:
    cert_file: /etc/flexway/tls/tls.crt          # reloaded when it rotates, no restart
    key_file: /etc/flexway/tls/tls.key
    client_ca_file: /etc/flexway/tls/clients-ca.pem   # the client certificates' authority, reloaded too

The contract declares the mutualTLS alternative:

components:
  securitySchemes:
    partner: { type: mutualTLS }
paths:
  /settlements:
    post:
      operationId: settle
      security: [ { partner: [] } ]    # a declared certificate, nothing else

Check:

Call Response
A declared certificate, a bound operation relayed; the certificate's X-Tenant; x-forwarded-client-cert never reaches the upstream
A declared certificate, an operation it does not name 403
A valid but undeclared certificate, or none 401 "requires a client certificate"
An x-forwarded-client-cert header from anywhere but the edge ignored - 401
A certificate from another authority, on the TLS listener the handshake fails
A token on an operation that accepts mutualTLS only 401; the token is not even verified

Reading order: a certificate verified by the listener, then the edge's x-forwarded-client-cert, then an API key, then a token. The contract decides which mechanism satisfies which alternative: a token never stands in for a key, nor the reverse. The MCP surface accepts OAuth tokens only (Agents and MCP). server.tls is not reloadable: adding or removing it needs a restart; its files are re-read on their own.

Next steps