Skip to content

Commit

Permalink
Encrypt keys before saving in OMAP file.
Browse files Browse the repository at this point in the history
Fixes ceph#960

Signed-off-by: Gil Bregman <[email protected]>
  • Loading branch information
gbregman committed Nov 25, 2024
1 parent 7b48f21 commit dfaf1ca
Show file tree
Hide file tree
Showing 15 changed files with 552 additions and 291 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ DHCHAP_KEY6="DHHC-1:01:Bu4tZd7X2oW7XxmVH5tGCdoS30pDX6bZvexHYoudeVlJW9yz:"
DHCHAP_KEY7="DHHC-1:01:JPJkDQ2po2FfLmKYlTF/sJ2HzVO/FKWxgXKE/H6XfL8ogQ1T:"
DHCHAP_KEY8="DHHC-1:01:e0B0vDxKleDzYVtG42xqFvoWZfiufkoywmfRKrETzayRdf1j:"
DHCHAP_KEY9="DHHC-1:01:KD+sfH3/o2bRQoV0ESjBUywQlMnSaYpZISUbVa0k0nsWpNST:"
DHCHAP_KEY10="DHHC-1:00:rWf0ZFYO7IgWGttM8w6jUrAY4cTQyqyXPdmxHeOSve3w5QU9:"
DHCHAP_KEY11="DHHC-1:02:j3uUz05r5aQy42vX4tDXqVf9HgUPPdEp3kXTgUWl9EphsG7jwpr9KSIt3bmRLXBijPTIDQ==:"
3 changes: 2 additions & 1 deletion ceph-nvmeof.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ state_update_notify = True
state_update_timeout_in_msec = 2000
state_update_interval_sec = 5
enable_spdk_discovery_controller = False
enable_key_encryption = True
#omap_file_lock_duration = 20
#omap_file_lock_retries = 30
#omap_file_lock_retry_sleep_interval = 1.0
Expand All @@ -29,7 +30,7 @@ enable_spdk_discovery_controller = False
#verify_nqns = True
#allowed_consecutive_spdk_ping_failures = 1
#spdk_ping_interval_in_seconds = 2.0
#max_hosts_per_namespace = 1
#max_hosts_per_namespace = 8
#max_namespaces_with_netmask = 1000
#max_subsystems = 128
#max_namespaces = 1024
Expand Down
37 changes: 31 additions & 6 deletions control/grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from .config import GatewayConfig
from .utils import GatewayEnumUtils
from .utils import GatewayUtils
from .utils import GatewayUtilsCrypto
from .utils import GatewayLogger
from .state import GatewayState, GatewayStateHandler, OmapLock
from .cephutils import CephUtils
Expand Down Expand Up @@ -324,13 +325,14 @@ def __init__(self, config: GatewayConfig, gateway_state: GatewayStateHandler, rp
self.host_name = socket.gethostname()
self.verify_nqns = self.config.getboolean_with_default("gateway", "verify_nqns", True)
self.gateway_group = self.config.get_with_default("gateway", "group", "")
self.max_hosts_per_namespace = self.config.getint_with_default("gateway", "max_hosts_per_namespace", 1)
self.max_hosts_per_namespace = self.config.getint_with_default("gateway", "max_hosts_per_namespace", 8)
self.max_namespaces_with_netmask = self.config.getint_with_default("gateway", "max_namespaces_with_netmask", 1000)
self.max_subsystems = self.config.getint_with_default("gateway", "max_subsystems", GatewayService.MAX_SUBSYSTEMS_DEFAULT)
self.max_namespaces = self.config.getint_with_default("gateway", "max_namespaces", GatewayService.MAX_NAMESPACES_DEFAULT)
self.max_namespaces_per_subsystem = self.config.getint_with_default("gateway", "max_namespaces_per_subsystem", GatewayService.MAX_NAMESPACES_PER_SUBSYSTEM_DEFAULT)
self.max_hosts_per_subsystem = self.config.getint_with_default("gateway", "max_hosts_per_subsystem", GatewayService.MAX_HOSTS_PER_SUBSYS_DEFAULT)
self.gateway_pool = self.config.get_with_default("ceph", "pool", "")
self.enable_key_encryption = self.config.getboolean_with_default("gateway", "enable_key_encryption", True)
self.ana_map = defaultdict(dict)
self.cluster_nonce = {}
self.bdev_cluster = {}
Expand Down Expand Up @@ -672,6 +674,7 @@ def create_bdev(self, anagrp: int, name, uuid, rbd_pool_name, rbd_image_name, bl
self.logger.exception(errmsg)
return BdevStatus(status=errcode, error_message=f"Failure creating bdev {name}: {errmsg}")

cluster_name = None
try:
cluster_name=self._get_cluster(anagrp)
bdev_name = rpc_bdev.bdev_rbd_create(
Expand All @@ -689,7 +692,8 @@ def create_bdev(self, anagrp: int, name, uuid, rbd_pool_name, rbd_image_name, bl

self.logger.debug(f"bdev_rbd_create: {bdev_name}, cluster_name {cluster_name}")
except Exception as ex:
self._put_cluster(cluster_name)
if cluster_name != None:
self._put_cluster(cluster_name)
errmsg = f"bdev_rbd_create {name} failed"
self.logger.exception(errmsg)
errmsg = f"{errmsg} with:\n{ex}"
Expand Down Expand Up @@ -978,6 +982,10 @@ def create_subsystem_safe(self, request, context):
if context:
# Update gateway state
try:
request.encrypted_dhchap_key = b""
if self.enable_key_encryption and request.dhchap_key:
request.encrypted_dhchap_key = GatewayUtilsCrypto.encrypt_text(request.dhchap_key)
request.dhchap_key = ""
json_req = json_format.MessageToJson(
request, preserving_proto_field_name=True, including_default_value_fields=True)
self.gateway_state.add_subsystem(request.subsystem_nqn, json_req)
Expand Down Expand Up @@ -2547,6 +2555,13 @@ def add_host_safe(self, request, context):
if context:
# Update gateway state
try:
if self.enable_key_encryption:
if request.dhchap_key:
request.encrypted_dhchap_key = GatewayUtilsCrypto.encrypt_text(request.dhchap_key)
request.dhchap_key = ""
if request.psk:
request.encrypted_psk = GatewayUtilsCrypto.encrypt_text(request.psk)
request.psk = ""
json_req = json_format.MessageToJson(
request, preserving_proto_field_name=True, including_default_value_fields=True)
self.gateway_state.add_host(request.subsystem_nqn, request.host_nqn, json_req)
Expand Down Expand Up @@ -2793,12 +2808,17 @@ def change_host_key_safe(self, request, context):
if context:
# Update gateway state
try:
encrypted_dhchap_key = b""
if self.enable_key_encryption and request.dhchap_key:
encrypted_dhchap_key = GatewayUtilsCrypto.encrypt_text(request.dhchap_key)
request.dhchap_key = ""
add_req = pb2.add_host_req(subsystem_nqn=request.subsystem_nqn,
host_nqn=request.host_nqn,
psk=host_psk,
dhchap_key=request.dhchap_key)
dhchap_key=request.dhchap_key,
encrypted_dhchap_key=encrypted_dhchap_key)
json_req = json_format.MessageToJson(
add_req, preserving_proto_field_name=True, including_default_value_fields=True)
add_req, preserving_proto_field_name=True, including_default_value_fields=True)
self.gateway_state.add_host(request.subsystem_nqn, request.host_nqn, json_req)
except Exception as ex:
errmsg = f"Error persisting host change key for host {request.host_nqn} in {request.subsystem_nqn}"
Expand Down Expand Up @@ -3501,12 +3521,18 @@ def change_subsystem_key_safe(self, request, context):

assert subsys_entry, f"Can't find entry for subsystem {request.subsystem_nqn}"
try:
dhchap_key = request.dhchap_key
encrypted_dhchap_key = b""
if self.enable_key_encryption and request.dhchap_key:
encrypted_dhchap_key = GatewayUtilsCrypto.encrypt_text(request.dhchap_key)
dhchap_key = ""
create_req = pb2.create_subsystem_req(subsystem_nqn=request.subsystem_nqn,
serial_number=subsys_entry["serial_number"],
max_namespaces=subsys_entry["max_namespaces"],
enable_ha=subsys_entry["enable_ha"],
no_group_append=subsys_entry["no_group_append"],
dhchap_key=request.dhchap_key)
dhchap_key=dhchap_key,
encrypted_dhchap_key=encrypted_dhchap_key)
json_req = json_format.MessageToJson(
create_req, preserving_proto_field_name=True, including_default_value_fields=True)
self.gateway_state.add_subsystem(request.subsystem_nqn, json_req)
Expand All @@ -3532,7 +3558,6 @@ def change_subsystem_key_safe(self, request, context):
except Excpetion:
pass


return pb2.req_status(status=0, error_message=os.strerror(0))

def change_subsystem_key(self, request, context=None):
Expand Down
3 changes: 3 additions & 0 deletions control/proto/gateway.proto
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ message create_subsystem_req {
bool enable_ha = 4;
optional bool no_group_append = 5;
optional string dhchap_key = 6;
optional bytes encrypted_dhchap_key = 7;
}

message delete_subsystem_req {
Expand All @@ -215,6 +216,8 @@ message add_host_req {
string host_nqn = 2;
optional string psk = 3;
optional string dhchap_key = 4;
optional bytes encrypted_psk = 5;
optional bytes encrypted_dhchap_key = 6;
}

message change_host_key_req {
Expand Down
10 changes: 10 additions & 0 deletions control/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from .config import GatewayConfig
from .utils import GatewayLogger
from .utils import GatewayUtils
from .utils import GatewayUtilsCrypto
from .cephutils import CephUtils
from .prometheus import start_exporter

Expand Down Expand Up @@ -764,6 +765,9 @@ def gateway_rpc_caller(self, requests, is_add_req):
if key.startswith(GatewayState.SUBSYSTEM_PREFIX):
if is_add_req:
req = json_format.Parse(val, pb2.create_subsystem_req(), ignore_unknown_fields=True)
if req.encrypted_dhchap_key:
req.dhchap_key = GatewayUtilsCrypto.decrypt_text(req.encrypted_dhchap_key)
req.encrypted_dhchap_key = b""
self.gateway_rpc.create_subsystem(req)
else:
req = json_format.Parse(val,
Expand All @@ -789,6 +793,12 @@ def gateway_rpc_caller(self, requests, is_add_req):
elif key.startswith(GatewayState.HOST_PREFIX):
if is_add_req:
req = json_format.Parse(val, pb2.add_host_req(), ignore_unknown_fields=True)
if req.encrypted_dhchap_key:
req.dhchap_key = GatewayUtilsCrypto.decrypt_text(req.encrypted_dhchap_key)
req.encrypted_dhchap_key = b""
if req.encrypted_psk:
req.psk = GatewayUtilsCrypto.decrypt_text(req.encrypted_psk)
req.encrypted_psk = b""
self.gateway_rpc.add_host(req)
else:
req = json_format.Parse(val, pb2.remove_host_req(), ignore_unknown_fields=True)
Expand Down
Loading

0 comments on commit dfaf1ca

Please sign in to comment.