diff options
Diffstat (limited to 'doc/rbd/rbd-encryption.rst')
-rw-r--r-- | doc/rbd/rbd-encryption.rst | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/doc/rbd/rbd-encryption.rst b/doc/rbd/rbd-encryption.rst new file mode 100644 index 000000000..3f37a8b1c --- /dev/null +++ b/doc/rbd/rbd-encryption.rst @@ -0,0 +1,246 @@ +====================== + Image Encryption +====================== + +.. index:: Ceph Block Device; encryption + +Starting with the Pacific release, image-level encryption can be handled +internally by RBD clients. This means you can set a secret key that will be +used to encrypt a specific RBD image. This page describes the scope of the +RBD encryption feature. + +.. note:: + The ``krbd`` kernel module does not support encryption at this time. + +.. note:: + External tools (e.g. dm-crypt, QEMU) can be used as well to encrypt + an RBD image, and the feature set and limitation set for that use may be + different than described here. + +Encryption Format +================= + +By default, RBD images are not encrypted. To encrypt an RBD image, it needs to +be formatted to one of the supported encryption formats. The format operation +persists encryption metadata to the image. The encryption metadata usually +includes information such as the encryption format and version, cipher +algorithm and mode specification, as well as information used to secure the +encryption key. The encryption key itself is protected by a user-kept secret +(usually a passphrase), which is never persisted. The basic encryption format +operation will require specifying the encryption format and a secret. + +Some of the encryption metadata may be stored as part of the image data, +typically an encryption header will be written to the beginning of the raw +image data. This means that the effective image size of the encrypted image may +be lower than the raw image size. See the `Supported Formats`_ section for more +details. + +.. note:: + Unless explicitly (re-)formatted, clones of an encrypted image are + inherently encrypted using the same format and secret. + +.. note:: + Clones of an encrypted image are always encrypted. + Re-formatting to plaintext is not supported. + +.. note:: + Any data written to the image prior to its format may become unreadable, + though it may still occupy storage resources. + +.. note:: + Images with the `journal feature`_ enabled cannot be formatted and encrypted + by RBD clients. + +Encryption Load +================= + +Formatting an image is a necessary pre-requisite for enabling encryption. +However, formatted images will still be treated as raw unencrypted images by +all of the RBD APIs. In particular, an encrypted RBD image can be opened +by the same APIs as any other image, and raw unencrypted data can be +read / written. Such raw IOs may risk the integrity of the encryption format, +for example by overriding encryption metadata located at the beginning of the +image. + +In order to safely perform encrypted IO on the formatted image, an additional +*encryption load* operation should be applied after opening the image. The +encryption load operation requires supplying the encryption format and a secret +for unlocking the encryption key for the image itself and each of its explicitly +formatted ancestor images. Following a successful encryption load operation, +all IOs for the opened image will be encrypted / decrypted. For a cloned +image, this includes IOs for ancestor images as well. The encryption keys will +be stored in-memory by the RBD client until the image is closed. + +.. note:: + Once encryption has been loaded, no other encryption load / format + operations can be applied to the context of the opened image. + +.. note:: + Once encryption has been loaded, API calls for retrieving the image size + and the parent overlap using the opened image context will return the + effective image size and the effective parent overlap respectively. + +.. note:: + Once encryption has been loaded, API calls for resizing the image will + interpret the specified target size as effective image size. + +.. note:: + If a clone of an encrypted image is explicitly formatted, the operation of + flattening the cloned image ceases to be transparent since the parent data + must be re-encrypted according to the cloned image format as it is copied + from the parent snapshot. If encryption is not loaded before the flatten + operation is issued, any parent data that was previously accessible in the + cloned image may become unreadable. + +.. note:: + If a clone of an encrypted image is explicitly formatted, the operation of + shrinking the cloned image ceases to be transparent since in some cases + (e.g. if the cloned image has snapshots or if the cloned image is being + shrunk to a size that is not aligned with the object size) it involves + copying some data from the parent snapshot, similar to flattening. If + encryption is not loaded before the shrink operation is issued, any parent + data that was previously accessible in the cloned image may become + unreadable. + +.. note:: + Encryption load can be automatically applied when mounting RBD images as + block devices via `rbd-nbd`_. + +Supported Formats +================= + +LUKS +~~~~~~~ + +Both LUKS1 and LUKS2 are supported. The data layout is fully compliant with the +LUKS specification. Thus, images formatted by RBD can be loaded using external +LUKS-supporting tools such as dm-crypt or QEMU. Furthermore, existing LUKS +data, created outside of RBD, can be imported (by copying the raw LUKS data +into the image) and loaded by RBD encryption. + +.. note:: + The LUKS formats are supported on Linux-based systems only. + +.. note:: + Currently, only AES-128 and AES-256 encryption algorithms are supported. + Additionally, xts-plain64 is currently the only supported encryption mode. + +To use the LUKS format, start by formatting the image: + +.. prompt:: bash $ + + rbd encryption format [--cipher-alg {aes-128|aes-256}] {image-spec} {luks1|luks2} {passphrase-file} + +The encryption format operation generates a LUKS header and writes it to the +beginning of the image. The header is appended with a single keyslot holding a +randomly-generated encryption key, and is protected by the passphrase read from +`passphrase-file`. + +.. note:: + In older versions, if the content of `passphrase-file` ended with a newline + character, it was stripped off. + +By default, AES-256 in xts-plain64 mode (which is the current recommended mode, +and the usual default for other tools) will be used. The format operation +allows selecting AES-128 as well. Adding / removing passphrases is currently +not supported by RBD, but can be applied to the raw RBD data using compatible +tools such as cryptsetup. + +The LUKS header size can vary (up to 136MiB in LUKS2), but is usually up to +16MiB, depending on the version of `libcryptsetup` installed. For optimal +performance, the encryption format will set the data offset to be aligned with +the image stripe period size. For example, expect a minimum overhead of 8MiB if +using an image configured with an 8MiB object size and a minimum overhead of +12MiB if using an image configured with a 4MiB object size and `stripe count`_ +of 3. + +In LUKS1, sectors, which are the minimal encryption units, are fixed at 512 +bytes. LUKS2 supports larger sectors, and for better performance we set +the default sector size to the maximum of 4KiB. Writes which are either smaller +than a sector, or are not aligned to a sector start, will trigger a guarded +read-modify-write chain on the client, with a considerable latency penalty. +A batch of such unaligned writes can lead to IO races which will further +deteriorate performance. Thus it is advisable to avoid using RBD encryption +in cases where incoming writes cannot be guaranteed to be sector-aligned. + +To map a LUKS-formatted image run: + +.. prompt:: bash # + + rbd device map -t nbd -o encryption-passphrase-file={passphrase-file} {image-spec} + +Note that for security reasons, both the encryption format and encryption load +operations are CPU-intensive, and may take a few seconds to complete. For the +encryption operations of actual image IO, assuming AES-NI is enabled, +a relative small microseconds latency should be added, as well as a small +increase in CPU utilization. + +Examples +======== + +Create a LUKS2-formatted image with the effective size of 50GiB: + +.. prompt:: bash $ + + rbd create --size 50G mypool/myimage + rbd encryption format mypool/myimage luks2 passphrase.bin + rbd resize --size 50G --encryption-passphrase-file passphrase.bin mypool/myimage + +``rbd resize`` command at the end grows the image to compensate for the +overhead associated with the LUKS2 header. + +Given a LUKS2-formatted image, create a LUKS2-formatted clone with the +same effective size: + +.. prompt:: bash $ + + rbd snap create mypool/myimage@snap + rbd snap protect mypool/myimage@snap + rbd clone mypool/myimage@snap mypool/myclone + rbd encryption format mypool/myclone luks2 clone-passphrase.bin + +Given a LUKS2-formatted image with the effective size of 50GiB, create +a LUKS1-formatted clone with the same effective size: + +.. prompt:: bash $ + + rbd snap create mypool/myimage@snap + rbd snap protect mypool/myimage@snap + rbd clone mypool/myimage@snap mypool/myclone + rbd encryption format mypool/myclone luks1 clone-passphrase.bin + rbd resize --size 50G --allow-shrink --encryption-passphrase-file clone-passphrase.bin --encryption-passphrase-file passphrase.bin mypool/myclone + +Since LUKS1 header is usually smaller than LUKS2 header, ``rbd resize`` +command at the end shrinks the cloned image to get rid of unneeded +space allowance. + +Given a LUKS1-formatted image with the effective size of 50GiB, create +a LUKS2-formatted clone with the same effective size: + +.. prompt:: bash $ + + rbd resize --size 51G mypool/myimage + rbd snap create mypool/myimage@snap + rbd snap protect mypool/myimage@snap + rbd clone mypool/myimage@snap mypool/myclone + rbd encryption format mypool/myclone luks2 clone-passphrase.bin + rbd resize --size 50G --allow-shrink --encryption-passphrase-file passphrase.bin mypool/myimage + rbd resize --size 50G --allow-shrink --encryption-passphrase-file clone-passphrase.bin --encryption-passphrase-file passphrase.bin mypool/myclone + +Since LUKS2 header is usually bigger than LUKS1 header, ``rbd resize`` +command at the beginning temporarily grows the parent image to reserve +some extra space in the parent snapshot and consequently the cloned +image. This is necessary to make all parent data accessible in the +cloned image. ``rbd resize`` commands at the end shrink the parent +image back to its original size (this does not impact the parent +snapshot) and also the cloned image to get rid of unused reserved +space. + +The same applies to creating a formatted clone of an unformatted +(plaintext) image since an unformatted image does not have a header at +all. + +.. _journal feature: ../rbd-mirroring/#enable-image-journaling-feature +.. _Supported Formats: #supported-formats +.. _rbd-nbd: ../../man/8/rbd-nbd +.. _stripe count: ../../man/8/rbd/#striping |