Search code examples
pythonsslrabbitmqpika

How to debug "pika.exceptions.AuthenticationError: EXTERNAL" error when establishing TLS connection to RabbitMQ?


I have a RabbitMQ 3.6.1 server on Ubuntu 14.04 running properly. I tried to configure an SSL listener according to official documentation. No problems during the startup.

However when trying to establish a connection, I get the following error on Python/pika side (full transcript below):

pika.exceptions.AuthenticationError: EXTERNAL

What does EXTERNAL mean here? How to debug / get further details of the error?


Course of actions (to test I used a Vagrant box and a local connection):

  1. RabbitMQ starts SSL Listener on port 5671 (per /var/log/rabbitmq/[email protected]):

    started SSL Listener on [::]:5671
    
  2. I execute the pika.BlockingConnection on the client side.

  3. On the server side I can see an incoming connection:

    =INFO REPORT==== 17-Apr-2016::17:07:15 ===
    accepting AMQP connection <0.2788.0> (127.0.0.1:48404 -> 127.0.0.1:5671)
    
  4. Client fails with:

    pika.exceptions.AuthenticationError: EXTERNAL
    
  5. Server timeouts:

    =ERROR REPORT==== 17-Apr-2016::17:07:25 ===
    closing AMQP connection <0.2788.0> (127.0.0.1:48404 -> 127.0.0.1:5671):
    {handshake_timeout,frame_header}
    

Full transcript of the client side:

>>> import pika, ssl
>>> from pika.credentials import ExternalCredentials
>>> ssl_options = ({"ca_certs": "/etc/rabbitmq/certs/testca/cacert.pem",
...                 "certfile": "/etc/rabbitmq/certs/client/cert.pem",
...                 "keyfile": "/etc/rabbitmq/certs/client/key.pem",
...                 "cert_reqs": ssl.CERT_REQUIRED,
...                 "server_side": False})
>>> host = "localhost"
>>> connection = pika.BlockingConnection(
...                  pika.ConnectionParameters(
...                      host, 5671, credentials=ExternalCredentials(),
...                      ssl=True, ssl_options=ssl_options))
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 339, in __init__
    self._process_io_for_connection_setup()
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 374, in _process_io_for_connection_setup
    self._open_error_result.is_ready)
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 410, in _flush_output
    self._impl.ioloop.poll()
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/select_connection.py", line 602, in poll
    self._process_fd_events(fd_event_map, write_only)
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/select_connection.py", line 443, in _process_fd_events
    handler(fileno, events, write_only=write_only)
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/base_connection.py", line 364, in _handle_events
    self._handle_read()
  File "/usr/local/lib/python2.7/dist-packages/pika/adapters/base_connection.py", line 415, in _handle_read
    self._on_data_available(data)
  File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1347, in _on_data_available
    self._process_frame(frame_value)
  File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1414, in _process_frame
    if self._process_callbacks(frame_value):
  File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1384, in _process_callbacks
    frame_value)  # Args
  File "/usr/local/lib/python2.7/dist-packages/pika/callback.py", line 60, in wrapper
    return function(*tuple(args), **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pika/callback.py", line 92, in wrapper
    return function(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pika/callback.py", line 236, in process
    callback(*args, **keywords)
  File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1298, in _on_connection_start
    self._send_connection_start_ok(*self._get_credentials(method_frame))
  File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1077, in _get_credentials
    raise exceptions.AuthenticationError(self.params.credentials.TYPE)
pika.exceptions.AuthenticationError: EXTERNAL
>>>

Solution

  • The Python / pika code in the question is correct.

    The error:

    pika.exceptions.AuthenticationError: EXTERNAL

    is reported when client certificate authorisation is not enabled on the RabbitMQ server side. The word EXTERNAL in the error refers to the authentication mechanism as described here.

    To enable:

    rabbitmq-plugins enable rabbitmq_auth_mechanism_ssl