sidb98 opened a new pull request, #23288:
URL: https://github.com/apache/kafka/pull/23288

   ## Summary
   In KRaft, `KafkaRaftManager` builds its controller-quorum network client 
with an
   `SslChannelBuilder` that is never registered as a `Reconfigurable` on the 
config that
   processes dynamic updates. A renewed controller-listener certificate 
therefore never
   reaches the running Raft channel: it keeps the cert loaded at startup and, 
on the next
   reconnect (e.g. controller failover), can present a stale/expired cert, 
breaking the
   broker↔controller connection and stalling metadata propagation. 
(KAFKA-20025.)
   
   `SharedServer` creates three `KafkaConfig` objects (`sharedServerConfig`, 
`brokerConfig`,
   `controllerConfig`). `RaftManager` is constructed with `sharedServerConfig`, 
whose
   `dynamicConfig` is initialized but never receives cert-rotation updates 
(those go to
   `brokerConfig`/`controllerConfig`), so self-registering on RaftManager's own 
config would
   be a silent no-op.
   
   ## Changes
   - `KafkaRaftManager`: expose the channel's `Reconfigurable` 
(`reconfigurableChannelBuilder`)
     and capture it when the channel builder is an SSL builder.
   - `BrokerServer` / `ControllerServer`: register it on their own config
     (`config.dynamicConfig.addReconfigurable`) alongside the other 
reconfigurables, keeping
     `RaftManager` on `sharedServerConfig` while routing the reconfigurable to 
the config that
     actually receives cert-rotation updates.
   
   ## Testing
   **Unit** : 
`RaftManagerTest.testRaftManagerExposesSslChannelBuilderAsReconfigurable`: a
   RaftManager built with an SSL controller listener exposes its 
`SslChannelBuilder` via
   `reconfigurableChannelBuilder`.
   
   **Integration** : `RaftManagerSslReconfigIntegrationTest`: brings up an SSL
   KRaft cluster, rotates the broker's 
`listener.name.controller.ssl.keystore.*` from cert A
   to cert B via `incrementalAlterConfigs`, and asserts the certificate serial 
loaded in the
   running Raft channel's `SslFactory` (read by reflection) flips A → B. 
Reverting the
   registration makes it fail with "Raft channel SslFactory never loaded the 
rotated keystore
   (cert B)". Deterministic: it inspects the loaded keystore directly, not cert 
expiry or
   handshake timing. Cert A and B share a CA (controller trusts both; cluster 
stays healthy)
   and a subject DN.
   
   ## Alternate integration test considered but rejected
   `Kraft cluster with short-lived cert A → rotate to B → force re-handshake → 
assert no SSL
   error`
   
   This is flaky by construction: invalidating the old cert relies on expiry (A 
and B share
   a CA), and JSSE's PKIX validation reads the real system clock with no 
injectable clock,
   giving a bring-up race and an expiry race that generous margins only slow 
down, never
   remove. The implemented test asserts the fix's effect deterministically 
instead.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to