Commit e1068a86 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Ben Walker
Browse files

sma: configure crypto when attaching volumes



Crypto parameters are now checked and crypto is configured when a volume
is attached.  Since configuring crypto can lead to creating new bdevs on
top of the attached volume, each device manager will also need to be
changed to retrieve the bdev through the CryptoEngine.get_crypto_bdev()
interface.  This will be done in subsequent patches.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: Idb5f804cf88aa5e34bbee6817acdb8f3a42a2320
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13870


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatar <sebastian.brzezinka@intel.com>
parent cc3f842c
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ import threading
import uuid
from dataclasses import dataclass
from spdk.rpc.client import JSONRPCException
from . import crypto
from ..common import format_volume_id
from ..proto import sma_pb2

@@ -157,6 +158,40 @@ class VolumeManager:
            raise VolumeException(grpc.StatusCode.INTERNAL,
                                  'Failed to stop discovery')

    def _get_crypto_params(self, params):
        key, cipher, key2 = None, None, None
        try:
            if params.HasField('crypto'):
                key, cipher = params.crypto.key.decode('ascii'), params.crypto.cipher
                if len(params.crypto.key2) > 0:
                    key2 = params.crypto.key2.decode('ascii')
        except UnicodeDecodeError:
            raise VolumeException(grpc.StatusCode.INVALID_ARGUMENT,
                                  'Corrupted crypto key')
        return key, cipher, key2

    def _setup_crypto(self, volume_id, params):
        try:
            if not params.HasField('crypto'):
                return
            key, cipher, key2 = self._get_crypto_params(params)
            crypto.get_crypto_engine().setup(volume_id, key, cipher, key2)
        except crypto.CryptoException as ex:
            raise VolumeException(ex.code, ex.message)

    def _cleanup_crypto(self, volume_id):
        try:
            crypto.get_crypto_engine().cleanup(volume_id)
        except crypto.CryptoException as ex:
            logging.warning(f'Failed to cleanup crypto: {ex.message}')

    def _verify_crypto(self, volume_id, params):
        try:
            key, cipher, key2 = self._get_crypto_params(params)
            crypto.get_crypto_engine().verify(volume_id, key, cipher, key2)
        except crypto.CryptoException as ex:
            raise VolumeException(ex.code, ex.message)

    @_locked
    def connect_volume(self, params, device_handle=None):
        """ Connects a volume through a discovery service.  Returns a tuple (volume_id, existing):
@@ -172,6 +207,8 @@ class VolumeManager:
            if device_handle is not None and volume.device_handle != device_handle:
                raise VolumeException(grpc.StatusCode.ALREADY_EXISTS,
                                      'Volume is already attached to a different device')
            # Make sure the crypto params are the same
            self._verify_crypto(volume_id, params)
            return volume_id, True
        discovery_services = set()
        try:
@@ -218,6 +255,7 @@ class VolumeManager:
                if subnqn != params.nvmf.subnqn:
                    raise VolumeException(grpc.StatusCode.INVALID_ARGUMENT,
                                          'Unexpected subsystem NQN')
            self._setup_crypto(volume_id, params)
            # Finally remember that volume
            self._volumes[volume_id] = Volume(volume_id, device_handle, discovery_services)
        except Exception as ex:
@@ -238,6 +276,7 @@ class VolumeManager:
        volume = self._volumes.get(id)
        if volume is None:
            return
        self._cleanup_crypto(id)
        # Delete the volume from the map and stop the services it uses
        for name in volume.discovery_services:
            try: