ceph-csi/docs/design/proposals/encrypted-pvc.md
Vasyl Purchel 419ad0dd8e Adds per volume encryption with Vault integration
- adds proposal document for PVC encryption from PR448
- adds per-volume encription by generating encryption passphrase
  for each volume and storing it in a KMS
- adds HashiCorp Vault integration as a KMS for encryption passphrases
- avoids encrypting volume second time if it was already encrypted but
  no file system created
- avoids unnecessary checks if volume is a mapped device when encryption
  was not requested
- prevents resizing encrypted volumes (it is not currently supported)
- prevents creating snapshots from encrypted volumes to prevent attack
  on encryption key (security guard until re-encryption of volumes
  implemented)

Signed-off-by: Vasyl Purchel vasyl.purchel@workday.com
Signed-off-by: Andrea Baglioni andrea.baglioni@workday.com

Fixes #420
Fixes #744
2020-02-05 05:18:56 +00:00

4.3 KiB

Encrypted Persistent Volume Claims

Proposal

Subject of this proposal is to add support for encryption of RBD volumes in Ceph-CSI.

Some but not all the benefits of this approach:

  • guarantee encryption in transit to rbd without using messenger v2
  • extra security layer to application with special regulatory needs
  • at rest encryption can be disabled to selectively allow encryption only where required

Document Terminology

  • volume encryption: encryption of a volume attached by rbd
  • encryption at rest: encryption of physical disk done by ceph
  • LUKS: Linux Unified Key Setup: stores all of the needed setup information for dm-crypt on the disk
  • dm-crypt: linux kernel device-mapper crypto target
  • cryptsetup: the command line tool to interface with dm-crypt

Proposed Solution

The proposed solution in this document, is to address the volume encryption requirement by using dm-crypt module through cryptsetup cli interface.

Implementation Summary

  • Encryption is implemented using cryptsetup with LUKS extension. A good introduction to LUKS and dm-crypt in general can be found here Functions to implement necessary interaction are implemented in a separate cryptsetup.go file.

    • LuksFormat
    • LuksOpen
    • LuksClose
    • LuksStatus
  • CreateVolume: refactored to prepare for encryption (tag image that it requires encryption later), before returning, if encrypted volume option is set.

  • NodeStageVolume: refactored to call encryptDevice method on the very first volume attach request

  • NodeStageVolume: refactored to open encrypted device (openEncryptedDevice)

  • openEncryptedDevice: looks up for a passphrase matching the volume id, returns the new device path in the form: /dev/mapper/luks-<volume_id>. On the woker node where the attach is scheduled:

    $ lsblk
    NAME                            MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
    sda                               8:0    0   10G  0 disk
    └─sda1                            8:1    0   10G  0 part  /
    sdb                               8:16   0   20G  0 disk
    rbd0                            253:0    0    1G  0 disk
    └─luks-pvc-8a710f4c934811e9 252:0    0 1020M  0 crypt /var/lib/kubelet/pods/9eaceaef-936c-11e9-b396-005056af3de0/volumes/kubernetes.io~csi/pvc-8a710f4c934811e9/mount
    
  • detachRBDDevice: calls LuksClose function to remove the LUKS mapping before detaching the volume.

  • StorageClass extended with following parameters:

    1. encrypted ("true" or "false")
    2. encryptionKMS (string representing kms of choice) ceph-csi plugin may support different kms vendors with different type of authentication
    3. encryptionKMSID (string representing kms configuration)
  • New KMS Configuration created.

Annotated YAML for RBD StorageClass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: csi-rbd
provisioner: rbd.csi.ceph.com
parameters:
   # String representing Ceph cluster configuration
   clusterID: <cluster-id>
   # ceph pool
   pool: rbd

   # RBD image features, CSI creates image with image-format 2
   # CSI RBD currently supports only `layering` feature.
   imageFeatures: layering

   # The secrets have to contain Ceph credentials with required access
   # to the 'pool'.
   csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
   csi.storage.k8s.io/provisioner-secret-namespace: default
   csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
   csi.storage.k8s.io/controller-expand-secret-namespace: default
   csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
   csi.storage.k8s.io/node-stage-secret-namespace: default
   # Specify the filesystem type of the volume. If not specified,
   # csi-provisioner will set default as `ext4`.
   csi.storage.k8s.io/fstype: ext4

   # Encrypt volumes
   encrypted: "true"

   # The type of kms we want to connect to: Barbican, aws kms or others can be
   # supported
   encryptionKMS: vault
   # String representing a KMS configuration
   encryptionKMSID: <kms-id>

reclaimPolicy: Delete

And kms configuration:

---
apiVersion: v1
kind: ConfigMap
data:
  config.json: |-
    [
      {
        "kmsID": "<kms-id>",
        kms specific config...
      }
    ]    
metadata:
  name: ceph-csi-encryption-kms-config