A-MQ and AMQP.Net Lite with TLS/SSL

In this post I’m going to show how to encrypt the communications between the Red Hat JBoss A-MQ (A-MQ) broker and the AMQP.Net Lite (Lite) client.

  • Disclaimer: This article is a demonstration of the security concepts with concrete examples and recipes you can use for testing on a private network. It is not a manual for securing clients and brokers on a public network nor is it a tutorial on TLS/SSL in .NET or Java.

Overview

There are two levels of authentication that can be performed:

TLS Handshake

TLS provides an authenticated and secured communications channel. For simple TLS the broker must present a certificate that is signed by a certificate authority (CA) that the client trusts.

TLS Handshake with Client Certificate Request

The broker must always send a certificate to the client to start the secure channel with the TLS Handshake. Using a client certificate request the broker can demand that the client authenticate itself by returning a certificate to the broker. The client’s identity is securely embedded in the client certificate and by carefully controlling who gets the client certificates a system administrator may control who gets access to resources in the A-MQ broker.

This is useful for messaging environments where the broker must confirm the identity of the client with stronger authentication than just a username and password.

Security Providers

The Lite client and the A-MQ broker use different security providers for creating and managing SSL/TLS connections.

In either case we must configure the security provider with the proper certificates before the provider can set up secure SSL/TLS communication channels.

Certificate Generation Tools

In this example we are going to generate all the certificates locally. There are plenty of certificate generation tools from which to choose:

  • OpenSSL
  • Java Keytool
  • IBM KeyMan
  • Microsoft Makecert
  • Portecle
  • and more …

For this article I choose to use Java Keytool from Oracle to run on a Windows host. To get keytool, install Java Platform, Standard Edition (Java SE), and add the kit to your execution environment. These settings add version jdk1.7.0_79 to a process environment:

set java_home=c:\program files\java\jdk1.7.0_79
set      path=%path%;%java_home%\bin

Generate a set of certificates

Overview

The script generates all the certificates needed for TLS Handshake and Client Certificate exchange.
The steps to perform are:

  • Create a private, local Certificate Authority (the ‘CA’)
  • Create a key pair for the broker and sign it with CA
  • Import CA and broker certificates into broker keystore
  • Create a key pair for the client and sign it with CA
  • Import CA and client certificates into client keystore
  • Export client private key and certificate trust chain into a Personal Information Exchange
  • Create a trust store for the broker; import CA certificate into it

Configuration script changes required for your setup

In this script you need to adjust some variables to match the environment in which the scripts will be used.

  • CERT_LOC The folder where all the certificates are generated and stored. The default is .\certs and that is usually adequate for test purposes.
  • CA_CN The name of the self-signed certificate authority this script creates. There are no limits on this value but use some common sense and don’t create a name that conflicts with any public certificate authority.
  • BROKER_CN This name must be that public hostname of the broker system. This is the name in the connection URL that the client uses to access the broker.
  • CLIENT_CN This is the client’s username used in the client certificate.

For more complicated installations you may want more descriptive file names. The file path suffixes (.keystore, .truststore, .crt, .csr, .p12) are common for the content illustrated here.

Certificate generation script

Generate your certificate files with this script. Remember to edit CA_CN, BROKER_CN, and CLIENT_CN to fit your environment.

Distribute Certificates

On the broker system the broker configuration references files

broker-jks.keystore
broker-jks.truststore

On client systems that use only the TLS Handshake the client needs

ca.crt

On client systems that use TLS Handshake and Client Certificate the client needs

ca.crt
client.crt
client.p12

Configuring the Broker

Referencing the keystore and truststore files

There is no special installation required for the certificate files. They must be readable during broker start up.

Assume that you have run the generation script in the broker’s root folder. The certificates will be in folder .\certs. In the broker configuration file the key stores are loaded by adding these lines to file .\conf\activemq.xml.

<sslContext>
  <sslContext
    keyStore="${activemq.conf}/../certs/broker-jks.keystore" keyStorePassword="password"
    trustStore="${activemq.conf}/../certs/broker-jks.truststore" trustStorePassword="password">
</sslContext>

Creating the AMQPS TLS Transport Connector for TLS Handshake Only

In file .\conf/activemq.xml add the A-MQ TLS/SSL AMQP connector

<transportConnector name="amqps" 
    uri="amqp+ssl://0.0.0.0:5671
    ?maximumConnections=1000
    &wireFormat.maxFrameSize=104857600"/>

Creating the AMQPS TLS Transport Connector for TLS Handshake and Client Certificate

In file .\conf\activemq.xml add a qualifier to the AMQPS transport connector

