5

I have a rabbitmq server and use the pika library with Python to produce/consume messages. For development purposes, I was simply using

credentials = pika.PlainCredentials(<user-name>, <password>)

I want to change that to use pika.ExternalCredentials or TLS.

I have set up my rabbitmq server to listen for TLS on port 5671, and have configured it correctly. I am able to communicate with rabbitmq from localhost, but the moment I try to communicate with it from outside the localhost it doesn't like that. I have a feeling my "credentials" are based on the "guest" user in rabbitmq.

rabbitmq.config

%% -*- mode: erlang -*-

[
 {rabbit,
  [
   {ssl_listeners, [5671]},
   {auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'EXTERNAL']},
   {ssl_options, [{cacertfile,"~/tls-gen/basic/result/ca_certificate.pem"},
                  {certfile,"~/tls-gen/basic/result/server_certificate.pem"},
                  {keyfile,"~/tls-gen/basic/result/server_key.pem"},
                  {verify,verify_none},
                  {ssl_cert_login_from, common_name},
                  {fail_if_no_peer_cert,false}]}
   
  ]}
].

I can confirm this works, since in my logs for rabbitmq I see:

2019-08-21 15:34:47.663 [info] <0.442.0> started TLS (SSL) listener on [::]:5671

Server-side everything seems to be set up, I have also generated certificates and all the .pem files required.

test_rabbitmq.py

import pika
import ssl
from pika.credentials import ExternalCredentials

context = ssl.create_default_context(cafile="~/tls-gen/basic/result/ca_certificate.pem")
context.load_cert_chain("~/tls-gen/basic/result/client_certificate.pem",
                            "~/tls-gen/basic/result/client_key.pem")
ssl_options = pika.SSLOptions(context, "10.154.0.27")
params = pika.ConnectionParameters(port=5671,ssl_options=ssl_options, credentials = ExternalCredentials())
connection = pika.BlockingConnection(params)
channel = connection.channel()

When I run the script locally

(<Basic.GetOk(['delivery_tag=1', 'exchange=', 'message_count=0', 'redelivered=False', 'routing_key=foobar'])>, <BasicProperties>, b'Hello, world!')

When I run the script from another instance

Traceback (most recent call last):
  File "pbbarcode.py", line 200, in <module>
    main()
  File "pbbarcode.py", line 187, in main
    connection = pika.BlockingConnection(params)
  File "/usr/local/lib/python3.7/site-packages/pika/adapters/blocking_connection.py", line 359, in __init__
    self._impl = self._create_connection(parameters, _impl_class)
  File "/usr/local/lib/python3.7/site-packages/pika/adapters/blocking_connection.py", line 450, in _create_connection
    raise self._reap_last_connection_workflow_error(error)
pika.exceptions.AMQPConnectionError

When I run the script locally, and delete the guest user

Traceback (most recent call last):
  File "test_mq.py", line 12, in <module>
    with pika.BlockingConnection(conn_params) as conn:
  File "/home/daudn/.local/lib/python3.7/site-packages/pika/adapters/blocking_connection.py", line 359, in __init__
    self._impl = self._create_connection(parameters, _impl_class)
  File "/home/daudn/.local/lib/python3.7/site-packages/pika/adapters/blocking_connection.py", line 450, in _create_connection
    raise self._reap_last_connection_workflow_error(error)
pika.exceptions.ProbableAuthenticationError: ConnectionClosedByBroker: (403) 'ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.'

It seems like SSL is configured with the user "guest" and rabbitmq doesn't allow connections to guest outside of localhost. How can I use SSL with a different user? When I delete the guest user, this is what the rabbitmq log says:

