Skip to content

TLS parameters example

This example demonstrates a TLS session with RabbitMQ using mutual authentication (server and client authentication).

See the RabbitMQ TLS/SSL documentation for certificate generation and RabbitMQ TLS configuration. Please note that the RabbitMQ TLS (x509 certificate) authentication mechanism must be enabled for these examples to work.

examples/tls_mutual_authentication.py:

import logging
import ssl
from pathlib import Path

import pika

logging.basicConfig(level=logging.INFO)

_certs = Path(__file__).resolve().parent.parent / 'tests' / 'certs'

context = ssl.create_default_context(cafile=str(_certs / 'ca_certificate.pem'))
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(str(_certs / 'client_certificate.pem'),
                        str(_certs / 'client_key.pem'))
ssl_options = pika.SSLOptions(context, 'localhost')
conn_params = pika.ConnectionParameters(port=5671, ssl_options=ssl_options)

with pika.BlockingConnection(conn_params) as conn:
    ch = conn.channel()
    ch.queue_declare('foobar')
    ch.basic_publish('', 'foobar', b'Hello, world!')
    print(ch.basic_get('foobar'))
rabbitmq.config:

# Enable AMQPS
listeners.ssl.default = 5671
ssl_options.cacertfile = PIKA_DIR/testdata/certs/ca_certificate.pem
ssl_options.certfile = PIKA_DIR/testdata/certs/server_certificate.pem
ssl_options.keyfile = PIKA_DIR/testdata/certs/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true

# Enable HTTPS
management.listener.port = 15671
management.listener.ssl = true
management.listener.ssl_opts.cacertfile = PIKA_DIR/testdata/certs/ca_certificate.pem
management.listener.ssl_opts.certfile = PIKA_DIR/testdata/certs/server_certificate.pem
management.listener.ssl_opts.keyfile = PIKA_DIR/testdata/certs/server_key.pem
To perform mutual authentication with a Twisted connection:

from pathlib import Path

from twisted.internet import defer, protocol, reactor, ssl

from pika import ConnectionParameters
from pika.adapters import twisted_connection
from pika.credentials import ExternalCredentials


@defer.inlineCallbacks
def publish(connection):
    channel = yield connection.channel()
    yield channel.basic_publish(
        exchange='amq.topic',
        routing_key='hello.world',
        body='Hello World!',
    )
    print('published')


def connection_ready(conn):
    conn.ready.addCallback(lambda _: conn)
    return conn.ready


_certs = Path(__file__).resolve().parent.parent / 'tests' / 'certs'
# Load the CA certificate to validate the server's identity
with _certs.joinpath('ca_certificate.pem').open() as fd:
    ca_cert = ssl.Certificate.loadPEM(fd.read())

# Load the client certificate and key to authenticate with the server
with _certs.joinpath('client_key.pem').open() as fd:
    client_key = fd.read()
with _certs.joinpath('client_certificate.pem').open() as fd:
    client_cert = fd.read()
client_keypair = ssl.PrivateCertificate.loadPEM(client_key + client_cert)

context_factory = ssl.optionsForClientTLS(
    'localhost',
    trustRoot=ca_cert,
    clientCertificate=client_keypair,
)
params = ConnectionParameters(credentials=ExternalCredentials())
cc = protocol.ClientCreator(reactor,
                            twisted_connection.TwistedProtocolConnection,
                            params)
deferred = cc.connectSSL('localhost', 5671, context_factory)
deferred.addCallback(connection_ready)
deferred.addCallback(publish)
reactor.run()