<transportConnector name="amqps" 
    uri="amqp+ssl://0.0.0.0:5671
    ?maximumConnections=1000
    &wireFormat.maxFrameSize=104857600
    &needClientAuth=true"/>

Restart the broker. The TLS transport connector should be listening on port 5671.

Configuring the Client

Install the CA certificate

Client TLS Handshake is enabled by installing file ca.crt in the system’s Trusted Root Certification Authorities store.

  • From an Administrator command prompt run the MMC Certificate Manager plugin: certmgr.msc
  • Expand the Trusted Root Certification Authorities folder on the left to expose Certificates
  • Right click Certificates and select All Tasks -> Import…
  • Click Next
  • Browse to select file ca.crt
  • Click Next
  • Select Place all certificates in the following store
  • Select Certificate store : Trusted Root Certification Authorities
  • Click Next
  • Click Finish

The certificate issued by reallly-trust-me.org should appear in the Trusted Root Certification Authorities\Certificates list.

Use TLS Handshake Only

The client system is now configured to connect to the broker using TLS Handshake only. The client’s source code must be adjusted to select the TLS transport channel. In HelloWorld_simple.cs the broker URL uses an unsecured channel:

string broker = "amqp://guest:password@10.10.10.254:5672";

The client can connect to the secured channel by changing the scheme to amqps and the port number to 5671

string broker = "amqps://guest:password@10.10.10.254:5671"; 

Use TLS Handshake and Client Certificates

In order to use TLS and client certficates then the certificates with the client’s private keys must be imported into the proper certificate store on the client system.

  • From an Administrator command prompt run the MMC Certificate Manager plugin: certmgr.msc
  • Expand the Personal folder on the left to expose Certificates
  • Right click Certificates and select All Tasks -> Import…
  • Click Next
  • Click Browse
  • In the file type pulldown select Personal Information Exchange (\.pfx;*.p12)*
  • Select file client.p12 and press Open
  • Click Next
  • Type in the password for the private key: password. Accept default import options.
  • Click Next
  • Select Place all certificates in the following store
  • Select Certificate store : Personal
  • Click Next
  • Click Finish

Hello World Example Using Client Certificates

Before a client will return a certificate to the broker, the AMQP.Net Lite library must be told which certificates to use. The client certificate file client.crt is added to the list of certificates to be used during SChannel connection startup.

factory.SSL.ClientCertificates.Add(
    X509Certificate.CreateFromCertFile(certfile));

A complete example is found in HelloWorld-client-certs.cs. This source file and the supporting project files are available in the SDK.

Troubleshooting

My experience getting a setup to work usually involves several permission and connectivity issues.

  • Check that the broker process has permission to listen on AMQPS port 5671.
  • Make sure your broker host system has AMQPS port 5671 open. This may involve both Windows firewall and third party security software.
  • Check that the rest of your infrastructure allows traffic to port 5671, too.

Still can’t connect? Fortunately, both the client and the broker have built-in facilities for troubleshooting SSL/TLS issues.

AMQP.Net Lite

The Lite library uses SChannel to open the secure connection. When any SSL/TLS error happens the caller is only informed of “SSL Handshake failed”. Detailed logging must be enabled through a registry setting. See How to enable Schannel event logging in IIS for detailed instructions and the usual warnings about registry modification. Essentially this registry key has values which are logically ORed together:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL

Value Name: EventLogging
Data Type: REG_DWORD

Value  Description
=====  ===========
0x0    Do not log
0x1    Log error messages
0x2    Log warnings
0x4    Log information and success events

The Lite library has internal event logging but in the case of an SSL/TLS handshake failure Lite does not receive detailed event information from SChannel.

A-MQ

Logging in the Java SSL code may enabled by starting the broker with

-Djavax.net.debug=ssl

The Red Hat JBoss A-MQ broker is fully supported by Red Hat.

Conclusion

With the proper certificates AMQP.Net Lite clients may use TLS Handshake encrypted channels when communicating with Red Hat JBoss A-MQ brokers. Advanced authentication may be performed with TLS Client Certificates.

Happy Messaging!

Advertisements

Hello World!

Red Hat JBoss AMQP.Net Lite Client – Hello World!

AMQP.Net Lite is a lightweight AMQP 1.0 library for .NET.

This article describes how to install and use the library packaged in the Red Hat JBoss A-MQ .NET Lite SDK. The example connects to services in a Red Hat JBoss A-MQ broker.

Download/Install AMQP.Net Lite

AMQP.Net Lite is available from a number of sources. The one you pick depends on your needs.

  • Red Hat JBoss A-MQ AMQP.Net Lite Client SDK
  • NuGet
  • Git

