Securing the Orbital Bus

After getting familiar with the Orbital Bus Architecture, and how it solves the traditional Enterprise Service Bus (ESB) shortcomings, it was time for our development team to create a secure solution around the components and communication channels of our distributed solution.

The challenge:

The Orbital Bus makes exchanging information possible between various parties. To this effect, Orbital Bus has three components involving communication:

  • RabbitMQ is the message broker across its various components.
  • Orbital Bus service registration and discovery is built on top of Consul.
  • The receiver calls out to the consumer with a REST Adapter that is built using the RestSharp Client.

These communication components support TLS-Encryption and HTTP authentication. We also want to support additional authentication and message protection mechanisms in the future. In order to implement these solutions Orbital Bus needs to provide a way to save credentials, X.509 certificates, and other forms of tokens. To summarize, the challenges we encountered in developing Orbital Bus were:

  1. Provide a secure vault to store various types of credentials, certificates, and tokens.
  2. Make the security features optional so it could be implemented only when needed.

The Solution

While working on the Orbital Bus it became obvious that a secure vault was needed to save sensitive information such as credentials, tokens, and certificates. Inspired by Java Keystore, Foci Solutions designed and developed a platform-agonstic C# Keystore solution that could work on Windows or Linux. Foci’s Keystore is available as a Nuget Package, and it also comes with a Keystore Manager CLI Tool to perform CRUD operations on the Keystore directly. Please visit the Keystore’s How to Guide for more details on how to use the Keystore and its manager.

The Keystore addresses the first security challenge. Your system requires a secure RabbitMQ client? Not a problem. You can have the credentials saved in the Keystore and use them whenever needed. Your Orbital Bus implementation requires using a certificate for service discovery through Consul? The Keystore can encrypt and save the certificate to be used whenever needed. If you look closely at the Orbital Bus API Documentation, you will notice that there is a KeystoreService and a KeystoreRepository that makes the integration with Foci’s Keystore Seamless. The Keystore’s CRUD repository makes it available to any part of the Orbital Bus components via the KeystoreService.

Now that the first security challenge has been addressed through the Keystore integration, let’s move on to the second challenge: How to make security available but optional? The first thought that comes to mind is to modify Orbital Bus code. After further consideration, it becomes very clear that code modification based on security requirements is an expensive approach that necessitates code change based on the implementation requirements. We decided to integrate the security options into our configuration service to allow changes on the fly. This way security options throughout the Orbital Bus solution can be toggled with minimal effort. You want to secure your dispatcher’s communication to the RabbitMQ client? Then all you need is to turn on a security flag and provide the RabbitMQ credentials. Just let Orbital Bus’ configuration service take care of the rest.

How to Use the Keystore

Foci’s Keystore can accommodate various entry types like certificates, key pairs, username/password pairs, and tokens. Each entry in the Keystore has a unique Alias to keep them organized. The Keystore can be configured to encrypt/decrypt its content using either the Current User or Local Machine data protection scopes. The Keystore is fully integrated for use by any component of the Orbital Bus like the dispatcher or receiver. You will only need to initialize the Keystore with the Keystore Manager Tool and add any credentials or certificates your solution requires. For example: Your implementation requires a secure communication between the dispatcher and RabbitMQ using a username and password? All you need to do is create the Keystore using the Keystore Manager Tool and add a new entry for the required credentials with a unique Alias. What’s next? How to retrieve the stored entries? What’s this Alias for? How to use it? All this will be explained in the next section.

How to Configure Security

Orbital Bus approach favours configuration over customization for obvious reasons. In this section we will walk through how you can configure RabbitMQ, Consul, and the REST Adapter to be secure. The Orbital Bus has a KeystoreService that sits in the Root of the solution. The KeystoreService is injected into the ConfigurationService class. This ConfigurationService is a powerful and flexible tool. It can be injected into any component and it imports any set of configurations that are stored in a specified JSON file mapped into their own configuration model. For example: The ConfigurationService is injected into the DispatcherRegistration in order to configure the dispatcher with settings including the RabbitMQ options for addresses, credentials, and certificates.

RabbitMQ Configuration

Both the dispatcher and receiver establish RabbitMQ buses that can be configured as secure. The following is a JSON configuration file for a dispatcher that has the RabbitMQ security enabled:

{
  "DispatcherConfiguration":
  {
    "BusHostIp": "localhost",
    "BusHostPort": 5672,
    "ContractLibraryPrefix": "",
    "ConsulConfiguration": {
      "HostIp": "localhost",
      "HostPort": 8500
    }
  },
  "BaseConfiguration": {
    "RabbitMQConfiguration": {
      "BusHostIp": "localhost",
      "BusHostPort": 5672,
      "SslEnabled": "true",
      "Alias": "rabbitCredentials"
    }
  }
}

You might notice that the property SslEnabled is set to true, and there is an Alias property with the value “rabbitCredentials”. This simple configuration allows Orbital Bus to enable secure communications with the RabbitMQ server. The Alias here is the unique name we assigned to the credentials entry saved in the Keystore using the Keystore Manger Tool. Securing RabbitMQ in Orbital Bus is as simple as this. Save your credentials in the Keystore, and make sure you edit your configuration to point to the stored credentials Alias.

Consul Configuration

For Orbital Bus we implemented Consul security connections with certificate authentication. Any REST client or request created to communicate to Consul should have an appended certificate for authentication. In return, Consul will return its certificate to authenticate to the client. The following is a JSON configuration file for a dispatcher that has the Consul security enabled:

{
  "DispatcherConfiguration":   
  {
    "BusHostIp": "localhost",
    "BusHostPort": 5672,
    "ContractLibraryPrefix": "",
    "ConsulConfiguration": {
      "HostIp": "localhost",
      "HostPort": 8500
    }
  },
  "BaseConfiguration": {
    "ConsulConfiguration": {
      "HostIp": "localhost",
      "HostPort": 8500,
      "SslEnabledConsul": "true",
      "Alias": "consulcert"
    }
  }
}

Here a similar approach to the RabbitMQ implementation is used. An entry with the Alias “consulcert” is referenced to retrieve the stored certificate that would be injected into the ConsulService when its initialized. The service then appends that certificate to requests.

REST API

The REST Adapter follows a similar approach to enable and configure secure HTTP communications. The RestAdapterConfiguration class has a SecureConsumer flag to indicate if the security is enabled and a ConsumerAlias contains the unique Alias name for the credentials in the Keystore.

Security is always a pressing concern and the best solution is not often easily apparent. In building the Keystore, we sought to make a tool that could be used easily and repeatedly, while at the same time making it an integral part of the Orbital Bus. We recommend checking out the How To Guide and trying it out yourself.