Jump to: navigation, search

Difference between revisions of "VolumeEncryption"

m (System Design: remove unnecessary exclamation marks)
(remove 'Test Setup Guide' because it is out-of-date)
Line 50: Line 50:
  
 
Performance testing will be executed later.
 
Performance testing will be executed later.
 
== Test Setup Guide ==
 
 
The purpose of this section is to provides steps that allow developers to get an environment where they can test out the volume encryption feature.  It also provides guidance on how to execute the feature and manually verify that it is working.
 
 
1. Get a working DevStack environment up and running.
 
 
2. Update the code in nova, horizon, and python-cinderclient with the changesets associated with the volume encryption feature.  ''Note:'' as of 2/6/2013 the python-cinderclient changes have been merged into master, so nothing further should be required for that repository.
 
 
3. Create and launch a new instance.
 
 
4. Create two new Cinder volumes, one encrypted and one unencrypted.  You can create them either using the Horizon interface or from the command-line.
 
 
* '''a)''' From the Horizon interface, click the "Create Volume" button.  At the bottom of this form will be a dropdown menu labeled "Encryption."  For the unencrypted volume, leave this field blank.  For the encrypted volume, choose the "dmcrypt LUKS" option.  After creation, you can verify the encryption setting in the detailed volume view page, under the "Metadata" section.
 
* '''b)''' From the command-line, the unencrypted volume can be created as usual, e.g. "<code><nowiki>cinder create 1 --display-name test_unencrypted</nowiki></code>".  For the encrypted volume, add an encryption field to the metadata as follows: "<code><nowiki>cinder create 1 --display-name test_encrypted --metadata encryption=LUKS</nowiki></code>".  Note that the metadata must be the last argument in the command.
 
 
5. Attach both volumes to the new instance.  For simplicity, we assume that the unencrypted volume is attached as <code><nowiki>/dev/vdb</nowiki></code> and the encrypted volume is attached as <code><nowiki>/dev/vdc</nowiki></code> but the actual mount points may differ. Use <code><nowiki>dmesg | tail</nowiki></code> or <code><nowiki>fdisk -l</nowiki></code> ''inside the instance'' after attaching the volume to determine its actual mount point. (You should verify the mount point before attaching another volume.)
 
 
6. Inside the instance, escalate to root and then write some strings to the two attached volumes.  We will validate that the volumes are un/encrypted as necessary by searching for these strings in files backing the volumes.
 
 
  <code><nowiki>sudo -i</nowiki></code>
 
 
  <code><nowiki>echo "Hello, world (unencrypted /dev/vdb)" >> /dev/vdb</nowiki></code>
 
 
  <code><nowiki>echo "Hello, world (encrypted /dev/vdc)" >> /dev/vdc</nowiki></code>
 
 
  <code><nowiki># force I/O cache synchronization</nowiki></code>
 
 
  <code><nowiki>sync && sleep 2</nowiki></code>
 
 
  <code><nowiki>sync && sleep 2</nowiki></code>
 
 
  <code><nowiki>exit</nowiki></code>
 
 
7. Back in the compute host, synchronize the I/O to flush any cached data.
 
 
  <code><nowiki>sync && sleep 2</nowiki></code>
 
 
  <code><nowiki>sync && sleep 2</nowiki></code>
 
 
  Search for all "Hello" strings in the backing file (it will take a little while).  You will only get back the unencrypted version.
 
 
  <code><nowiki>sudo strings /dev/stack-volumes/volume-* | grep "Hello"</nowiki></code>
 
 
  Expected output: <code><nowiki>"Hello, world (unencrypted /dev/vdb)"</nowiki></code>
 
 
  Examining the iSCSI device that corresponds to the encrypted volume (e.g., <code><nowiki>sudo less -f /dev/sdc</nowiki></code>, substituting the appropriate device ''on the compute host'') will reveal the LUKS header and encrypted data whereas the unencrypted iSCSI device will display the text written to the unencrypted volume.
 
  
 
== Scope ==
 
== Scope ==

Revision as of 17:24, 8 August 2014

  • Launchpad Entry: Grizzly
  • Created: 29 Nov 2012
  • Updated: 5 Feb 2013
  • Contributors: Bruce Benjamin, Joel Coffman, Laura Glendenning, Nate Reller

Introduction

OpenStack currently provides no support to encrypt block storage automatically. This makes the platforms hosting volumes for VMs high value targets because an attacker can break into a volume-hosting platform and read the data for many different VMs. Another issue is that the physical storage medium could be stolen, remounted, and accessed from a different machine. This blueprint addresses both of these vulnerabilities.

The aim of this blueprint is to provide encryption of the VM's data before it is written to disk. This will allow the privacy of data to be maintained while residing on the storage device. The idea is similar to how self-encrypting drives work. This new feature presents a normal block storage device to the VM but will encrypt the bytes in the virtualization host before writing them to the disk. Note that the necessary design changes are only made in the virtualization host and the key management entity. The block server operates exactly as it does when reading and writing unencrypted blocks. No modifications to the storage device are needed.

Existing tools allow a user to encrypt data inside the VM, but these solutions require manual configuration. Transparently encrypting the data removes the potential risks posed by relying on end-users' manual configuration of the encryption. Cinder volumes currently provides little security, and iSCSI [1] does not inherently provide data-in-transit protection, although external networking security can be added. To address these issues, the encryption provided by this new feature will occur before the iSCSI commands are invoked. The data that goes over the wire to the remote Cinder server is encrypted, and it stays encrypted on the disk.

System Architecture

The diagram below illustrates the system architecture for the block encryption capability. The process for setting up the encryption begins when a user selects an encrypted volume on the dashboard. The next step of the process is a call to Nova's attach_volume command. Nova will map the device as a block device in the virtualization host. This mapping is the same as in the previous OpenStack release.

After the volume is mounted in the virtualization host, Nova will setup the encryption using what we call a Volume Encryptor. The Volume Encryptor is responsible for setting up the encryption for a block device. The reference implementation will be a Dm-Crypt Volume Encryptor, but an abstraction layer allows other choices.

The Volume Encryptor will be invoked to encrypt the block device, and to do this it must have the appropriate key to encrypt the drive. Volume Encryptor gets this by a call to a Key Manager, which is responsible for retrieving appropriate keys. Our eventual goal will be to use a key manager server that implements the OASIS Key Management Interoperability Protocol (KMIP) [2], which defines an industry-wide standard for key management. However, our initial reference implementation uses the Nova database to store the keys.

The Key Manager will return the key to the Volume Encryptor that will then set up the block device for encryption. When dm-crypt [3] is used as the Volume Encryptor, this will entail setting up a loop back device on the mounted volume and setting up dm-crypt using the encryption key for the loop back device. The Volume Encryptor will then return the device name to Nova, and Nova will use that device to map into the VM. This last step is the same as in previous releases.

Block Encryption Blueprint v0.82.jpg

An extension of this architecture is planned which addresses another storage target. It will encrypt the disk image called “ephemeral storage,” which contains the operating system and other additional local storage for the VM.

System Design

The Nova architecture only requires a slight modification to provide support for the block encryption feature. The new main interface will be VolumeEncryptor, which is responsible for encrypting block devices. Nova has been modified to directly call this interface. This feature is an option in Nova, so if encryption is not desired, then Nova will simply operate normally. The UML class diagram shows this new interface.

VolumeEncryptor interacts with a KeyManager, which returns keys to VolumeEncryptor.

KeyManager is an interface that allows different types of key managers to be used. The initial interface only defines a method for retrieving keys (get_key), but future revisions will contain more methods for creating, updating, and deleting keys (via KMIPKeyManager, or equiv.). Since this present version doesn’t include a method for creating keys, if KeyManager doesn’t have a key available when this method is called, the current implementation of DBKeyManager will create a random key. This feature is provided for ease of testing, and will not likely remain in the production implementation.

NovaAttach 0.82.jpg

There are some additional unknowns about how the encrypted device will interact with other OpenStack features. For example, exporting/snapshotting volumes and live migration will need to be investigated.

The configuration file key manager in this design is included only as a reference implementation and should only be used for testing purposes. Similarly, the database key manager should not be used in a production environment. A planned feature for the future is to expand the pull-down menu on Horizon to support several encryption mode choices that can be used for volume encryption.

Schedule

This first release, aimed at Grizzly, is essentially a proof of concept of the encryption capabilities. It has a simple key management capability and is intended for testing the proof-of-concept implementation. This initial version will rely on OpenStack’s existing authentication mechanisms, API calls, and database access, which may limit the security.

A later version is planned that will be based on some basic key management capabilities that will be compatible with the Key Management Interoperability Protocol (KMIP). The plan is to offload the complexity of implementing key management by using a KMIP server. This will talk with the virtualization host to provide a secure link that will deliver the proper keys when needed. The KMIP server would also need to rely on Keystone to provide the authorization credentials, validating that the correct user is accessing the block storage device, and validating that the correct key is being accessed. When PKI is fully implemented in Keystone, this will enhance the security of this key management capability.

Testing

OpenStack unit testing of this encryption component has been successfully completed, which includes successfully running Nova unit tests, Horizon unit tests, and 'Python-cinderclient' unit tests. New unit tests have been developed and used for testing the new capabilities, and these also ran successfully. These addressed attaching/detaching encrypted volumes, the Horizon GUI widgets, the database key manager, the Nova database API, and the python Cinder client. Two encryption modes have been tested: aes-cbc-essiv:sha256 and aes-xts-plain64 [4].

All unit and functional tests have been run against APL’s code merged in with the latest code from the OpenStack master branch as of 01/29/2013. OpenStack has new code pushed to it on a daily or even hourly basis which may invalidate these test results in the future.

Setup instructions have been developed, and will be made available. These are primarily to facilitate the setup of a development environment that supports the block encryption feature. This is to try it out and check out the features that have been implemented as a demonstration/ integration test. The code works just the same in a non-development environment.

Performance testing will be executed later.

Scope

Note that most changes supporting this specification are in the libvirt driver of Nova. If a different virtualization driver is being used, the capabilities in this specification will not work. Note that modifying other drivers might be relatively easy to do to allow this capability to be used. In the libvirt driver, only two additional lines of code in the attach statement and one additional line of code in the detach statement were modified.

References

[1]http://www.ietf.org/rfc/rfc3720.txt (Internet Small Computer Systems Interface - iSCSI)

[2]https://www.oasis-open.org/committees/kmip/ an specifications http://docs.oasis-open.org/kmip/spec/v1.0/cs01/kmip-spec-1.0-cs-01.pdf

[3]http://www.saout.de/misc/dm-crypt/

[4]http://csrc.nist.gov/publications/nistpubs/800-38E/nist-sp-800-38E.pdf (NIST SP800-38E)