Red Hat JBoss A-MQ AMQP.Net Lite Client SDK

As part of Red Hat JBoss A-MQ 6.2 Red Hat supplies an SDK for AMQP.Net Lite. The SDK has precompiled binary library files for use on a Windows desktop system running Visual Studio 2012 or Visual Studio 2013, AMQP.Net Lite API documentation, and a set of example programs. This is an ideal environment for getting started with .NET and AMQP.

Download

Download the SDK from Red Hat JBoss A-MQ – Downloads. On the download page choose .NET Lite SDK. This will result in downloading a single file: amqpnetlite-sdk-1.1.0.2.zip.

Install

Installing AMQP.Net Lite consists of unzipping the distribution file. This may be done using Windows Explorer or by a third party utility such as 7-Zip.

A typical unzipped installation will look like this:

W:\1.1.0.2> dir
 Directory of W:\1.1.0.2

06/18/2015  03:58 PM    <DIR>          amqpnetlite
06/03/2015  01:00 PM         1,020,150 amqpnetlite-sdk-1.1.0.2.zip

Inside the amqpnetlite folder you will find the Visual Studio 2012 and 2013 solution files and the other files that make up the kit.

W:\1.1.0.2> dir amqpnetlite
 Directory of W:\1.1.0.2\amqpnetlite

05/27/2015  01:20 PM            12,757 amqp-vs2012.sln
05/27/2015  01:20 PM            12,837 amqp.sln
06/11/2015  04:53 PM    <DIR>          bin
06/11/2015  04:53 PM    <DIR>          doc
06/11/2015  04:53 PM    <DIR>          Examples
05/27/2015  01:20 PM             3,763 README-amqpnetlite.txt

NuGet

AMQP.Net Lite is available through the Package Manager Console integrated with Visual Studio. Users will find this method of installation very convenient but the process does not install examples nor supporting documentation. I’d recommend the NuGet package for experienced users who just need the runtime library bits and don’t need help getting started.

To install using NuGet issue the following command in the Package Manager Console

Install-Package AMQPNetLite

Git from upstream

The upstream project is open source. Visit the home page.

The source code is available at

git clone https://git01.codeplex.com/amqpnetlite

The upstream project is open source on github. Visit the home page.

The source code is available at

git clone https://github.com/Azure/amqpnetlite.git

The project supports a variety of .NET Frameworks:

  • .NET 3.5
  • .NET 4.0
  • .NET Core
  • Windows Phone
  • Windows RT
  • Windows Store
  • Compact Framework
  • Micro Framework

When you try to build a fresh source from upstream is it unlikely that your system will have all of the .NET packages required to support everything AMQP.Net Lite offers. While loading the solution file Visual Studio emits a series of errors as it removes projects that can not compile on your system now. Not to worry, though, as projects reappear when the underlying support for them is installed.

The upstream project also includes dozens of self tests that illustrate how things are supposed to work. These are a great reference.

AMQP 1.0

AMQP.Net Lite uses only AMQP version 1.0 and interoperates with a system such as the JBoss A-MQ broker that also uses AMQP 1.0.

A brief introduction to the AMQP 1.0 messaging protocol is in order. The AMQP.Net Lite programming API closely models the structures defined by AMQP 1.0. If one is familiar with AMQP 1.0 then one understands most of the relationships in the messaging aspects of AMQP.Net Lite.

Connection

A Connection is a full-duplex, reliably ordered sequence of frames, or units of work, carried over the communication wire.

  • AMQP requires guarantees similar to what TCP or SCTP provide for byte streams.
  • A single AMQP Connection is established for each underlying transport (TCP) connection.

Session

Within a Connection a Session is a grouping of some number of independent unidirectional channels.

  • Sessions provide sequencing and flow control at the frame transfer level.
  • A Connection may contain any number of Sessions.

Link

Within a Session a Link is a unidirectional route between a source and a target, one at each end of the Connection.

  • Links are the paths over which messages are transferred.
  • Links are unidirectional.
  • Pairs of links are bound to create full duplex communication channels between endpoints.
  • A single Session may be associated with any number of Links.
  • Links provide flow control at the message transfer level.

From a client’s point of view the source and target are names of the terminus objects in the connection peer’s namespace. The SenderLink target name and ReceiverLink source name are the names of queues or topics in the broker.

The example code sends and receives messages to and from a queue named my_queue. The JBoss A-MQ broker may autocreate this queue if it does not already exist. Note that the JBoss A-MQ broker may be configured with a security setting that restricts queue autocreation. With that restriction then my_queue must be created administratively before the example will work.

