Skip to content

MEDIUM: ssl: share and rotate TLS ticket keys across replicas - #874

Open
PixiBixi wants to merge 2 commits into
haproxytech:masterfrom
PixiBixi:feat/tls-ticket-keys
Open

PixiBixi wants to merge 2 commits into
haproxytech:masterfrom
PixiBixi:feat/tls-ticket-keys

Conversation

@PixiBixi

@PixiBixi PixiBixi commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Each HAProxy instance generates its own TLS ticket keys, and new ones on every reload. Behind several replicas (DNS round robin, a load balancer without affinity), a client that lands on another replica, or comes back after a reload, cannot resume its session and pays a full handshake.

This adds a tls-ticket-keys ConfigMap annotation holding the path of a keys file, typically mounted from a Secret:

  • MEDIUM: ssl: add the tls-ticket-keys configmap annotation: sets tls-ticket-keys <file> on the v4, v6 and ssl-passthrough binds of the https frontend when SSL offload is enabled. The quic binds are left untouched. An unreadable path is ignored, since HAProxy would reject the configuration. A reload is requested only when a bind changes.
  • MEDIUM: ssl: rotate tls-ticket-keys through the runtime API: on every sync tick, when the file changed, the controller compares the loaded keys (show tls-keys) with the last three lines of the file and pushes only the missing ones with set ssl tls-key. A rotation therefore needs no reload. A failed runtime update falls back to a reload.

The Frontend v3 custom resource has a tls_ticket_keys field, but the controller-owned binds win the merge, so it cannot set it on the https binds today.

Tests

  • Unit tests for the bind update and the rotation diff (pkg/handler, pkg/controller).
  • On kind, 2 replicas with the companion chart change (MINOR: kubernetes-ingress: add TLS ticket keys support helm-charts#400):
    • the generated config carries tls-ticket-keys on the v4 and v6 binds only;
    • openssl s_client -sess_out on replica A then -sess_in on replica B: Reused with TLS 1.2 and 1.3, New without the annotation;
    • after rotating the Secret (drop the first key, append one): pushed a rotated key in both controllers, no reload, show tls-keys matching the new file, and a ticket issued before the rotation still Reused on the other replica.

Each HAProxy instance generates its own TLS ticket keys, and generates
new ones on every reload. A client spread over several replicas, or
reconnecting after a reload, cannot resume its session and pays a
full handshake.

tls-ticket-keys takes the path of a keys file, typically mounted from
a Secret, and sets it on the v4, v6 and ssl-passthrough binds of the
https frontend when SSL offload is enabled. Replicas sharing the file
resume each other's sessions. The quic binds are left untouched.

The path is ignored when the file cannot be read, since HAProxy would
reject the configuration. It is applied after the ssl-passthrough
toggle, which recreates the binds, and a reload is requested only when
a bind changes. A rotated file is picked up on the next reload.
HAProxy reads the tls-ticket-keys file only when it starts or reloads,
so a rotated Secret was applied at the next unrelated reload, and
forcing one costs a reload per rotation.

On every sync tick, the controller now checks whether the keys file
changed. When it did, it compares the keys HAProxy holds (show tls-keys)
with the last three lines of the file and pushes only the missing ones
with set ssl tls-key, which appends a key and drops the oldest. A
rotation that appended one key pushes that key, and one already loaded
by a reload in between pushes nothing. A failed runtime update falls
back to a reload, which reads the file again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant