I tried to solve this issue and got to the following:
1) Added support for EXTERNAL authentication into sasl.py
2) Added new attributes to the Connection class in messaging/endpoints.py
3) Modified the connect method of class Driver in messaging/driver.py
4) Modifies the TLS class - added certificates as parameters and used them wrap_socket call in messaginf/transports.py
In general, I added 3 new attributes:
a) keyfile - client's private key in PEM format
b) certfile - client's public key (eventually both, public and private keys - in such case the keyfile can be omitted) in PEM format
c) trustfile - public key of the broker, to verify brokers identity (CRT file is working for me)
The user uses them when creating new Connection object together with specifiyng the transport (ssl) and the sasl_mechanism (PLAIN or EXTERNAL).
With these changes I managed to get this to work for unencrypted+PLAIN, ssl+PLAIN and ssl+EXTERNAL.
However, there are some smaller issues with my solution:
I) The certificate in trustfile is not verified against the broker - you don't even need to pass the brokers public key to the Connection object and it still works. This seems to be a problem of the Python SSL library. However, I still left the trustfile attribute there, since it may be fixed in the future.
II) With EXTERNAL authentication, there doesn't seem to be any easy way how to get the username (CN=xxxx in certificates subject) from the certificate. The only option seems to be reading the file and searching for the CN, which I'm not sure is a good idea. Therefore, my current implementation expect the user to enter the username as a normal username attribute when creating the Connection object.
III) The the PEM certificates are encrypted, the Python asks for password. so it is kinda working. I didn't found any way how to enter the password inside the script.
IV) The broker URL supports SSL by using the "ampqs://" protocol specification. However, I'm not aware of any existing parameters in the URL string to pass the certificates. Therefore my modifications are working only when passing the specific parameters manually when creating the Connection object instead of using the URL.
Despite of these problems, I believe it would be worth to commit my changes (or some changes based on this), because the resulting functionality would be better then the existing is.