Messaging

AMQP 1.0 Messaging has a rich and well structured design to suit virtually any message use case. In the example only a simple message consisting of a text string is used. Real world applications are typically much more demanding and will use more advanced messaging properties and capabilities.

Hello World Example

Let’s get going with HelloWorld. This example is file HelloWorld-simple.cs in the SDK.

Source Code

 1 using System;
 2 using Amqp;
 3 
 4 namespace HelloWorld
 5 {
 6   class HelloWorld
 7   {
 8     static void Main(string[] args)
 9     {
10       string brokerUrl = "amqp://localhost:5672";
11       string address   = "my_queue";
12 
13       Address    brokerAddr = new Address(brokerUrl);
14       Connection connection = new Connection(brokerAddr);
15       Session    session    = new Session(connection);
16 
17       SenderLink   sender   = new   SenderLink(session, "sender",   address);
18       ReceiverLink receiver = new ReceiverLink(session, "receiver", address);
19 
20       Message helloOut = new Message("Hello World!");
21       sender.Send(helloOut);
22 
23       Message helloIn = receiver.Receive();
24       receiver.Accept(helloIn);
25 
26       Console.WriteLine(helloIn.Body.ToString());
27 
28       receiver.Close();
29       sender.Close();
30       session.Close();
31       connection.Close();
32     }
33   }
34 }

The source is also available here

Code Notes

  • Line 2 The using directive enables unqualified use of the AMQP.Net Lite objects in the AMQP namespace.
  • Line 10 contains the URL specifying the network address of the A-MQ broker to which this connection is directed. The details of the URL format are explained below.
  • Line 11 has the name of the resource in the broker to which and from which links will be created.
  • Line 13 creates an Address object that holds the parsed URL.
  • Line 14 opens the connection:
    • A TCP connection is opened
    • AMQP Version information is exchanged and accepted
    • AMQP Open performatives are exchanged to create an AMQP Connection and to define Connection-level capabilities and properties.
  • Line 15 creates a session:
    • AMQP Begin performatives are exchanged to create an AMQP Session and to define Session-level values and limits.
  • Lines 17 and 18 create links to the resource in the broker.
    • AMQP Attach performatives are exchanged to create AMQP Links and to define Link-level names, values, and properties.
    • The broker issues AMQP Flow performatives to define credits that allow the client to send messages.
  • Line 20 creates a message holding a simple text string
  • Line 21 sends the message on the sender link
    • The client sends an AMQP Transfer performative containing the original message.
    • The broker sends an AMQP Disposition performative acknowledging and assuming ownership of the message. The broker puts the message into the my_queue queue.
  • Line 23 receives a message on the receiver link.
    • The broker sends an AMQP Transfer performative containing the reply message.
    • Note: The receiver will time out and throw an exception if no message is received
    • The client issues an AMQP Flow performative to replenish the broker’s credits for sending to the reply link.
  • Line 24 The receiver accepts the message.
    • The client sends an AMQP Disposition performative acknowledging and assuming ownership of the message. The broker removes the message from the my_queue queue.
    • Note: if the client did not accept the message then the message would remain on the broker queue.
  • Line 26 prints “Hello World!”
  • Lines 28 and 29 close the receiver and sender links
    • AMQP Detach performatives are exchanged to dispose of the links.
  • Line 30 closes the session
    • AMQP End performatives are exchanged to dispose of the session.
  • Line 31 closes the connection and releases internal resources related to it
    • The client and broker exchange AMQP Close performatives to dispose of the connection.
    • The TCP connection between the client and broker is torn down.

AMQP.Net Lite Connection Specification

AMQP.Net Lite accepts a formatted URL to specify the peer address.

amqp[s] :// [user:[password]@] domain[:port] [/path]
  1. The scheme
    • amqp specifies an unencrytped connection
    • amqps specifies an encrypted connection.
  2. user and password are optional credentials. When specified AMQP.Net Lite uses them during the SASL negotiation phase of AMQP connection establishment.
  3. domain is the domain name or literal IP numeric address of the target peer system.
  4. port number, given in decimal, is optional. If omitted, the default for the scheme is used:
    • 5672 for amqp
    • 5671 for amqps
  5. path is part of the parsed Address class but is not used as part of the connection.

Conclusion

Using AMQP.Net Lite it is easy to get going in the AMQP messaging space. With AMQP you can operate with Red Hat A-MQ brokers and with services in the Azure cloud with equal ease.

In a future blog post I want to share how to secure your AMQP communications with TLS/SLL.

Happy Messaging!