Thrift SASL Python Client
This is a Python library (version 0.4.3) that provides SASL (Simple Authentication and Security Layer) transport for Apache Thrift clients. It enables secure communication by implementing `TSaslClientTransport`, allowing Thrift applications to use authentication mechanisms like Kerberos. The library has a maintenance release cadence, with the latest update in May 2021.
Warnings
- breaking Older versions of `thrift-sasl` (prior to 0.4.3) depended on the unmaintained `sasl` package, which had compatibility issues with newer Python versions and required `g++` for compilation. Version `0.4.3` switched to `pure-sasl` to resolve this, making it pure-Python compatible.
- gotcha Correct configuration of SASL parameters (e.g., mechanism, username, password, service principal) is crucial and highly dependent on your server's SASL setup. Incorrect parameters will lead to authentication failures. For GSSAPI (Kerberos), ensure you have valid Kerberos tickets (`kinit`) and the correct service principal.
- gotcha It's essential to wrap the underlying Thrift transport (e.g., `TSocket`) with a buffered transport (`TBufferedTransport`) before passing it to `TSaslClientTransport`. The `thrift-sasl` library, particularly in versions 0.4.3a1 and later, includes fixes to ensure frames are fully buffered.
Install
-
pip install thrift-sasl
Imports
- TSaslClientTransport
from thrift_sasl import TSaslClientTransport
Quickstart
import os
from thrift.transport import TSocket, TTransport
from thrift.protocol import TBinaryProtocol
from thrift_sasl import TSaslClientTransport
# --- Configuration (replace with your actual values) ---
SASL_MECHANISM = os.environ.get('SASL_MECHANISM', 'PLAIN') # e.g., 'GSSAPI', 'PLAIN'
SASL_USERNAME = os.environ.get('SASL_USERNAME', 'user')
SASL_PASSWORD = os.environ.get('SASL_PASSWORD', 'password') # Only for PLAIN mechanism
THRIFT_HOST = os.environ.get('THRIFT_HOST', 'localhost')
THRIFT_PORT = int(os.environ.get('THRIFT_PORT', '9090'))
# For GSSAPI, you might need: SASL_SERVICE_PRINCIPAL = 'thrift/host.example.com@REALM'
# 1. Create a base Thrift socket transport
socket = TSocket.TSocket(THRIFT_HOST, THRIFT_PORT)
# 2. Wrap the socket in a buffered transport (often required)
buffered_transport = TTransport.TBufferedTransport(socket)
# 3. Create the SASL client transport
# For PLAIN mechanism:
sasl_transport = TSaslClientTransport(
buffered_transport,
SASL_MECHANISM,
username=SASL_USERNAME,
password=SASL_PASSWORD
)
# For GSSAPI, you would typically use:
# sasl_transport = TSaslClientTransport(
# buffered_transport,
# SASL_MECHANISM,
# service_principal=SASL_SERVICE_PRINCIPAL
# )
# 4. Open the SASL transport (initiates SASL handshake)
try:
sasl_transport.open()
print(f"Successfully opened SASL transport to {THRIFT_HOST}:{THRIFT_PORT}")
# 5. Create a protocol (e.g., TBinaryProtocol) using the SASL transport
protocol = TBinaryProtocol.TBinaryProtocol(sasl_transport)
# At this point, you would typically create a Thrift client
# and make remote procedure calls (RPCs).
# Example: client = MyThriftService.Client(protocol)
# result = client.my_method()
# print(f"RPC result: {result}")
except TTransport.TTransportException as e:
print(f"Thrift transport error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# 6. Close the transport
if sasl_transport.isOpen():
sasl_transport.close()
print("SASL transport closed.")