mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
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
This commit is contained in:
committed by
mergify[bot]
parent
1adef00c86
commit
419ad0dd8e
@ -95,7 +95,7 @@ func (cs *ControllerServer) parseVolCreateRequest(ctx context.Context, req *csi.
|
||||
}
|
||||
|
||||
// if it's NOT SINGLE_NODE_WRITER and it's BLOCK we'll set the parameter to ignore the in-use checks
|
||||
rbdVol, err := genVolFromVolumeOptions(ctx, req.GetParameters(), nil, (isMultiNode && isBlock), false)
|
||||
rbdVol, err := genVolFromVolumeOptions(ctx, req.GetParameters(), req.GetSecrets(), (isMultiNode && isBlock), false)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
@ -343,7 +343,7 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
|
||||
defer cs.VolumeLocks.Release(volumeID)
|
||||
|
||||
rbdVol := &rbdVolume{}
|
||||
if err := genVolFromVolID(ctx, rbdVol, volumeID, cr); err != nil {
|
||||
if err = genVolFromVolID(ctx, rbdVol, volumeID, cr, req.GetSecrets()); err != nil {
|
||||
// If error is ErrInvalidVolID it could be a version 1.0.0 or lower volume, attempt
|
||||
// to process it as such
|
||||
if _, ok := err.(ErrInvalidVolID); ok {
|
||||
@ -377,7 +377,7 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
|
||||
}
|
||||
defer cs.VolumeLocks.Release(rbdVol.RequestName)
|
||||
|
||||
if err := undoVolReservation(ctx, rbdVol, cr); err != nil {
|
||||
if err = undoVolReservation(ctx, rbdVol, cr); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
@ -393,18 +393,24 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
|
||||
|
||||
// Deleting rbd image
|
||||
klog.V(4).Infof(util.Log(ctx, "deleting image %s"), rbdVol.RbdImageName)
|
||||
if err := deleteImage(ctx, rbdVol, cr); err != nil {
|
||||
if err = deleteImage(ctx, rbdVol, cr); err != nil {
|
||||
klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s/%s with error: %v"),
|
||||
rbdVol.Pool, rbdVol.RbdImageName, err)
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
if err := undoVolReservation(ctx, rbdVol, cr); err != nil {
|
||||
if err = undoVolReservation(ctx, rbdVol, cr); err != nil {
|
||||
klog.Errorf(util.Log(ctx, "failed to remove reservation for volume (%s) with backing image (%s) (%s)"),
|
||||
rbdVol.RequestName, rbdVol.RbdImageName, err)
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
if rbdVol.Encrypted {
|
||||
if err = rbdVol.KMS.DeletePassphrase(rbdVol.VolID); err != nil {
|
||||
klog.V(3).Infof(util.Log(ctx, "failed to clean the passphrase for volume %s: %s"), rbdVol.VolID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
@ -447,7 +453,7 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
|
||||
|
||||
// Fetch source volume information
|
||||
rbdVol := new(rbdVolume)
|
||||
err = genVolFromVolID(ctx, rbdVol, req.GetSourceVolumeId(), cr)
|
||||
err = genVolFromVolID(ctx, rbdVol, req.GetSourceVolumeId(), cr, req.GetSecrets())
|
||||
if err != nil {
|
||||
if _, ok := err.(ErrImageNotFound); ok {
|
||||
return nil, status.Errorf(codes.NotFound, "source Volume ID %s not found", req.GetSourceVolumeId())
|
||||
@ -455,6 +461,12 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
// TODO: re-encrypt snapshot with a new passphrase
|
||||
if rbdVol.Encrypted {
|
||||
return nil, status.Errorf(codes.Unimplemented, "source Volume %s is encrypted, "+
|
||||
"snapshotting is not supported currently", rbdVol.VolID)
|
||||
}
|
||||
|
||||
// Check if source volume was created with required image features for snaps
|
||||
if !hasSnapshotFeature(rbdVol.ImageFeatures) {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "volume(%s) has not snapshot feature(layering)", req.GetSourceVolumeId())
|
||||
@ -698,7 +710,7 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi
|
||||
defer cr.DeleteCredentials()
|
||||
|
||||
rbdVol := &rbdVolume{}
|
||||
err = genVolFromVolID(ctx, rbdVol, volID, cr)
|
||||
err = genVolFromVolID(ctx, rbdVol, volID, cr, req.GetSecrets())
|
||||
if err != nil {
|
||||
if _, ok := err.(ErrImageNotFound); ok {
|
||||
return nil, status.Errorf(codes.NotFound, "volume ID %s not found", volID)
|
||||
@ -706,6 +718,11 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
if rbdVol.Encrypted {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "encrypted volumes do not support resize (%s/%s)",
|
||||
rbdVol.Pool, rbdVol.RbdImageName)
|
||||
}
|
||||
|
||||
// always round up the request size in bytes to the nearest MiB/GiB
|
||||
volSize := util.RoundOffBytes(req.GetCapacityRange().GetRequiredBytes())
|
||||
|
||||
|
@ -116,6 +116,7 @@ func (ns *NodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
|
||||
volOptions.VolID = req.GetVolumeId()
|
||||
|
||||
isMounted := false
|
||||
isEncrypted := false
|
||||
isStagePathCreated := false
|
||||
devicePath := ""
|
||||
|
||||
@ -127,7 +128,7 @@ func (ns *NodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
ns.undoStagingTransaction(ctx, stagingParentPath, devicePath, volID, isStagePathCreated, isMounted)
|
||||
ns.undoStagingTransaction(ctx, stagingParentPath, devicePath, volID, isStagePathCreated, isMounted, isEncrypted)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -140,10 +141,11 @@ func (ns *NodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
|
||||
req.GetVolumeId(), volOptions.Pool, devicePath)
|
||||
|
||||
if volOptions.Encrypted {
|
||||
devicePath, err = ns.processEncryptedDevice(ctx, volOptions, devicePath, cr, req.GetSecrets())
|
||||
devicePath, err = ns.processEncryptedDevice(ctx, volOptions, devicePath, cr)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
isEncrypted = true
|
||||
}
|
||||
|
||||
err = ns.createStageMountPoint(ctx, stagingTargetPath, isBlock)
|
||||
@ -170,7 +172,7 @@ func (ns *NodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *NodeServer) undoStagingTransaction(ctx context.Context, stagingParentPath, devicePath, volID string, isStagePathCreated, isMounted bool) {
|
||||
func (ns *NodeServer) undoStagingTransaction(ctx context.Context, stagingParentPath, devicePath, volID string, isStagePathCreated, isMounted, isEncrypted bool) {
|
||||
var err error
|
||||
|
||||
stagingTargetPath := stagingParentPath + "/" + volID
|
||||
@ -193,7 +195,7 @@ func (ns *NodeServer) undoStagingTransaction(ctx context.Context, stagingParentP
|
||||
|
||||
// Unmapping rbd device
|
||||
if devicePath != "" {
|
||||
err = detachRBDDevice(ctx, devicePath, volID)
|
||||
err = detachRBDDevice(ctx, devicePath, volID, isEncrypted)
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "failed to unmap rbd device: %s for volume %s with error: %v"), devicePath, volID, err)
|
||||
// continue on failure to delete the stash file, as kubernetes will fail to delete the staging path otherwise
|
||||
@ -510,7 +512,7 @@ func (ns *NodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
|
||||
|
||||
// Unmapping rbd device
|
||||
imageSpec := imgInfo.Pool + "/" + imgInfo.ImageName
|
||||
if err = detachRBDImageOrDeviceSpec(ctx, imageSpec, true, imgInfo.NbdAccess, req.GetVolumeId()); err != nil {
|
||||
if err = detachRBDImageOrDeviceSpec(ctx, imageSpec, true, imgInfo.NbdAccess, imgInfo.Encrypted, req.GetVolumeId()); err != nil {
|
||||
klog.Errorf(util.Log(ctx, "error unmapping volume (%s) from staging path (%s): (%v)"), req.GetVolumeId(), stagingTargetPath, err)
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
@ -526,6 +528,7 @@ func (ns *NodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// NodeExpandVolume resizes rbd volumes
|
||||
func (ns *NodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) {
|
||||
volumeID := req.GetVolumeId()
|
||||
if volumeID == "" {
|
||||
@ -620,7 +623,7 @@ func (ns *NodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetC
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string, cr *util.Credentials, secrets map[string]string) (string, error) {
|
||||
func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string, cr *util.Credentials) (string, error) {
|
||||
imageSpec := volOptions.Pool + "/" + volOptions.RbdImageName
|
||||
encrypted, err := util.CheckRbdImageEncrypted(ctx, cr, volOptions.Monitors, imageSpec)
|
||||
if err != nil {
|
||||
@ -637,20 +640,31 @@ func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rb
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get disk format for path %s, error: %v", devicePath, err)
|
||||
}
|
||||
if existingFormat != "" {
|
||||
|
||||
switch existingFormat {
|
||||
case "":
|
||||
err = encryptDevice(ctx, volOptions, cr, devicePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to encrypt rbd image %s: %v", imageSpec, err)
|
||||
}
|
||||
case "crypt":
|
||||
klog.Warningf(util.Log(ctx, "rbd image %s is encrypted, but encryption state was not updated"),
|
||||
imageSpec)
|
||||
err = util.SaveRbdImageEncryptionStatus(
|
||||
ctx, cr, volOptions.Monitors, imageSpec, rbdImageEncrypted)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to update encryption state for rbd image %s", imageSpec)
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("can not encrypt rbdImage %s that already has file system: %s",
|
||||
imageSpec, existingFormat)
|
||||
}
|
||||
err = encryptDevice(ctx, volOptions, secrets, cr, devicePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to encrypt rbd image %s: %v", imageSpec, err)
|
||||
}
|
||||
} else if encrypted != rbdImageEncrypted {
|
||||
return "", fmt.Errorf("rbd image %s found mounted with unexpected encryption status %s",
|
||||
imageSpec, encrypted)
|
||||
}
|
||||
|
||||
devicePath, err = openEncryptedDevice(ctx, volOptions, devicePath, secrets)
|
||||
devicePath, err = openEncryptedDevice(ctx, volOptions, devicePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -658,8 +672,8 @@ func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rb
|
||||
return devicePath, nil
|
||||
}
|
||||
|
||||
func encryptDevice(ctx context.Context, rbdVol *rbdVolume, secret map[string]string, cr *util.Credentials, devicePath string) error {
|
||||
passphrase, err := util.GetCryptoPassphrase(secret)
|
||||
func encryptDevice(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials, devicePath string) error {
|
||||
passphrase, err := util.GetCryptoPassphrase(ctx, rbdVol.VolID, rbdVol.KMS)
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "failed to get crypto passphrase for %s/%s: %v"),
|
||||
rbdVol.Pool, rbdVol.RbdImageName, err)
|
||||
@ -678,8 +692,8 @@ func encryptDevice(ctx context.Context, rbdVol *rbdVolume, secret map[string]str
|
||||
return err
|
||||
}
|
||||
|
||||
func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string, secrets map[string]string) (string, error) {
|
||||
passphrase, err := util.GetCryptoPassphrase(secrets)
|
||||
func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string) (string, error) {
|
||||
passphrase, err := util.GetCryptoPassphrase(ctx, volOptions.VolID, volOptions.KMS)
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "failed to get passphrase for encrypted device %s/%s: %v"),
|
||||
volOptions.Pool, volOptions.RbdImageName, err)
|
||||
|
@ -231,7 +231,7 @@ func createPath(ctx context.Context, volOpt *rbdVolume, cr *util.Credentials) (s
|
||||
klog.Warningf(util.Log(ctx, "rbd: map error %v, rbd output: %s"), err, string(output))
|
||||
// unmap rbd image if connection timeout
|
||||
if strings.Contains(err.Error(), rbdMapConnectionTimeout) {
|
||||
detErr := detachRBDImageOrDeviceSpec(ctx, imagePath, true, isNbd, volOpt.VolID)
|
||||
detErr := detachRBDImageOrDeviceSpec(ctx, imagePath, true, isNbd, volOpt.Encrypted, volOpt.VolID)
|
||||
if detErr != nil {
|
||||
klog.Warningf(util.Log(ctx, "rbd: %s unmap error %v"), imagePath, detErr)
|
||||
}
|
||||
@ -266,36 +266,38 @@ func waitForrbdImage(ctx context.Context, backoff wait.Backoff, volOptions *rbdV
|
||||
return err
|
||||
}
|
||||
|
||||
func detachRBDDevice(ctx context.Context, devicePath, volumeID string) error {
|
||||
func detachRBDDevice(ctx context.Context, devicePath, volumeID string, encrypted bool) error {
|
||||
nbdType := false
|
||||
if strings.HasPrefix(devicePath, "/dev/nbd") {
|
||||
nbdType = true
|
||||
}
|
||||
|
||||
return detachRBDImageOrDeviceSpec(ctx, devicePath, false, nbdType, volumeID)
|
||||
return detachRBDImageOrDeviceSpec(ctx, devicePath, false, nbdType, encrypted, volumeID)
|
||||
}
|
||||
|
||||
// detachRBDImageOrDeviceSpec detaches an rbd imageSpec or devicePath, with additional checking
|
||||
// when imageSpec is used to decide if image is already unmapped
|
||||
func detachRBDImageOrDeviceSpec(ctx context.Context, imageOrDeviceSpec string, isImageSpec, ndbType bool, volumeID string) error {
|
||||
func detachRBDImageOrDeviceSpec(ctx context.Context, imageOrDeviceSpec string, isImageSpec, ndbType, encrypted bool, volumeID string) error {
|
||||
var output []byte
|
||||
|
||||
mapperFile, mapperPath := util.VolumeMapper(volumeID)
|
||||
mappedDevice, mapper, err := util.DeviceEncryptionStatus(ctx, mapperPath)
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "error determining LUKS device on %s, %s: %s"),
|
||||
mapperPath, imageOrDeviceSpec, err)
|
||||
return err
|
||||
}
|
||||
if len(mapper) > 0 {
|
||||
// mapper found, so it is open Luks device
|
||||
err = util.CloseEncryptedVolume(ctx, mapperFile)
|
||||
if encrypted {
|
||||
mapperFile, mapperPath := util.VolumeMapper(volumeID)
|
||||
mappedDevice, mapper, err := util.DeviceEncryptionStatus(ctx, mapperPath)
|
||||
if err != nil {
|
||||
klog.Warningf(util.Log(ctx, "error closing LUKS device on %s, %s: %s"),
|
||||
klog.Errorf(util.Log(ctx, "error determining LUKS device on %s, %s: %s"),
|
||||
mapperPath, imageOrDeviceSpec, err)
|
||||
return err
|
||||
}
|
||||
imageOrDeviceSpec = mappedDevice
|
||||
if len(mapper) > 0 {
|
||||
// mapper found, so it is open Luks device
|
||||
err = util.CloseEncryptedVolume(ctx, mapperFile)
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "error closing LUKS device on %s, %s: %s"),
|
||||
mapperPath, imageOrDeviceSpec, err)
|
||||
return err
|
||||
}
|
||||
imageOrDeviceSpec = mappedDevice
|
||||
}
|
||||
}
|
||||
|
||||
accessType := accessTypeKRbd
|
||||
@ -304,7 +306,7 @@ func detachRBDImageOrDeviceSpec(ctx context.Context, imageOrDeviceSpec string, i
|
||||
}
|
||||
options := []string{"unmap", "--device-type", accessType, imageOrDeviceSpec}
|
||||
|
||||
output, err = execCommand(rbd, options)
|
||||
output, err := execCommand(rbd, options)
|
||||
if err != nil {
|
||||
// Messages for krbd and nbd differ, hence checking either of them for missing mapping
|
||||
// This is not applicable when a device path is passed in
|
||||
|
@ -115,7 +115,7 @@ func checkSnapExists(ctx context.Context, rbdSnap *rbdSnapshot, cr *util.Credent
|
||||
}
|
||||
|
||||
snapUUID, err := snapJournal.CheckReservation(ctx, rbdSnap.Monitors, cr, rbdSnap.Pool,
|
||||
rbdSnap.RequestName, rbdSnap.RbdImageName)
|
||||
rbdSnap.RequestName, rbdSnap.RbdImageName, "")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -162,8 +162,12 @@ func checkVolExists(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials
|
||||
return false, err
|
||||
}
|
||||
|
||||
encryptionKmsConfig := ""
|
||||
if rbdVol.Encrypted {
|
||||
encryptionKmsConfig = rbdVol.KMS.KmsConfig()
|
||||
}
|
||||
imageUUID, err := volJournal.CheckReservation(ctx, rbdVol.Monitors, cr, rbdVol.Pool,
|
||||
rbdVol.RequestName, "")
|
||||
rbdVol.RequestName, "", encryptionKmsConfig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -211,7 +215,7 @@ func checkVolExists(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials
|
||||
// volume ID for the generated name
|
||||
func reserveSnap(ctx context.Context, rbdSnap *rbdSnapshot, cr *util.Credentials) error {
|
||||
snapUUID, err := snapJournal.ReserveName(ctx, rbdSnap.Monitors, cr, rbdSnap.Pool,
|
||||
rbdSnap.RequestName, rbdSnap.RbdImageName)
|
||||
rbdSnap.RequestName, rbdSnap.RbdImageName, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -233,8 +237,12 @@ func reserveSnap(ctx context.Context, rbdSnap *rbdSnapshot, cr *util.Credentials
|
||||
// reserveVol is a helper routine to request a rbdVolume name reservation and generate the
|
||||
// volume ID for the generated name
|
||||
func reserveVol(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials) error {
|
||||
encryptionKmsConfig := ""
|
||||
if rbdVol.Encrypted {
|
||||
encryptionKmsConfig = rbdVol.KMS.KmsConfig()
|
||||
}
|
||||
imageUUID, err := volJournal.ReserveName(ctx, rbdVol.Monitors, cr, rbdVol.Pool,
|
||||
rbdVol.RequestName, "")
|
||||
rbdVol.RequestName, "", encryptionKmsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ type rbdVolume struct {
|
||||
VolSize int64 `json:"volSize"`
|
||||
DisableInUseChecks bool `json:"disableInUseChecks"`
|
||||
Encrypted bool
|
||||
KMS util.EncryptionKMS
|
||||
}
|
||||
|
||||
// rbdSnapshot represents a CSI snapshot and its RBD snapshot specifics
|
||||
@ -306,7 +307,7 @@ func genSnapFromSnapID(ctx context.Context, rbdSnap *rbdSnapshot, snapshotID str
|
||||
return err
|
||||
}
|
||||
|
||||
rbdSnap.RequestName, rbdSnap.RbdImageName, err = snapJournal.GetObjectUUIDData(ctx, rbdSnap.Monitors,
|
||||
rbdSnap.RequestName, rbdSnap.RbdImageName, _, err = snapJournal.GetObjectUUIDData(ctx, rbdSnap.Monitors,
|
||||
cr, rbdSnap.Pool, vi.ObjectUUID, true)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -319,7 +320,7 @@ func genSnapFromSnapID(ctx context.Context, rbdSnap *rbdSnapshot, snapshotID str
|
||||
|
||||
// genVolFromVolID generates a rbdVolume structure from the provided identifier, updating
|
||||
// the structure with elements from on-disk image metadata as well
|
||||
func genVolFromVolID(ctx context.Context, rbdVol *rbdVolume, volumeID string, cr *util.Credentials) error {
|
||||
func genVolFromVolID(ctx context.Context, rbdVol *rbdVolume, volumeID string, cr *util.Credentials, secrets map[string]string) error {
|
||||
var (
|
||||
options map[string]string
|
||||
vi util.CSIIdentifier
|
||||
@ -350,11 +351,23 @@ func genVolFromVolID(ctx context.Context, rbdVol *rbdVolume, volumeID string, cr
|
||||
return err
|
||||
}
|
||||
|
||||
rbdVol.RequestName, _, err = volJournal.GetObjectUUIDData(ctx, rbdVol.Monitors, cr,
|
||||
rbdVol.Pool, vi.ObjectUUID, false)
|
||||
kmsConfig := ""
|
||||
rbdVol.RequestName, _, kmsConfig, err = volJournal.GetObjectUUIDData(
|
||||
ctx, rbdVol.Monitors, cr, rbdVol.Pool, vi.ObjectUUID, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if kmsConfig != "" {
|
||||
rbdVol.Encrypted = true
|
||||
kmsOpts, kmsConfigParseErr := util.GetKMSConfig(kmsConfig)
|
||||
if kmsConfigParseErr != nil {
|
||||
return kmsConfigParseErr
|
||||
}
|
||||
rbdVol.KMS, err = util.GetKMS(kmsOpts, secrets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = updateVolWithImageInfo(ctx, rbdVol, cr)
|
||||
|
||||
@ -445,8 +458,9 @@ func updateMons(rbdVol *rbdVolume, options, credentials map[string]string) error
|
||||
|
||||
func genVolFromVolumeOptions(ctx context.Context, volOptions, credentials map[string]string, disableInUseChecks, isLegacyVolume bool) (*rbdVolume, error) {
|
||||
var (
|
||||
ok bool
|
||||
err error
|
||||
ok bool
|
||||
err error
|
||||
encrypted string
|
||||
)
|
||||
|
||||
rbdVol := &rbdVolume{}
|
||||
@ -493,13 +507,20 @@ func genVolFromVolumeOptions(ctx context.Context, volOptions, credentials map[st
|
||||
}
|
||||
|
||||
rbdVol.Encrypted = false
|
||||
encrypted, ok := volOptions["encrypted"]
|
||||
encrypted, ok = volOptions["encrypted"]
|
||||
if ok {
|
||||
rbdVol.Encrypted, err = strconv.ParseBool(encrypted)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"invalid value set in 'encrypted': %s (should be \"true\" or \"false\")", encrypted)
|
||||
}
|
||||
|
||||
if rbdVol.Encrypted {
|
||||
rbdVol.KMS, err = util.GetKMS(volOptions, credentials)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid encryption kms configuration: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rbdVol, nil
|
||||
@ -763,6 +784,7 @@ type rbdImageMetadataStash struct {
|
||||
Pool string `json:"pool"`
|
||||
ImageName string `json:"image"`
|
||||
NbdAccess bool `json:"accessType"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
}
|
||||
|
||||
// file name in which image metadata is stashed
|
||||
@ -772,9 +794,10 @@ const stashFileName = "image-meta.json"
|
||||
// JSON format
|
||||
func stashRBDImageMetadata(volOptions *rbdVolume, path string) error {
|
||||
var imgMeta = rbdImageMetadataStash{
|
||||
Version: 1, // Stash a v1 for now, in case of changes later, there are no checks for this at present
|
||||
Version: 2, // there are no checks for this at present
|
||||
Pool: volOptions.Pool,
|
||||
ImageName: volOptions.RbdImageName,
|
||||
Encrypted: volOptions.Encrypted,
|
||||
}
|
||||
|
||||
imgMeta.NbdAccess = false
|
||||
|
Reference in New Issue
Block a user