# 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](https://wiki.archlinux.org/index.php/Dm-crypt/Device_encryption#Encrypting_devices_with_cryptsetup) 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: ```shell $ 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") 1. `encryptionKMSID` (string representing kms configuration of choice) ceph-csi plugin may support different kms vendors with different type of authentication * New KMS Configuration created. #### Annotated YAML for RBD StorageClass ```yaml 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" # Use external key management system for encryption passphrases by specifying # a unique ID matching KMS ConfigMap. The ID is only used for correlation to # configmap entry. encryptionKMSID: <kms-id> reclaimPolicy: Delete ``` And kms configuration: ```yaml --- apiVersion: v1 kind: ConfigMap data: config.json: |- { "<kms-id>": { "encryptionKMSType": "kmsType", kms specific config... } } metadata: name: ceph-csi-encryption-kms-config ```