diff --git a/packages/documentation/content/docs/router/configuration/traffic_shaping.mdx b/packages/documentation/content/docs/router/configuration/traffic_shaping.mdx index c484adf4..4a9cfdde 100644 --- a/packages/documentation/content/docs/router/configuration/traffic_shaping.mdx +++ b/packages/documentation/content/docs/router/configuration/traffic_shaping.mdx @@ -2,6 +2,7 @@ title: "traffic_shaping" --- +import { Callout } from "@hive/design-system/hive-components/callout"; import { Tabs } from "@hive/design-system/tabs"; The `traffic_shaping` configuration object provides control over how the Hive Router manages @@ -130,10 +131,44 @@ new long-lived connection attempts are rejected with `503 Service Unavailable` a This limit only activates when at least one of WebSocket or Subscriptions is enabled. Setting it to `0` disables the limit entirely. +### `router.tls` (Client ↔ Router) + +Use this configuration field to make the router serve HTTPS traffic (TLS) and optionally require client certificates (mTLS). +For a conceptual overview and step-by-step setup, see [TLS & mTLS](/docs/router/security/tls). + +- `cert_file` (**required**): Router server certificate file path, or a list of certificate file + paths. +- `key_file` (**required**): Router server private key file path. +- `client_auth.cert_file` (optional): Trusted client CA certificate file path, or a list of + certificate file paths. +- `client_auth.required` (optional, default `true`): Whether client certificates are required when + `client_auth` is set. + +```yaml title="router.config.yaml" +traffic_shaping: + router: + tls: + cert_file: /etc/router/tls/server.crt + key_file: /etc/router/tls/server.key +``` + +```yaml title="router.config.yaml" +traffic_shaping: + router: + tls: + cert_file: + - /etc/router/tls/server.crt + - /etc/router/tls/intermediate.crt + key_file: /etc/router/tls/server.key + client_auth: + cert_file: /etc/router/tls/client-ca.crt + required: true +``` + ## Outbound Options -The following options (`dedupe_enabled`, `pool_idle_timeout`, and `request_timeout`) can be set -globally for all subgraphs or overridden on a per-subgraph basis by nesting them under the +The following options (`dedupe_enabled`, `pool_idle_timeout`, `request_timeout`, and `tls`) can be +set globally for all subgraphs or overridden on a per-subgraph basis by nesting them under the subgraph's name within the `traffic_shaping` map. For example, the following example shows how to set global defaults and override them for a specific @@ -238,3 +273,46 @@ traffic_shaping: This example sets a shorter timeout for high-priority requests based on a custom header, and configures the `product` subgraph to have a different timeout for requests originating from Europe. + +### `tls` (Router ↔ Subgraphs) + +Use these configuration fields to configure TLS for outbound requests from the router to subgraphs. For a +conceptual overview and step-by-step setup, see [TLS & mTLS](/docs/router/security/tls). + +- `all.tls`: global default TLS config for all subgraphs. +- `subgraphs..tls`: per-subgraph override. + +Supported fields: + +- `cert_file` (optional): Trusted subgraph CA certificate file path, or a list of certificate file + paths. +- `client_auth.cert_file` + `client_auth.key_file` (optional): Router client certificate and key + for mTLS to subgraphs. +- `insecure_skip_ca_verification` (optional, default `false`): Disables server certificate + verification. + +When both `all.tls` and `subgraphs..tls` are set, the subgraph config overrides the matching +global fields. Fields not set in the subgraph config fall back to `all.tls`. + +```yaml title="router.config.yaml" +traffic_shaping: + all: + tls: + cert_file: /etc/router/tls/subgraph-ca.crt + subgraphs: + payments: + tls: + cert_file: /etc/router/tls/payments-ca.crt + accounts: + tls: + cert_file: /etc/router/tls/accounts-ca.crt + client_auth: + cert_file: /etc/router/tls/router-client.crt + key_file: /etc/router/tls/router-client.key +``` + + + `insecure_skip_ca_verification: true` should only be used for local + development or controlled testing. It disables verification of subgraph server + certificates. + diff --git a/packages/documentation/content/docs/router/security/meta.json b/packages/documentation/content/docs/router/security/meta.json index 85740970..a778981a 100644 --- a/packages/documentation/content/docs/router/security/meta.json +++ b/packages/documentation/content/docs/router/security/meta.json @@ -5,7 +5,8 @@ "csrf", "introspection", "jwt-authentication", - "operation-complexity", + "tls", + "operation-complexity" "persisted-documents" ] } diff --git a/packages/documentation/content/docs/router/security/tls.mdx b/packages/documentation/content/docs/router/security/tls.mdx new file mode 100644 index 00000000..4962dc08 --- /dev/null +++ b/packages/documentation/content/docs/router/security/tls.mdx @@ -0,0 +1,163 @@ +--- +title: "TLS & mTLS" +--- + +import { Callout } from "@hive/design-system/hive-components/callout"; + +Transport Layer Security (TLS) encrypts traffic between every participant in your federated graph. +Mutual TLS (mTLS) goes a step further and authenticates both sides of a connection using +certificates, so each party can prove who it is, not just that the channel is encrypted. + +Hive Router lets you configure TLS independently on two connection segments: + +- **Client → Router (inbound):** the router terminates TLS toward API consumers. +- **Router → Subgraphs (outbound):** the router validates subgraph certificates and optionally + presents its own client certificate. + +``` +Client ──[TLS]──► Router ──[TLS]──► Subgraph(s) + inbound outbound +``` + +For the full configuration reference for every field described on this page, see +[`traffic_shaping` configuration](/docs/router/configuration/traffic_shaping). + +## Inbound TLS (Client → Router) + +By default the router listens on plain HTTP. Enable inbound TLS when the router is directly exposed +to clients and is **not** behind a TLS-terminating load balancer or reverse proxy (e.g. nginx, +Envoy, AWS ALB). + +### Basic HTTPS + +Provide a server certificate and its private key: + +```yaml title="router.config.yaml" +traffic_shaping: + router: + tls: + cert_file: /etc/router/tls/server.crt + key_file: /etc/router/tls/server.key +``` + +When inbound TLS is enabled, WebSocket clients must connect using `wss://` instead of `ws://`. The router automatically accepts secure WebSocket upgrades on the same TLS port. + +If your certificate is issued by an intermediate CA, supply the full chain by listing every file in +order (leaf certificate first): + +```yaml title="router.config.yaml" +traffic_shaping: + router: + tls: + cert_file: + - /etc/router/tls/server.crt + - /etc/router/tls/intermediate.crt + key_file: /etc/router/tls/server.key +``` + +### Mutual TLS (mTLS) for Inbound Connections + +mTLS requires clients to present a valid certificate signed by a trusted CA. This is useful in +zero-trust environments where you need to guarantee that only authorized clients can reach the +router. + +Set `client_auth.cert_file` to the CA certificate that signed your clients' certificates. Set +`client_auth.required` to `true` (the default when `client_auth` is configured) to reject clients +that do not present a valid certificate. + +```yaml title="router.config.yaml" +traffic_shaping: + router: + tls: + cert_file: /etc/router/tls/server.crt + key_file: /etc/router/tls/server.key + client_auth: + cert_file: /etc/router/tls/client-ca.crt + required: true +``` + +To make client certificates optional (for example, to accept both mTLS and plain TLS clients) +set `required: false`. + +## Outbound TLS (Router → Subgraphs) + +When subgraphs are served over HTTPS, the router validates their certificates using the operating +system's default CA bundle. No additional configuration is needed for subgraphs that use +publicly-trusted certificates. + +### Custom or Self-Signed CA + +If your subgraphs use a private CA or self-signed certificates, tell the router where to find the +trusted CA certificate: + +```yaml title="router.config.yaml" +traffic_shaping: + all: + tls: + cert_file: /etc/router/tls/subgraph-ca.crt +``` + +This applies to all subgraphs. To use a different CA for a specific subgraph, override it under +`subgraphs.`: + +```yaml title="router.config.yaml" +traffic_shaping: + all: + tls: + cert_file: /etc/router/tls/subgraph-ca.crt + subgraphs: + payments: + tls: + cert_file: /etc/router/tls/payments-ca.crt +``` + +Fields not set in a per-subgraph override fall back to the `all.tls` value. + +### Mutual TLS (mTLS) to Subgraphs + +Some subgraphs require the router to authenticate itself with a client certificate. Provide the +router's client certificate and key under `client_auth`: + +```yaml title="router.config.yaml" +traffic_shaping: + all: + tls: + cert_file: /etc/router/tls/subgraph-ca.crt + subgraphs: + accounts: + tls: + cert_file: /etc/router/tls/accounts-ca.crt + client_auth: + cert_file: /etc/router/tls/router-client.crt + key_file: /etc/router/tls/router-client.key +``` + +### Skipping Certificate Verification + + + `insecure_skip_ca_verification: true` disables verification of subgraph server + certificates. Only use this for local development or controlled testing, never + in production. + + +```yaml title="router.config.yaml" +traffic_shaping: + all: + tls: + insecure_skip_ca_verification: true +``` + +## Certificate Management Tips + +- **Store certificate files outside the config file.** Reference them by path so you can rotate + them without editing `router.config.yaml`. +- **Use a secrets manager or mounted secrets.** In Kubernetes, mount TLS secrets as volumes and + reference the resulting file paths in the config. +- **Rotate certificates by restarting the router.** The router reads certificate files at startup. + After replacing a certificate file, perform a rolling restart to pick up the new certificate with + zero downtime. +- **Keep private keys restricted.** Ensure key files are readable only by the user the router + process runs as (e.g. `chmod 600`). +- **Automate renewal.** Tools such as [cert-manager](https://cert-manager.io) (Kubernetes) or + [Certbot](https://certbot.eff.org) can renew certificates automatically and trigger a restart when + they do. diff --git a/packages/documentation/content/docs/router/subscriptions/websockets.mdx b/packages/documentation/content/docs/router/subscriptions/websockets.mdx index 850cd60e..7bedd55f 100644 --- a/packages/documentation/content/docs/router/subscriptions/websockets.mdx +++ b/packages/documentation/content/docs/router/subscriptions/websockets.mdx @@ -65,6 +65,19 @@ websocket: persist: false ``` +#### TLS and `wss://` + +When the router has [inbound TLS enabled](/docs/router/security/tls), WebSocket clients must use `wss://` instead of `ws://`. The router accepts secure WebSocket upgrades on the same port as HTTPS. + +```ts +import { createClient } from "graphql-ws"; + +const client = createClient({ + url: "wss://your-router.example.com/ws", + // ... +}); +``` + #### `enabled` Enables or disables WebSocket support for clients. Defaults to `false`. Can also be set via the `WEBSOCKET_ENABLED` environment variable.