2019-08-22 10:14:40.054 [info] <0.735.0> accepting AMQP connection <0.735.0> (127.0.0.1:59192 -> 127.0.0.1:5671)
2019-08-22 10:14:40.063 [error] <0.735.0> Error on AMQP connection <0.735.0> (127.0.0.1:59192 -> 127.0.0.1:5671, state: starting):
PLAIN login refused: user 'guest' - invalid credentials
2019-08-22 10:14:40.063 [warning] <0.735.0> closing AMQP connection <0.735.0> (127.0.0.1:59192 -> 127.0.0.1:5671):
client unexpectedly closed TCP connection
2019-08-22 10:15:12.613 [info] <0.743.0> Creating user 'guest'
2019-08-22 10:15:28.370 [info] <0.750.0> Setting user tags for user 'guest' to [administrator]
2019-08-22 10:15:51.352 [info] <0.768.0> Setting permissions for 'guest' in '/' to '.*', '.*', '.*'
2019-08-22 10:15:54.237 [info] <0.774.0> accepting AMQP connection <0.774.0> (127.0.0.1:59202 -> 127.0.0.1:5671)
2019-08-22 10:15:54.243 [info] <0.774.0> connection <0.774.0> (127.0.0.1:59202 -> 127.0.0.1:5671): user 'guest' authenticated and granted access to vhost '/'

This also clearly means the SSL is still using the username and password to connect to rabbitmq? HELP!

References:

tls_official_example

pika_official_tls_docs

added_authentication_external

Community
  • 1
  • 1
DUDANF
  • 2,618
  • 1
  • 12
  • 42

2 Answers2

3

Going to leave this here for future reference

ssl_options = pika.SSLOptions(context, "rabbitmq-node-name")
params = pika.ConnectionParameters(host="rabbitmq-node-name",port=5671,ssl_options=ssl_options, credentials = ExternalCredentials())

The confusion was that I believed when doing SSLOptions(context, "rabbitmq-node-name") I thought I had supplied the host here and did not have to supply it again in the args for ConnectionParameters(). But turns out that's incorrect, if no host is supplied, it defaults to localhost. Which is why the script ran locally and not outside of the local network.

DUDANF
  • 2,618
  • 1
  • 12
  • 42
  • In case you get an error `module 'pika' has no attribute 'ExternalCredentials'`, then you need to import `ExternalCredentials` properly, for example by qualifying with `pika.credentials.ExternalCredentials`. – ivosh Jul 05 '23 at 15:04
1

You will have to enable the rabbitmq-auth-mechanism-ssl plugin , i think you are missing that part.

To enable the plugin do the following ( showing the example for a Windows setup)

rabbitmq-plugins.bat enable rabbitmq_auth_mechanism_ssl
Soumen Mukherjee
  • 2,953
  • 3
  • 22
  • 34
  • I have edited my question, the problem is that SSL is configured with the default 'guest' user, and so I can't access it from outside the local environment. – DUDANF Aug 22 '19 at 10:25
  • Can you share the rabbitmq logs when access is denied to the user guest whiel logging in from a remote system ? – Soumen Mukherjee Aug 22 '19 at 11:26
  • Nothing appears in the logs since it directly throws ```pika.exceptions.AMQPConnectionError``` – DUDANF Aug 22 '19 at 11:29
  • .... If you have a look at my code "test_rabbitmq.py" I don't specify a user/password since I am trying to access it over SSL? When the similar code is run on the localhost, the logs say: ```2019-08-22 10:14:40.063 [error] <0.735.0> Error on AMQP connection <0.735.0> (127.0.0.1:59192 -> 127.0.0.1:5671, state: starting): PLAIN login refused: user 'guest' - invalid credentials``` – DUDANF Aug 22 '19 at 11:31
  • Humm.. can you give External the first precedence like this {auth_mechanisms, ['EXTERNAL','PLAIN', 'AMQPLAIN'}, – Soumen Mukherjee Aug 22 '19 at 11:33
  • This is the problem: ```2019-08-22 11:36:45.660 [info] <0.615.0> accepting AMQP connection <0.615.0> (127.0.0.1:59680 -> 127.0.0.1:5671) 2019-08-22 11:36:45.666 [info] <0.615.0> connection <0.615.0> (127.0.0.1:59680 -> 127.0.0.1:5671): user 'guest' authenticated and granted access to vhost '/'``` It uses "guest" and not the user I have created. How to make it use a different user! – DUDANF Aug 22 '19 at 11:37
  • Hello, I am one of Pika's maintainers. Please continue the discussion via the [`pika-python`](https://groups.google.com/d/topic/pika-python/lHv1Ho_I_DU/discussion) mailing list. – Luke Bakken Aug 22 '19 at 14:41