There is some interest in supporting various SASL mechanisms not
currently included in the library:
* dpkp#2110 (DMS)
* dpkp#2204 (SSPI)
* dpkp#2232 (AWS_MSK_IAM)
Adding these mechanisms in the core library may be undesirable due to:
* Increased maintenance burden.
* Unavailable testing environments.
* Vendor specificity.
This commit provides a quick prototype for a pluggable SASL system.
---
**Example**
To define a custom SASL mechanism a module must implement two methods:
```py
def validate_config(conn):
# Check configuration values, available libraries, etc.
assert conn.config['vendor_specific_setting'] is not None, (
'vendor_specific_setting required when sasl_mechanism=MY_SASL'
)
def try_authenticate(conn, future):
# Do authentication routine and return resolved Future with failed
# or succeeded state.
```
And then the custom mechanism should be registered before initializing
a KafkaAdminClient, KafkaConsumer, or KafkaProducer:
```py
import kafka.sasl
from kafka import KafkaProducer
import my_sasl
kafka.sasl.register_mechanism('MY_SASL', my_sasl)
producer = KafkaProducer(sasl_mechanism='MY_SASL')
```
---
**Notes**
**ABCs**
This prototype does not implement an ABC for custom SASL mechanisms.
Using an ABC would reduce a few of the explicit assertions involved with
registering a mechanism and is a viable option. Due to differing feature
sets between py2/py3 this option was not explored, but shouldn't be
difficult.
**Private Methods**
This prototype relies on some methods that are currently marked as
**private** in `BrokerConnection`.
* `._can_send_recv`
* `._lock`
* `._recv_bytes_blocking`
* `._send_bytes_blocking`
A pluggable system would require stable interfaces for these actions.
**Alternative Approach**
If the module-scoped dict modification in `register_mechanism` feels too
clunky maybe the addtional mechanisms can be specified via an argument
when initializing one of the `Kafka*` classes?