Apache Pulsar supports client-side encryption where messages can be encrypted by producers and decrypted by consumers. When a message is encrypted, Pulsar includes an EncryptionContext
with each message that contains encryption metadata such as:
Key concepts:
FAIL
: Fail message consumption (default)DISCARD
: Silently discard the messageCONSUME
: Deliver the encrypted message to the applicationCurrently, when ConsumerCryptoFailureAction.CONSUME
is configured, consumers can receive encrypted messages even when decryption fails (e.g., missing private key, mismatched keys). However, applications have no way to determine whether the received message was successfully decrypted or is still encrypted.
Applications using Pulsar's encryption feature with ConsumerCryptoFailureAction.CONSUME
need to determine whether received messages were successfully decrypted or if decryption failed. This is essential for:
Current situation:
CONSUME
action receive messages regardless of decryption successUse cases this solves:
isEncrypted
boolean field to the EncryptionContext
classConsumerCryptoFailureAction
behaviorThe solution adds a simple boolean field isEncrypted
to the existing EncryptionContext
class. This field is set during message processing in the consumer:
isEncrypted
is set to false
ConsumerCryptoFailureAction.CONSUME
is configured, isEncrypted
is set to true
EncryptionContext
is created (existing behavior)The field is populated in the consumer's message creation logic, specifically in the createEncryptionContext()
method where the decryption success/failure status is already known.
Applications can then check this field to determine if the received message payload is encrypted or decrypted:
Message<byte[]> message = consumer.receive(); Optional<EncryptionContext> ctx = message.getEncryptionCtx(); if (ctx.isPresent()) { if (ctx.get().isEncrypted()) { // Handle encrypted message - decryption failed handleEncryptedMessage(message, ctx.get()); } else { // Handle decrypted message - decryption succeeded handleDecryptedMessage(message); } }
New method available via Lombok-generated getter:
public boolean isEncrypted()
Usage pattern:
Message<T> message = consumer.receive(); Optional<EncryptionContext> encryptionCtx = message.getEncryptionCtx(); if (encryptionCtx.isPresent()) { boolean encrypted = encryptionCtx.get().isEncrypted(); if (encrypted) { // Message is encrypted (decryption failed) } else { // Message is decrypted (decryption succeeded) } }
Breaking Changes: None - this is a purely additive change.
No compatibility concerns.
Rolling back to a previous Pulsar version:
isEncrypted()
will get compilation errors - this is expectedisEncrypted()
from application code