Securing Azure Service Bus and Azure Queuing Messages in .NET

Securing data at rest is often the center of concern for cloud adoption in the enterprise. Secure communication protocols like SSL partially address the issues. However, SSL falls short once data is decrypted and persisted to a data store. While .NET includes encryption classes there are no instructions for bringing encryption to bear on, for example, Azure Messaging services like Service Bus and Azure Queuing.

One simple path is to encrypt individual fields in the message. As the number of messages increases, however, rewriting code to encrypt individual fields becomes impractical. Another approach is to encrypt a message’s payload. A Pipeline and Envelope architecture handling the encryption is a suitable implementation approach that leads to more reusable code across all Azure Messaging infrastructures. The Envelope separates the message format from the platform and the Pipeline separates encryption from class Serialization. The remaining paragraphs explain how to achieve this.

Designing a Secure Envelope

An Envelope is a message within a message. In this sample; the outer part is an encrypted byte array and the inner part contains the data. The following code depicts the encrypted data class and Envelope class designs.

ByteDataContract will contain the encrypted version of a more specialized message class. ByteDataContract will, in turn, will become the Payload property on the EnvelopeMessage. EnvelopeMessage will then be handled by whatever Azure Messaging Infrastructure a developer decides to employ.

A Pipeline Architecture that operates on the MessageEnvelope class works on the MessageEnvelope layers. First decrypting/encrypting the message and then unpacking/packing the specialized message class. All layers utilize a set of Serialization and Deserialization utility methods. Utility Serialization and Deserialization methods are captured in the following code.

The internalTypes parameter is required; because a class may be composed of other internal classes. Serialization only works on primitives unless the serializer is directed to use other classes. The first type in the internalTypes list is assumed to be the class being Deserialized. A complete review of the Serialization involved in the process is beyond the scope of this article; however you’ll find a good review in the resources at the end of the article.

When a developer is working with WCF and Serialization; for security reasons, WCF Messages have buffer limitations. There are default settings on the message and on the message contents. For example: the Payload property could easily exceed the default message size for message property contents. Developers may need to adjust code like in the following sample if message sizes exceed these defaults.

Pipeline Architecture

Pipelines are a good way to implement processes with stages where each stage gets input from the prior state and generates input for the next stage. The underlying infrastructure is only aware of the MessageEnvelope class. Core Pipeline operations are handled in extension methods on the MessageEnvelope. Separating the operations into Extension Methods separates the Message contract from the methods operating on the contract. This ensures that code only needing the contract will only see the contract and nothing more. So, for example, the Messaging Infrastructure code is only aware of the MessageEnvelope class and not aware of the Extensions that manipulate the class. Extension methods on the MessageEnvelope follow.

TransformationDirection directs the code to either Encrypt, turning the class into bytes, or Decrypt, turning the bytes into a class. The implementation assumes another class has either serialized the string to XML data or will deserialize the string from XML data to a class. Notice how the transformation operates on or creates a ByteDataContract.

Encrypt and Decrypt implementation details first require an Encryption primer.

.NET Encryption Primer

Cryptography has been a part of .NET since .NET was first released. What follows is a short .NET cryptography introduction focusing on the classes used in the sample solution. The Encrypt, Decrypt, and related methods used in the previous sample code follow.

Developers familiar with the .NET Stream class and its variants will notice similarities here. Streams are often chained together in a Pipeline where one Stream feeds another Stream. CryptoStream utilizes the same arrangement. A Byte array is managed by a MemoryStream. The MemoryStream handles reading and writing Bytes fed to or pulled from the CryptoStream class. CopyFormToStream method mediates between the two Streams.

The CryptoStream requires two values the Key and the Initialization Vector. The values “prime” the underlying algorithm and ensure, for example, that identical text blocks are not identical after each block is encrypted. Because the sample works with XML data the bytes are assumed to be UTF8 encoded. A more complete introduction to encryption can be found in resources at the end of the article.

All components discussed so far are packaged together in the Pipeline Factory.

Pulling it Together in a Pipeline Factory

Everything is packaged into a Pipeline and Pipeline Factory interface implementation. The interfaces are demonstrated in the following code.

The selected Messaging Infrastructure Deserializes the incoming message into a MessageEnvelope class.

An IMessageEnvelopePiplineFactory class is created and the MessageEnvelope is passed to the Create method.

GetResponse is invoked and the response is sent back through the Messaging Infrastructure.

MessageEnvelope Response contents can be as simple or as complicated as a developer makes them. For example, a developer may find that the response should also be encrypted. The example can be modified so the Response is an integer indicating whether the message was successfully consumed.

Conclusion

Securing data at rest is often the center of concern when an enterprise is considering adopting Azure Service Bus or Azure Queuing. Encryption is often the answer to addressing data at rest. Taking a Pipeline and Envelope Pattern approach allows reusability across both infrastructures and decouples the messaging infrastructure from the message handling.

Top White Papers and Webcasts

The 2014 State of DevOps Report — based on a survey of 9,200+ people in IT operations, software development and technology management roles in 110 countries — reveals:
Companies with high-performing IT organizations are twice as likely to exceed their profitability, market share and productivity goals.
IT performance improves with DevOps maturity, and strongly correlates with well-known DevOps practices.
Job satisfaction is the No. 1 predictor of performance against organizational …