Home > On-disk encryption prototype for OpenStack Swift

On-disk encryption prototype for OpenStack Swift

Oleg Gelbukh - January 22, 2013 -

A few months ago, I described the design of on-disk per-user encryption of objects in Swift, so I’m excited to announce a first working prototype of this feature. It has very basic functionality at the moment, but most of its components are pluggable and can be enhanced or replaced with more advanced versions. We already have a backlog of improvements to work on, and hope to get even more ideas from community discussions.

The prototype’s code—based on the 1.7.5 version of Swift—is published at our Github account.

OpenStack Swift code modifications overview

We’ve modified an ObjectController class of the object server application in two parts: disk read and write procedures. We also added several components. The changed classes are summarized in the following diagram:

The code for the new components is organized as follows:

  • swift/common/key_manager
    The directory containing the code for key management.
  • swift/common/key_manager/drivers/
    The directory containing the code of the key storage drivers.
  • swift/common/middleware/key_manager.py
    The module containing the filter for the proxy-server application that communicates with the key store back-end.
  • swift/obj/encryptor.py 
    The module containing the object encryption functions.
Most of the modifications were made to the swift/obj/server.py module, where we had to insert encrypt/decrypt calls into the object reading and writing functions. We also added methods that communicate with the key store using key_manager back-end drivers. Finally, we had to modify the way the server calculates and stores the object Etag.

Encrypting the OpenStack Swift object server

To get the object server with encryption support up and running, you will need to make modifications to some configuration files. First is the /etc/swift/object-server.conf file. A sample configuration for an encryption-capable object server is included with the code. The most important parameters set in this file with regard to encryption are:

  • crypto_protocol
    This parameter defines which encryption protocol/algorithm will be used. Currently, prototype implementation supports only the AES-128-CBC protocol, which corresponds to the aes_128_cbc value of the parameter.
  • crypto_keystore_driver
    This parameter defines the back-end used to store and retrieve keys. Prototype implementation only supports the SQLAlchemy back-end, which stores keys in SQL DB, so set this to sql.
  • crypto_driver
    This parameter defines which encryption driver will be used. CryptoDriver is the default value in the prototype.
  • crypto_keystore_sql_url
    This parameter contains the SQL connection string used by the SQL key store driver to connect to the DB. This parameter is specific for the sql key store back-end.

Key management in the OpenStack Swift proxy server

In the original design, the only operation performed by the proxy server key management filter was retrieval of a key ID to pass with the object upon a write or update operation. However, in our prototype implementation we’ve made generation of the key string itself a part of the key-manager middleware. Obviously, this is a less-than-optimal solution from the security point of view, since in any production environment, generation of key strings must be performed on demand by the key server.

For prototype implementation, only SQL is supported as key storage on the back-end. The SQL driver in the key-manager middleware ensures key ID retrieval and generation in case no active key is found in the database. Configuration parameters for the proxy server closely resemble the ones for the object server:

  • crypto_keystore_driver 
    This parameter defines the back-end used to store and retrieve keys. Prototype implementation only supports the SQLAlchemy back-end, which stores keys in SQL DB, so set this to sql.
  • crypto_keystore_sql_url 
    This parameter contains the SQL connection string used by the SQL key store driver to connect to the database. This parameter is specific to the sql key store back-end.

Future directions for on-disk encryption for OpenStack Swift

Lots of work lies ahead to turn this prototype into a production-ready application, and we hope to get yet more insights from the community. Let me elaborate on some items from our backlog to give you an idea of where we are heading.

Object file decorators

From the mailing lists and design summit discussions we know there are many things to do with object files in Swift beyond encryption, such as compression and deduplication. These operations could be thought of as “filters” or “handlers” applied to the object data (actually, a chunk of data transferred from the client through the proxy server) one after another in a sequence. This sequence must be stored with the file and repeat when the client wants to read the file, but in the reversed order.

Key server integration

The most important part of the encryption feature is, naturally, key management, so integration with key management systems is our primary focus in future development. We’re looking forward to progress in Keystone’s key management feature (it’s covered by the access keys auth blueprint). However, it should be possible to utilize a key management system with open API support, such as KMIP. This also corresponds to the approach to encryption of the Cinder volumes proposed in this specification. The most important question now is—where does key management belong? We see the following three options:

  1. The key manager belong in Keystone. In this case, the key_manager middleware above will move to Keystone and become a service of its own, just like Identity, Token, and Catalog. Swift will get the key from the Keystone token.
  2. The key manager is in a separate library, like part of an Oslo project. This is even more reasonable since encryption-related proposals exist for Nova and Cinder projects.
  3. The key manager remains part of Swift. In this case, Swift will support encryption even in stand-alone mode without integration with external services. However, reuse of this code will be an issue.
Once this decision is made, we can decide which API needs to be extended, which will also define the management model of this encryption service for OpenStack.