block/rbd: Add support for rbd image encryption
Starting from ceph Pacific, RBD has built-in support for image-level encryption. Currently supported formats are LUKS version 1 and 2. There are 2 new relevant librbd APIs for controlling encryption, both expect an open image context: rbd_encryption_format: formats an image (i.e. writes the LUKS header) rbd_encryption_load: loads encryptor/decryptor to the image IO stack This commit extends the qemu rbd driver API to support the above. Signed-off-by: Or Ozeri <oro@il.ibm.com> Message-Id: <20210627114635.39326-1-oro@il.ibm.com> Reviewed-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
0725570b2d
commit
42e4ac9ef5
361
block/rbd.c
361
block/rbd.c
@ -73,6 +73,18 @@
|
|||||||
#define LIBRBD_USE_IOVEC 0
|
#define LIBRBD_USE_IOVEC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN 8
|
||||||
|
|
||||||
|
static const char rbd_luks_header_verification[
|
||||||
|
RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
|
||||||
|
'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char rbd_luks2_header_verification[
|
||||||
|
RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
|
||||||
|
'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RBD_AIO_READ,
|
RBD_AIO_READ,
|
||||||
RBD_AIO_WRITE,
|
RBD_AIO_WRITE,
|
||||||
@ -351,6 +363,203 @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LIBRBD_SUPPORTS_ENCRYPTION
|
||||||
|
static int qemu_rbd_convert_luks_options(
|
||||||
|
RbdEncryptionOptionsLUKSBase *luks_opts,
|
||||||
|
char **passphrase,
|
||||||
|
size_t *passphrase_len,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
return qcrypto_secret_lookup(luks_opts->key_secret, (uint8_t **)passphrase,
|
||||||
|
passphrase_len, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_rbd_convert_luks_create_options(
|
||||||
|
RbdEncryptionCreateOptionsLUKSBase *luks_opts,
|
||||||
|
rbd_encryption_algorithm_t *alg,
|
||||||
|
char **passphrase,
|
||||||
|
size_t *passphrase_len,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
r = qemu_rbd_convert_luks_options(
|
||||||
|
qapi_RbdEncryptionCreateOptionsLUKSBase_base(luks_opts),
|
||||||
|
passphrase, passphrase_len, errp);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (luks_opts->has_cipher_alg) {
|
||||||
|
switch (luks_opts->cipher_alg) {
|
||||||
|
case QCRYPTO_CIPHER_ALG_AES_128: {
|
||||||
|
*alg = RBD_ENCRYPTION_ALGORITHM_AES128;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QCRYPTO_CIPHER_ALG_AES_256: {
|
||||||
|
*alg = RBD_ENCRYPTION_ALGORITHM_AES256;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
r = -ENOTSUP;
|
||||||
|
error_setg_errno(errp, -r, "unknown encryption algorithm: %u",
|
||||||
|
luks_opts->cipher_alg);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* default alg */
|
||||||
|
*alg = RBD_ENCRYPTION_ALGORITHM_AES256;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_rbd_encryption_format(rbd_image_t image,
|
||||||
|
RbdEncryptionCreateOptions *encrypt,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
g_autofree char *passphrase = NULL;
|
||||||
|
size_t passphrase_len;
|
||||||
|
rbd_encryption_format_t format;
|
||||||
|
rbd_encryption_options_t opts;
|
||||||
|
rbd_encryption_luks1_format_options_t luks_opts;
|
||||||
|
rbd_encryption_luks2_format_options_t luks2_opts;
|
||||||
|
size_t opts_size;
|
||||||
|
uint64_t raw_size, effective_size;
|
||||||
|
|
||||||
|
r = rbd_get_size(image, &raw_size);
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "cannot get raw image size");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (encrypt->format) {
|
||||||
|
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: {
|
||||||
|
memset(&luks_opts, 0, sizeof(luks_opts));
|
||||||
|
format = RBD_ENCRYPTION_FORMAT_LUKS1;
|
||||||
|
opts = &luks_opts;
|
||||||
|
opts_size = sizeof(luks_opts);
|
||||||
|
r = qemu_rbd_convert_luks_create_options(
|
||||||
|
qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks),
|
||||||
|
&luks_opts.alg, &passphrase, &passphrase_len, errp);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
luks_opts.passphrase = passphrase;
|
||||||
|
luks_opts.passphrase_size = passphrase_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
|
||||||
|
memset(&luks2_opts, 0, sizeof(luks2_opts));
|
||||||
|
format = RBD_ENCRYPTION_FORMAT_LUKS2;
|
||||||
|
opts = &luks2_opts;
|
||||||
|
opts_size = sizeof(luks2_opts);
|
||||||
|
r = qemu_rbd_convert_luks_create_options(
|
||||||
|
qapi_RbdEncryptionCreateOptionsLUKS2_base(
|
||||||
|
&encrypt->u.luks2),
|
||||||
|
&luks2_opts.alg, &passphrase, &passphrase_len, errp);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
luks2_opts.passphrase = passphrase;
|
||||||
|
luks2_opts.passphrase_size = passphrase_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
r = -ENOTSUP;
|
||||||
|
error_setg_errno(
|
||||||
|
errp, -r, "unknown image encryption format: %u",
|
||||||
|
encrypt->format);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = rbd_encryption_format(image, format, opts, opts_size);
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "encryption format fail");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = rbd_get_size(image, &effective_size);
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "cannot get effective image size");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = rbd_resize(image, raw_size + (raw_size - effective_size));
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "cannot resize image after format");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_rbd_encryption_load(rbd_image_t image,
|
||||||
|
RbdEncryptionOptions *encrypt,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
g_autofree char *passphrase = NULL;
|
||||||
|
size_t passphrase_len;
|
||||||
|
rbd_encryption_luks1_format_options_t luks_opts;
|
||||||
|
rbd_encryption_luks2_format_options_t luks2_opts;
|
||||||
|
rbd_encryption_format_t format;
|
||||||
|
rbd_encryption_options_t opts;
|
||||||
|
size_t opts_size;
|
||||||
|
|
||||||
|
switch (encrypt->format) {
|
||||||
|
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: {
|
||||||
|
memset(&luks_opts, 0, sizeof(luks_opts));
|
||||||
|
format = RBD_ENCRYPTION_FORMAT_LUKS1;
|
||||||
|
opts = &luks_opts;
|
||||||
|
opts_size = sizeof(luks_opts);
|
||||||
|
r = qemu_rbd_convert_luks_options(
|
||||||
|
qapi_RbdEncryptionOptionsLUKS_base(&encrypt->u.luks),
|
||||||
|
&passphrase, &passphrase_len, errp);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
luks_opts.passphrase = passphrase;
|
||||||
|
luks_opts.passphrase_size = passphrase_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
|
||||||
|
memset(&luks2_opts, 0, sizeof(luks2_opts));
|
||||||
|
format = RBD_ENCRYPTION_FORMAT_LUKS2;
|
||||||
|
opts = &luks2_opts;
|
||||||
|
opts_size = sizeof(luks2_opts);
|
||||||
|
r = qemu_rbd_convert_luks_options(
|
||||||
|
qapi_RbdEncryptionOptionsLUKS2_base(&encrypt->u.luks2),
|
||||||
|
&passphrase, &passphrase_len, errp);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
luks2_opts.passphrase = passphrase;
|
||||||
|
luks2_opts.passphrase_size = passphrase_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
r = -ENOTSUP;
|
||||||
|
error_setg_errno(
|
||||||
|
errp, -r, "unknown image encryption format: %u",
|
||||||
|
encrypt->format);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = rbd_encryption_load(image, format, opts, opts_size);
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "encryption load fail");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FIXME Deprecate and remove keypairs or make it available in QMP. */
|
/* FIXME Deprecate and remove keypairs or make it available in QMP. */
|
||||||
static int qemu_rbd_do_create(BlockdevCreateOptions *options,
|
static int qemu_rbd_do_create(BlockdevCreateOptions *options,
|
||||||
const char *keypairs, const char *password_secret,
|
const char *keypairs, const char *password_secret,
|
||||||
@ -368,6 +577,13 @@ static int qemu_rbd_do_create(BlockdevCreateOptions *options,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LIBRBD_SUPPORTS_ENCRYPTION
|
||||||
|
if (opts->has_encrypt) {
|
||||||
|
error_setg(errp, "RBD library does not support image encryption");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (opts->has_cluster_size) {
|
if (opts->has_cluster_size) {
|
||||||
int64_t objsize = opts->cluster_size;
|
int64_t objsize = opts->cluster_size;
|
||||||
if ((objsize - 1) & objsize) { /* not a power of 2? */
|
if ((objsize - 1) & objsize) { /* not a power of 2? */
|
||||||
@ -393,6 +609,28 @@ static int qemu_rbd_do_create(BlockdevCreateOptions *options,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LIBRBD_SUPPORTS_ENCRYPTION
|
||||||
|
if (opts->has_encrypt) {
|
||||||
|
rbd_image_t image;
|
||||||
|
|
||||||
|
ret = rbd_open(io_ctx, opts->location->image, &image, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret,
|
||||||
|
"error opening image '%s' for encryption format",
|
||||||
|
opts->location->image);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = qemu_rbd_encryption_format(image, opts->encrypt, errp);
|
||||||
|
rbd_close(image);
|
||||||
|
if (ret < 0) {
|
||||||
|
/* encryption format fail, try removing the image */
|
||||||
|
rbd_remove(io_ctx, opts->location->image);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
rados_ioctx_destroy(io_ctx);
|
rados_ioctx_destroy(io_ctx);
|
||||||
@ -405,6 +643,43 @@ static int qemu_rbd_co_create(BlockdevCreateOptions *options, Error **errp)
|
|||||||
return qemu_rbd_do_create(options, NULL, NULL, errp);
|
return qemu_rbd_do_create(options, NULL, NULL, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemu_rbd_extract_encryption_create_options(
|
||||||
|
QemuOpts *opts,
|
||||||
|
RbdEncryptionCreateOptions **spec,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QDict *opts_qdict;
|
||||||
|
QDict *encrypt_qdict;
|
||||||
|
Visitor *v;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
opts_qdict = qemu_opts_to_qdict(opts, NULL);
|
||||||
|
qdict_extract_subqdict(opts_qdict, &encrypt_qdict, "encrypt.");
|
||||||
|
qobject_unref(opts_qdict);
|
||||||
|
if (!qdict_size(encrypt_qdict)) {
|
||||||
|
*spec = NULL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert options into a QAPI object */
|
||||||
|
v = qobject_input_visitor_new_flat_confused(encrypt_qdict, errp);
|
||||||
|
if (!v) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_type_RbdEncryptionCreateOptions(v, NULL, spec, errp);
|
||||||
|
visit_free(v);
|
||||||
|
if (!*spec) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
qobject_unref(encrypt_qdict);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int coroutine_fn qemu_rbd_co_create_opts(BlockDriver *drv,
|
static int coroutine_fn qemu_rbd_co_create_opts(BlockDriver *drv,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
QemuOpts *opts,
|
QemuOpts *opts,
|
||||||
@ -413,6 +688,7 @@ static int coroutine_fn qemu_rbd_co_create_opts(BlockDriver *drv,
|
|||||||
BlockdevCreateOptions *create_options;
|
BlockdevCreateOptions *create_options;
|
||||||
BlockdevCreateOptionsRbd *rbd_opts;
|
BlockdevCreateOptionsRbd *rbd_opts;
|
||||||
BlockdevOptionsRbd *loc;
|
BlockdevOptionsRbd *loc;
|
||||||
|
RbdEncryptionCreateOptions *encrypt = NULL;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
const char *keypairs, *password_secret;
|
const char *keypairs, *password_secret;
|
||||||
QDict *options = NULL;
|
QDict *options = NULL;
|
||||||
@ -441,6 +717,13 @@ static int coroutine_fn qemu_rbd_co_create_opts(BlockDriver *drv,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = qemu_rbd_extract_encryption_create_options(opts, &encrypt, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
rbd_opts->encrypt = encrypt;
|
||||||
|
rbd_opts->has_encrypt = !!encrypt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Caution: while qdict_get_try_str() is fine, getting non-string
|
* Caution: while qdict_get_try_str() is fine, getting non-string
|
||||||
* types would require more care. When @options come from -blockdev
|
* types would require more care. When @options come from -blockdev
|
||||||
@ -766,12 +1049,24 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
goto failed_open;
|
goto failed_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->has_encrypt) {
|
||||||
|
#ifdef LIBRBD_SUPPORTS_ENCRYPTION
|
||||||
|
r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
|
||||||
|
if (r < 0) {
|
||||||
|
goto failed_post_open;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
r = -ENOTSUP;
|
||||||
|
error_setg(errp, "RBD library does not support image encryption");
|
||||||
|
goto failed_post_open;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
r = rbd_get_size(s->image, &s->image_size);
|
r = rbd_get_size(s->image, &s->image_size);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_setg_errno(errp, -r, "error getting image size from %s",
|
error_setg_errno(errp, -r, "error getting image size from %s",
|
||||||
s->image_name);
|
s->image_name);
|
||||||
rbd_close(s->image);
|
goto failed_post_open;
|
||||||
goto failed_open;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are using an rbd snapshot, we must be r/o, otherwise
|
/* If we are using an rbd snapshot, we must be r/o, otherwise
|
||||||
@ -779,8 +1074,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
if (s->snap != NULL) {
|
if (s->snap != NULL) {
|
||||||
r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
|
r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
rbd_close(s->image);
|
goto failed_post_open;
|
||||||
goto failed_open;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,6 +1084,8 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
r = 0;
|
r = 0;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
failed_post_open:
|
||||||
|
rbd_close(s->image);
|
||||||
failed_open:
|
failed_open:
|
||||||
rados_ioctx_destroy(s->io_ctx);
|
rados_ioctx_destroy(s->io_ctx);
|
||||||
g_free(s->snap);
|
g_free(s->snap);
|
||||||
@ -1060,6 +1356,46 @@ static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ImageInfoSpecific *qemu_rbd_get_specific_info(BlockDriverState *bs,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BDRVRBDState *s = bs->opaque;
|
||||||
|
ImageInfoSpecific *spec_info;
|
||||||
|
char buf[RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {0};
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (s->image_size >= RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) {
|
||||||
|
r = rbd_read(s->image, 0,
|
||||||
|
RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN, buf);
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "cannot read image start for probe");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec_info = g_new(ImageInfoSpecific, 1);
|
||||||
|
*spec_info = (ImageInfoSpecific){
|
||||||
|
.type = IMAGE_INFO_SPECIFIC_KIND_RBD,
|
||||||
|
.u.rbd.data = g_new0(ImageInfoSpecificRbd, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (memcmp(buf, rbd_luks_header_verification,
|
||||||
|
RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
|
||||||
|
spec_info->u.rbd.data->encryption_format =
|
||||||
|
RBD_IMAGE_ENCRYPTION_FORMAT_LUKS;
|
||||||
|
spec_info->u.rbd.data->has_encryption_format = true;
|
||||||
|
} else if (memcmp(buf, rbd_luks2_header_verification,
|
||||||
|
RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
|
||||||
|
spec_info->u.rbd.data->encryption_format =
|
||||||
|
RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
|
||||||
|
spec_info->u.rbd.data->has_encryption_format = true;
|
||||||
|
} else {
|
||||||
|
spec_info->u.rbd.data->has_encryption_format = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec_info;
|
||||||
|
}
|
||||||
|
|
||||||
static int64_t qemu_rbd_getlength(BlockDriverState *bs)
|
static int64_t qemu_rbd_getlength(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
BDRVRBDState *s = bs->opaque;
|
BDRVRBDState *s = bs->opaque;
|
||||||
@ -1253,6 +1589,22 @@ static QemuOptsList qemu_rbd_create_opts = {
|
|||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
.help = "ID of secret providing the password",
|
.help = "ID of secret providing the password",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "encrypt.format",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "Encrypt the image, format choices: 'luks', 'luks2'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "encrypt.cipher-alg",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "Name of encryption cipher algorithm"
|
||||||
|
" (allowed values: aes-128, aes-256)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "encrypt.key-secret",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "ID of secret providing LUKS passphrase",
|
||||||
|
},
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1282,6 +1634,7 @@ static BlockDriver bdrv_rbd = {
|
|||||||
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
|
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
|
||||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||||
.bdrv_get_info = qemu_rbd_getinfo,
|
.bdrv_get_info = qemu_rbd_getinfo,
|
||||||
|
.bdrv_get_specific_info = qemu_rbd_get_specific_info,
|
||||||
.create_opts = &qemu_rbd_create_opts,
|
.create_opts = &qemu_rbd_create_opts,
|
||||||
.bdrv_getlength = qemu_rbd_getlength,
|
.bdrv_getlength = qemu_rbd_getlength,
|
||||||
.bdrv_co_truncate = qemu_rbd_co_truncate,
|
.bdrv_co_truncate = qemu_rbd_co_truncate,
|
||||||
|
@ -127,6 +127,18 @@
|
|||||||
'extents': ['ImageInfo']
|
'extents': ['ImageInfo']
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @ImageInfoSpecificRbd:
|
||||||
|
#
|
||||||
|
# @encryption-format: Image encryption format
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'ImageInfoSpecificRbd',
|
||||||
|
'data': {
|
||||||
|
'*encryption-format': 'RbdImageEncryptionFormat'
|
||||||
|
} }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @ImageInfoSpecific:
|
# @ImageInfoSpecific:
|
||||||
#
|
#
|
||||||
@ -141,7 +153,8 @@
|
|||||||
# If we need to add block driver specific parameters for
|
# If we need to add block driver specific parameters for
|
||||||
# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
|
# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
|
||||||
# to define a ImageInfoSpecificLUKS
|
# to define a ImageInfoSpecificLUKS
|
||||||
'luks': 'QCryptoBlockInfoLUKS'
|
'luks': 'QCryptoBlockInfoLUKS',
|
||||||
|
'rbd': 'ImageInfoSpecificRbd'
|
||||||
} }
|
} }
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -3613,6 +3626,94 @@
|
|||||||
{ 'enum': 'RbdAuthMode',
|
{ 'enum': 'RbdAuthMode',
|
||||||
'data': [ 'cephx', 'none' ] }
|
'data': [ 'cephx', 'none' ] }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdImageEncryptionFormat:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'enum': 'RbdImageEncryptionFormat',
|
||||||
|
'data': [ 'luks', 'luks2' ] }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionOptionsLUKSBase:
|
||||||
|
#
|
||||||
|
# @key-secret: ID of a QCryptoSecret object providing a passphrase
|
||||||
|
# for unlocking the encryption
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'RbdEncryptionOptionsLUKSBase',
|
||||||
|
'data': { 'key-secret': 'str' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionCreateOptionsLUKSBase:
|
||||||
|
#
|
||||||
|
# @cipher-alg: The encryption algorithm
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'RbdEncryptionCreateOptionsLUKSBase',
|
||||||
|
'base': 'RbdEncryptionOptionsLUKSBase',
|
||||||
|
'data': { '*cipher-alg': 'QCryptoCipherAlgorithm' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionOptionsLUKS:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'RbdEncryptionOptionsLUKS',
|
||||||
|
'base': 'RbdEncryptionOptionsLUKSBase',
|
||||||
|
'data': { } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionOptionsLUKS2:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'RbdEncryptionOptionsLUKS2',
|
||||||
|
'base': 'RbdEncryptionOptionsLUKSBase',
|
||||||
|
'data': { } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionCreateOptionsLUKS:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'RbdEncryptionCreateOptionsLUKS',
|
||||||
|
'base': 'RbdEncryptionCreateOptionsLUKSBase',
|
||||||
|
'data': { } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionCreateOptionsLUKS2:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'RbdEncryptionCreateOptionsLUKS2',
|
||||||
|
'base': 'RbdEncryptionCreateOptionsLUKSBase',
|
||||||
|
'data': { } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionOptions:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'union': 'RbdEncryptionOptions',
|
||||||
|
'base': { 'format': 'RbdImageEncryptionFormat' },
|
||||||
|
'discriminator': 'format',
|
||||||
|
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
|
||||||
|
'luks2': 'RbdEncryptionOptionsLUKS2' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @RbdEncryptionCreateOptions:
|
||||||
|
#
|
||||||
|
# Since: 6.1
|
||||||
|
##
|
||||||
|
{ 'union': 'RbdEncryptionCreateOptions',
|
||||||
|
'base': { 'format': 'RbdImageEncryptionFormat' },
|
||||||
|
'discriminator': 'format',
|
||||||
|
'data': { 'luks': 'RbdEncryptionCreateOptionsLUKS',
|
||||||
|
'luks2': 'RbdEncryptionCreateOptionsLUKS2' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockdevOptionsRbd:
|
# @BlockdevOptionsRbd:
|
||||||
#
|
#
|
||||||
@ -3628,6 +3729,8 @@
|
|||||||
#
|
#
|
||||||
# @snapshot: Ceph snapshot name.
|
# @snapshot: Ceph snapshot name.
|
||||||
#
|
#
|
||||||
|
# @encrypt: Image encryption options. (Since 6.1)
|
||||||
|
#
|
||||||
# @user: Ceph id name.
|
# @user: Ceph id name.
|
||||||
#
|
#
|
||||||
# @auth-client-required: Acceptable authentication modes.
|
# @auth-client-required: Acceptable authentication modes.
|
||||||
@ -3650,6 +3753,7 @@
|
|||||||
'image': 'str',
|
'image': 'str',
|
||||||
'*conf': 'str',
|
'*conf': 'str',
|
||||||
'*snapshot': 'str',
|
'*snapshot': 'str',
|
||||||
|
'*encrypt': 'RbdEncryptionOptions',
|
||||||
'*user': 'str',
|
'*user': 'str',
|
||||||
'*auth-client-required': ['RbdAuthMode'],
|
'*auth-client-required': ['RbdAuthMode'],
|
||||||
'*key-secret': 'str',
|
'*key-secret': 'str',
|
||||||
@ -4403,13 +4507,15 @@
|
|||||||
# point to a snapshot.
|
# point to a snapshot.
|
||||||
# @size: Size of the virtual disk in bytes
|
# @size: Size of the virtual disk in bytes
|
||||||
# @cluster-size: RBD object size
|
# @cluster-size: RBD object size
|
||||||
|
# @encrypt: Image encryption options. (Since 6.1)
|
||||||
#
|
#
|
||||||
# Since: 2.12
|
# Since: 2.12
|
||||||
##
|
##
|
||||||
{ 'struct': 'BlockdevCreateOptionsRbd',
|
{ 'struct': 'BlockdevCreateOptionsRbd',
|
||||||
'data': { 'location': 'BlockdevOptionsRbd',
|
'data': { 'location': 'BlockdevOptionsRbd',
|
||||||
'size': 'size',
|
'size': 'size',
|
||||||
'*cluster-size' : 'size' } }
|
'*cluster-size' : 'size',
|
||||||
|
'*encrypt' : 'RbdEncryptionCreateOptions' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockdevVmdkSubformat:
|
# @BlockdevVmdkSubformat:
|
||||||
|
Loading…
Reference in New Issue
Block a user