Adds the option to keep storage devices encrypted at rest. This can be enabled or disabled by a parameter to `Vm.assemble`. It is enabled by default: ``` > st = Prog::Vm::Nexus.assemble(mykey, nil, storage_encrypted: true) ``` We also add a program to rotate key encryption keys: ``` > st = Strand.create(prog: 'RotateStorageKek', label: 'start', stack: [{subject_id: vm_storage_volume.id}]) ``` We use envelope encryption [1]. On the Clover side, a "key encryption key" (KEK) is generated & stored in database. On the rhizome side, a "data encryption key" (DEK) is generated & used to encrypt data. The DEK is encrypted using KEK & saved near the storage data in the host. Now attackers cannot decrypt data if they only get access to either of DB or the file system. They need to get access to both of them to be able to decrypt. We use "AES-256-GCM" for key encryption, and "AES_XTS" for data encryption. The KEK is saved in the "StorageKeyEncryptionKey" table. The DEK is saved in `/var/storage/$vm_name/$disk_index/data_encryption_key.json`. Key fields of the json file are encrypted using KEK. I have named the key fields "key" and "key2" to match the terminology SPDK uses. [1] https://cloud.google.com/kms/docs/envelope-encryption
20 lines
735 B
Ruby
20 lines
735 B
Ruby
# frozen_string_literal: true
|
|
|
|
Sequel.migration do
|
|
change do
|
|
create_table(:storage_key_encryption_key) do
|
|
column :id, :uuid, primary_key: true, default: Sequel.lit("gen_random_uuid()")
|
|
column :algorithm, :text, null: false, collate: '"C"'
|
|
column :key, :text, null: false
|
|
column :init_vector, :text, null: false
|
|
column :auth_data, :text, null: false
|
|
column :created_at, :timestamptz, null: false, default: Sequel.lit("now()")
|
|
end
|
|
|
|
alter_table(:vm_storage_volume) do
|
|
add_foreign_key :key_encryption_key_1_id, :storage_key_encryption_key, type: :uuid, null: true
|
|
add_foreign_key :key_encryption_key_2_id, :storage_key_encryption_key, type: :uuid, null: true
|
|
end
|
|
end
|
|
end
|