Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR implements the legacy SASL implementation still in use by the python driver.
I am not aware of any other drivers that use it.
The protocol docs describe the situation pretty well.
To summarize, when the client sends a SaslHandshake request of version 0, the client and broker will perform all SASL communication over raw packets.
Implementing this within shotover requires a lot of complexity, but it is ultimately manageable, and the implementation does not impact non-legacy SASL.
While the docs do not specify this, I am assuming that the client will always send its raw sasl requests immediately after sending a v0 SaslHandshake. The python driver at least behaves this way, and we would have to resort to heuristics to detect message types if any driver did behave this way.
Overview of implementation
To implement this functionality the following is done:
CodecState
Refer to this comment about CodecState:
In this PR
CodecState::Kafka
is expanded to containKafkaCodecState
struct which contains the existing request_header field along with the newraw_sasl: Option<SaslRequestState>
field. When this field is None the standard message handling occurs, when it is Some special encoding and decoding paths will be taken to pretend the raw sasl messages are SaslAuthenticate v0 messages. This ensures that the transforms can treat these raw messages just like they do for the regular sasl messages, completely hiding the distinction from them. This makes KafkaSinkCluster simple to implement and also makes any possible future transforms simple to implement too.Codecs
In order to correctly populate the
CodecState
value, theKafkaEncoder
andKafkaDecoder
need to coordinate with each other to keep track of any SaslHandshake v0 that pass through in order to mark the following messages as raw sasl messages in the KafkaCodecState.Overall Flow
client request -> kafka (SaslHandshake v0)
self.expect_raw_sasl = Some(_)
expect_raw_sasl = Some()
to Sink KafkaDecoderkafka response -> client (SaslHandshake v0)
self.expect_raw_sasl = Some(_)
from KafkaDecoderclient request -> kafka (raw sasl)
self.expect_raw_sasl
being Some, as a result it sets theKafkaCodecState::raw_sasl
field on the message.KafkaCodecState::raw_sasl
field.KafkaCodecState::raw_sasl
field.kafka response -> client (raw sasl)
self.expect_raw_sasl
being Some, as a result it sets theKafkaCodecState::raw_sasl
field on the message.KafkaCodecState::raw_sasl
field.KafkaCodecState::raw_sasl
field.Other fixes
There were a few unrelated misc fixes that were needed to get the new integration tests working.
.kill_on_drop(true)
is needed to ensure the python scripts do not linger around after a failed test.New tests
Added tests for:
Alternatives
We could submit a patch to the python driver that upgrades it to use the modern SASL implementation.
This is probably worth doing if we ever have the resources to spare.
But we should probably still still ship this implementation so that we can handle any other drivers out there still using this old SASL implementation. I dont think kafka has ever deprecated old parts of the protocol before.