Skip to content

[feat] PIP-468: V5 end-to-end encryption API redesign#25682

Open
merlimat wants to merge 1 commit intoapache:masterfrom
merlimat:st-v5-encryption-api
Open

[feat] PIP-468: V5 end-to-end encryption API redesign#25682
merlimat wants to merge 1 commit intoapache:masterfrom
merlimat:st-v5-encryption-api

Conversation

@merlimat
Copy link
Copy Markdown
Contributor

@merlimat merlimat commented May 5, 2026

Summary

Reshape the V5 end-to-end encryption surface so first-time setup is straightforward and misconfiguration is harder to express:

  • Role-specific async SPI: split the dual-role CryptoKeyReader into PublicKeyProvider (producer side) and PrivateKeyProvider (consumer side). Both return CompletableFuture<EncryptionKey> so KMS-backed implementations don't have to block. CryptoKeyProvider extends both for in-process use.
  • Per-side failure actions: split CryptoFailureAction into ProducerCryptoFailureAction (FAIL, SEND_UNENCRYPTED) and ConsumerCryptoFailureAction (FAIL, DISCARD, CONSUME). Compile-time prevents producer-side DISCARD/CONSUME misconfigurations.
  • Per-side policy types: split EncryptionPolicy into ProducerEncryptionPolicy and ConsumerEncryptionPolicy. The consumer policy accepts a null privateKeyProvider when the failure action is DISCARD or CONSUME — matching v4's "no key reader, just receive raw bytes" mode.
  • Cleaner value type: EncryptionKeyInfoEncryptionKey (final class, private ctor + of(...) factories). Avoids records' broken byte[] equality.
  • Batteries-included default: new PemFileKeyProvider for the common load-from-disk case. Eliminates v4's friction of having to implement the SPI from scratch just to encrypt one message.
  • Internal adapter: CryptoKeyReaderAdapter exposes role-specific forProducer / forConsumer factories that bridge to v4's combined CryptoKeyReader.

Test plan

  • PemFileKeyProviderTest (5 unit tests) — registered keys, missing key, missing file, dual-role usage.
  • EncryptionPolicyTest (9 unit tests) — builder validation, defaults, optional consumer provider for DISCARD/CONSUME.
  • V5EncryptionTest (4 end-to-end tests):
    • Producer encrypts → consumer decrypts on a single-segment scalable topic.
    • 30 messages across a 3-segment scalable topic, all decrypt correctly.
    • CONSUME without a provider delivers raw encrypted bytes.
    • DISCARD without a provider silently drops the message.
  • pulsar-client-api-v5, pulsar-client-v5, pulsar-broker checkstyle clean.

…verage

Reshape the V5 end-to-end encryption surface to make first-time setup
straightforward and to make misconfiguration harder to express:

- Split the dual-role CryptoKeyReader into role-specific PublicKeyProvider
  (producer side) and PrivateKeyProvider (consumer side) interfaces.
  Both signatures are async (CompletableFuture<EncryptionKey>) so KMS-
  backed implementations don't need to block. CryptoKeyProvider extends
  both for convenience when the same store serves both sides.

- Split the single CryptoFailureAction into ProducerCryptoFailureAction
  (FAIL, SEND_UNENCRYPTED) and ConsumerCryptoFailureAction (FAIL,
  DISCARD, CONSUME). Compile-time prevents producer-side DISCARD/CONSUME
  misconfigurations.

- Split EncryptionPolicy into ProducerEncryptionPolicy and
  ConsumerEncryptionPolicy, each with its own builder. ConsumerEncryption
  Policy lets the user skip the privateKeyProvider when the failure
  action is DISCARD or CONSUME — matching v4's "no key reader, just
  receive raw bytes" mode.

- Convert EncryptionKeyInfo to EncryptionKey (final class with private
  ctor + of(...) factories), avoiding records' broken byte[] equality.

- Ship a batteries-included PemFileKeyProvider for the common
  load-from-disk case, eliminating the v4 friction of having to
  implement the SPI from scratch just to encrypt one message.

- Internal CryptoKeyReaderAdapter now exposes role-specific
  forProducer / forConsumer factories that bridge to the v4
  CryptoKeyReader. Documents the sync-blocking constraint imposed by
  v4's MessageCrypto path (orthogonal to this change).

Tests:
- PemFileKeyProviderTest — read registered keys, missing key / file
  failure modes, dual-role usage.
- EncryptionPolicyTest — builder validation: required fields, default
  failure actions, DISCARD/CONSUME without a provider.
- V5EncryptionTest — end-to-end round trip on a single segment, on a
  3-segment scalable topic, and CONSUME / DISCARD action behavior with
  no provider configured.
@merlimat merlimat changed the title PIP-468: V5 end-to-end encryption API redesign [feat] PIP-468: V5 end-to-end encryption API redesign May 5, 2026
@lhotari lhotari self-requested a review May 5, 2026 23:01
Copy link
Copy Markdown
Member

@lhotari lhotari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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.

2 participants