TLS

apigenie-server serves TLS itself, and its proxies reach https:// and wss:// servers and mqtts:// brokers. TLS 1.2 and 1.3 come from Mbed TLS. It’s built with what modern servers use: AES-GCM and ChaCha20-Poly1305, ECDHE key exchange on x25519, P-256, P-384 and P-521, and RSA and ECDSA certificates. A server that offers only static RSA or DHE key exchange, or other ciphers, can’t be reached.

Serving. --tls-cert server.pem --tls-key server.key (or tls.cert and tls.key in the configuration) turns the port into HTTPS. WebSocket channels and GraphQL subscriptions become WSS, and clients that ask for h2 by ALPN get HTTP/2, which is how browsers and gRPC clients over TLS connect. The admin API on a port of its own (admin.port) uses the same certificate. The MQTT broker of an AsyncAPI document serves MQTT over TLS too, on port 8883 unless --mqtt-port says otherwise. The startup line shows https:// and mqtts:// URLs and, as JSON, "tls": true. The certificate file may hold the chain, the server’s certificate first. The key must be PEM and not encrypted. For local development, mkcert localhost 127.0.0.1 makes a pair your system trusts:

apigenie-server openapi.yaml --tls-cert localhost+1.pem --tls-key localhost+1-key.pem
curl https://localhost:4010/pets

Upstreams. --proxy-to https://api.example.com (OpenAPI, GraphQL, AsyncAPI HTTP channels), wss://... (AsyncAPI WebSocket channels), mqtts://... (AsyncAPI MQTT channels, port 8883 unless given) and https://host[:port] (gRPC, HTTP/2 over TLS) connect over TLS, port 443 unless given. Certificates are verified against the system’s roots:

  • macOS: the system keychain, and the certificates an administrator or the user marked as always trusted;
  • Windows: the ROOT store;
  • Linux: the first CA bundle found (/etc/ssl/certs/ca-certificates.crt, /etc/pki/tls/certs/ca-bundle.crt, …).

SSL_CERT_FILE and SSL_CERT_DIR replace them on every system. --ca-cert FILE adds authorities, such as a company’s own root or a test CA, and --insecure skips verification altogether. The host name of the URL is checked against the certificate (an IP address against its IP addresses). An upstream whose certificate is rejected gets the usual 502 upstream-unreachable, with the reason in the detail.

tls:
  cert: certs/server.pem     # relative to the configuration file
  key: certs/server.key
  ca_certs: [certs/company-root.pem]
  insecure: false

Client certificates (mTLS)

Requiring them. --tls-client-ca clients-ca.pem (or tls.client_ca) makes every HTTPS, WSS, gRPC and MQTTS connection present a client certificate issued by an authority of that PEM file, as a service behind mutual TLS does. It needs --tls-cert. The certificate’s extended key usage must allow client authentication when it has one.

  • A client without a certificate, or with one the authorities didn’t issue, fails the TLS handshake. The log gets a warning that says why, for example TLS handshake with 127.0.0.1 failed: the client presented no certificate.
  • The subject of an accepted certificate (CN=billing, O=Example) is in each event of the JSON log ("clientSubject"), on a ~ client line of the stylish log, and in the admin API’s log.
  • The contract report lists the clients: clients in JSON ([{"subject": "CN=billing, O=Example", "exchanges": 12}], counting HTTP requests, gRPC calls, WebSocket connections and MQTT messages), a client property per subject in JUnit, and a Clients: line in the summary.
  • The admin API asks for a certificate too, on the main port and on admin.port.
apigenie-server openapi.yaml --tls-cert server.pem --tls-key server.key --tls-client-ca clients-ca.pem
curl --cacert ca.pem --cert client.pem --key client.key https://localhost:4010/pets

Presenting one. --client-cert client.pem --client-key client.key (or tls.client_cert and tls.client_key) is the certificate the proxies present to https://, wss://, mqtts:// and gRPC TLS upstreams that ask for one. Upstreams that don’t ask never see it. It works with --insecure too. The key must be PEM and not encrypted. An upstream that refuses the proxy for want of a certificate gets the usual 502 upstream-unreachable, which says so in the detail (an MQTT client’s CONNECT gets return code 3).

tls:
  cert: certs/server.pem
  key: certs/server.key
  client_ca: certs/partners-ca.pem
  client_cert: certs/proxy.pem
  client_key: certs/proxy.key

Not supported. There is no session resumption: every connection does a full handshake. Neither certificate revocation lists (CRL) nor OCSP are checked, so a revoked client or upstream certificate is accepted as long as its chain is valid. Remove a revoked client’s authority from --tls-client-ca, or issue client certificates with short lifetimes.

Was this helpful?