# Secure a Gateway deployment

<table><caption class="sr-only">Secure a Gateway deployment</caption><thead><tr><th scope="col">Source</th><th scope="col">Destination</th><th scope="col">Protocol</th><th scope="col">Port</th><th scope="col">Direction</th><th scope="col">Purpose</th><th scope="col">Required</th></tr></thead><tbody><tr><td>Product installation</td><td>Gateway client listener</td><td>HTTP or HTTPS</td><td>configured <code>api.*.listen</code></td><td>inbound</td><td>Lease and status API</td><td>Yes</td></tr><tr><td>Health checker</td><td>Gateway client listener</td><td>HTTP or HTTPS</td><td>configured client port</td><td>inbound</td><td><code>/healthz</code>, <code>/readyz</code></td><td>Optional</td></tr><tr><td>Gateway A</td><td>Gateway B</td><td>mutual TLS</td><td>configured peer listen (example 9443)</td><td>both</td><td>Raft replication</td><td>HA only</td></tr><tr><td>Gateway A</td><td>Gateway B</td><td>mutual TLS</td><td>configured reconciliation listen (example 9543)</td><td>both</td><td>Partition reconciliation</td><td>HA only</td></tr><tr><td>Gateway</td><td>customer OTLP Collector</td><td>OTLP/gRPC or HTTP/protobuf</td><td>Collector endpoint (commonly 4317/4318)</td><td>outbound</td><td>Metrics and traces</td><td>Optional</td></tr></tbody></table>

Expose only the configured client listener and restrict peer ports to the two replicas. Use HTTPS/mTLS for untrusted or shared paths. HTTP requires `allow_insecure_http: true`; bearer tokens can be replayed if captured. `none` delegates authentication to the customer network perimeter and gives callers one shared principal.

Run as an unprivileged account. Restrict license, state key, private keys, bearer mapping, mTLS mapping, telemetry-header files, state, backups, and detailed reports to the service account and approved operators. Store secrets outside source control. Gateway-owned structured logs redact values under recognized sensitive keys and, for string/error values, high-confidence credential representations, but this is defense in depth rather than a complete secret detector. Callers must not log raw credentials, credential-bearing URLs, arbitrary request/configuration objects, or unsanitized errors. Metrics, traces, reports, and startup diagnostics use separate output paths and allowlists; review them before sharing and do not assume the structured-log redactor covers them. Peer certificates must chain to the peer CA, have a CN matching the configured peer identity, and a target-matching SAN. Rotate certificate/mapping changes by restart. V1 does not provide CRL/OCSP or online state-key rotation.

Keep credentials in the dedicated secret files and telemetry headers documented below. `telemetry.otlp_endpoint` rejects userinfo, query parameters, and fragments; use `telemetry.auth_headers` and inspect startup errors before forwarding them to support.

## Configure client authentication

Enable exactly one client listener. HTTPS supports `none` or `mtls`; HTTP supports `none` or `bearer` and requires `api.http.allow_insecure_http: true`. `none` trusts the network perimeter and gives all callers the one configured fixed principal. That principal has exactly one `allowed_license_type`, so use mTLS or bearer mappings when the Gateway must distinguish installations or authorize both product types. Use mTLS when the path is not fully controlled.

Every authenticated principal has exactly one `allowed_license_type`: `phocol` or `lmc_exporter`. It may acquire, renew, retrieve, and release only leases of that type; the request body cannot select a different type. Configure separate principals for installations that use different product types. There is no configured entry-count limit for a mapping file, but it must contain at least one entry and its complete YAML document must not exceed 1 MiB. Every mapped type must also be present in the verified Gateway license or the Gateway rejects the configuration at startup.

In `mtls` and `bearer` modes, leave `api.auth.principal_id`, `api.auth.allowed_license_type`, and `api.auth.operator` unset. Identity and authorization come from the selected mapping file. The fixed fields are valid only in `none` mode.

For mTLS, set `api.auth.mode: mtls`, configure the server certificate/key and client CA, and make `api.https.principal_mappings_file` a strict YAML file:

```
principals:
  - common_name: product-phocol-01
    principal_id: product-phocol-01
    allowed_license_type: phocol
    operator: false
  - common_name: product-lmc-exporter-01
    principal_id: product-lmc-exporter-01
    allowed_license_type: lmc_exporter
    operator: false
  - common_name: gateway-operator
    principal_id: gateway-operator
    allowed_license_type: phocol
    operator: true
```

`common_name` matches the client certificate Subject CN exactly and case-sensitively. Empty or duplicate names, unmapped certificates, wildcard matching, and conflicting authority for a reused `principal_id` are rejected. The customer CA must issue the client certificate.

For bearer authentication, set `api.auth.mode: bearer` and make `api.http.bearer_credentials_file` a strict YAML file containing hashes, never plaintext tokens:

```
credentials:
  - sha256: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
    principal_id: product-phocol-01
    allowed_license_type: phocol
  - sha256: abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789
    principal_id: product-lmc-exporter-01
    allowed_license_type: lmc_exporter
```

The presented opaque token must be at least 32 bytes. Gateway hashes it with SHA-256 and performs a constant-time comparison. Hashes must be valid and unique; bearer principals cannot perform operator-only reads. A repeated `principal_id` must retain the same license-type and operator authority across all of its mappings. Rotate credentials by changing the mapping file and restarting Gateway.

`allowed_license_type` scopes lease ownership and mutation, not customer-wide metadata reads. Authenticated `none` and mTLS callers can see all types declared by the Gateway license through `GET /v1/license` and `GET /v1/entitlements`; those responses are not filtered to the caller’s allowed type. Bearer mode cannot access those endpoints because it is restricted to lease paths.
