diff --git a/control/cli.py b/control/cli.py index f56d3286..8af7bb25 100644 --- a/control/cli.py +++ b/control/cli.py @@ -1056,8 +1056,6 @@ def host_add(self, args): if args.psk: if len(args.host_nqn) > 1: self.cli.parser.error(f"Can't have more than one host NQN when PSK keys are used") - if args.dhchap_key: - self.cli.parser.error(f"PSK and DH-HMAC-CHAP keys are mutually exclusive") if args.dhchap_key: if len(args.host_nqn) > 1: diff --git a/control/grpc.py b/control/grpc.py index d5eed853..544b52d6 100644 --- a/control/grpc.py +++ b/control/grpc.py @@ -2320,11 +2320,6 @@ def add_host_safe(self, request, context): self.logger.error(f"{errmsg}") return pb2.req_status(status=errno.EINVAL, error_message=errmsg) - if request.psk and request.dhchap_key: - errmsg=f"{host_failure_prefix}: PSK and DH-HMAC-CHAP keys are mutually exclusive" - self.logger.error(f"{errmsg}") - return pb2.req_status(status=errno.EINVAL, error_message=errmsg) - host_already_exist = self.matching_host_exists(context, request.subsystem_nqn, request.host_nqn) if host_already_exist: if request.host_nqn == "*": diff --git a/mk/demosecuredhchap.mk b/mk/demosecuredhchap.mk index 6d9f3298..862c47c6 100644 --- a/mk/demosecuredhchap.mk +++ b/mk/demosecuredhchap.mk @@ -3,11 +3,15 @@ HOSTNQN=`cat /etc/nvme/hostnqn` HOSTNQN2=`cat /etc/nvme/hostnqn | sed 's/......$$/ffffff/'` HOSTNQN3=`cat /etc/nvme/hostnqn | sed 's/......$$/fffffe/'` +HOSTNQN4=`cat /etc/nvme/hostnqn | sed 's/......$$/fffffd/'` NVMEOF_IO_PORT2=`expr $(NVMEOF_IO_PORT) + 1` NVMEOF_IO_PORT3=`expr $(NVMEOF_IO_PORT) + 2` +NVMEOF_IO_PORT4=`expr $(NVMEOF_IO_PORT) + 3` DHCHAPKEY1=$(DHCHAP_KEY1) DHCHAPKEY2=$(DHCHAP_KEY2) DHCHAPKEY3=$(DHCHAP_KEY3) +DHCHAPKEY4=$(DHCHAP_KEY4) +PSKKEY1=$(PSK_KEY1) # demosecuredhchap demosecuredhchap: $(NVMEOF_CLI) subsystem add --subsystem $(NQN) --no-group-append @@ -16,9 +20,11 @@ demosecuredhchap: $(NVMEOF_CLI) listener add --subsystem $(NQN) --host-name `docker ps -q -f name=$(NVMEOF_CONTAINER_NAME)` --traddr $(NVMEOF_IP_ADDRESS) --trsvcid $(NVMEOF_IO_PORT) $(NVMEOF_CLI) listener add --subsystem $(NQN) --host-name `docker ps -q -f name=$(NVMEOF_CONTAINER_NAME)` --traddr $(NVMEOF_IP_ADDRESS) --trsvcid $(NVMEOF_IO_PORT2) $(NVMEOF_CLI) listener add --subsystem $(NQN) --host-name `docker ps -q -f name=$(NVMEOF_CONTAINER_NAME)` --traddr $(NVMEOF_IP_ADDRESS) --trsvcid $(NVMEOF_IO_PORT3) + $(NVMEOF_CLI) listener add --subsystem $(NQN) --host-name `docker ps -q -f name=$(NVMEOF_CONTAINER_NAME)` --traddr $(NVMEOF_IP_ADDRESS) --trsvcid $(NVMEOF_IO_PORT4) --secure $(NVMEOF_CLI) host add --subsystem $(NQN) --host-nqn $(HOSTNQN) --dhchap-key $(DHCHAPKEY1) $(NVMEOF_CLI) host add --subsystem $(NQN) --host-nqn $(HOSTNQN2) --dhchap-key $(DHCHAPKEY2) --dhchap-ctrlr-key $(DHCHAPKEY3) $(NVMEOF_CLI) host add --subsystem $(NQN) --host-nqn $(HOSTNQN3) $(NVMEOF_CLI) namespace add_host --subsystem $(NQN) --nsid 2 --host-nqn $(HOSTNQN) + $(NVMEOF_CLI) host add --subsystem $(NQN) --host-nqn $(HOSTNQN4) --dhchap-key $(DHCHAPKEY4) --psk $(PSKKEY1) .PHONY: demosecuredhchap diff --git a/tests/ha/demo_test.sh b/tests/ha/demo_test.sh index dd5feb1d..90fd2531 100755 --- a/tests/ha/demo_test.sh +++ b/tests/ha/demo_test.sh @@ -46,12 +46,16 @@ function demo_test_dhchap() echo -n "${DHCHAP_KEY5}" > /tmp/temp-dhchap/dhchap/${NQN}/key2 echo -n "${DHCHAP_KEY6}" > /tmp/temp-dhchap/dhchap/${NQN}/key3 echo -n "${DHCHAP_KEY7}" > /tmp/temp-dhchap/dhchap/${NQN}/key4 + echo -n "${DHCHAP_KEY8}" > /tmp/temp-dhchap/dhchap/${NQN}/key5 + echo -n "${PSK_KEY1}" > /tmp/temp-dhchap/dhchap/${NQN}/key6 chmod 0600 /tmp/temp-dhchap/dhchap/${NQN}/key1 chmod 0600 /tmp/temp-dhchap/dhchap/${NQN}/key2 chmod 0600 /tmp/temp-dhchap/dhchap/${NQN}/key3 chmod 0600 /tmp/temp-dhchap/dhchap/${NQN}/key4 + chmod 0600 /tmp/temp-dhchap/dhchap/${NQN}/key5 + chmod 0600 /tmp/temp-dhchap/dhchap/${NQN}/key6 - make demosecuredhchap OPTS=-T HOSTNQN="${NQN}host" HOSTNQN2="${NQN}host2" HOSTNQN3="${NQN}host3" NVMEOF_IO_PORT2=${port2} NVMEOF_IO_PORT3=${port3} DHCHAPKEY1="${DHCHAP_KEY4}" DHCHAPKEY2="${DHCHAP_KEY5}" DHCHAPKEY3="${DHCHAP_KEY6}" + make demosecuredhchap OPTS=-T HOSTNQN="${NQN}host" HOSTNQN2="${NQN}host2" HOSTNQN3="${NQN}host3" HOSTNQN4="${NQN}host4" NVMEOF_IO_PORT2=${port2} NVMEOF_IO_PORT3=${port3} NVMEOF_IO_PORT4=${port4} DHCHAPKEY1="${DHCHAP_KEY4}" DHCHAPKEY2="${DHCHAP_KEY5}" DHCHAPKEY3="${DHCHAP_KEY6}" DHCHAPKEY4="${DHCHAP_KEY8}" PSKKEY1="${PSK_KEY1}" } function demo_bdevperf_unsecured() @@ -321,6 +325,8 @@ function demo_bdevperf_dhchap() make exec SVC=bdevperf OPTS=-T CMD="chmod 0600 ${dhchap_path}/key2" make exec SVC=bdevperf OPTS=-T CMD="chmod 0600 ${dhchap_path}/key3" make exec SVC=bdevperf OPTS=-T CMD="chmod 0600 ${dhchap_path}/key4" + make exec SVC=bdevperf OPTS=-T CMD="chmod 0600 ${dhchap_path}/key5" + make exec SVC=bdevperf OPTS=-T CMD="chmod 0600 ${dhchap_path}/key6" rm -rf /tmp/temp-dhchap echo "ℹ️ bdevperf add DHCHAP key name key1 to keyring" @@ -331,6 +337,10 @@ function demo_bdevperf_dhchap() make -s exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET keyring_file_add_key key3 ${dhchap_path}/key3" echo "ℹ️ bdevperf add DHCHAP key name key4 to keyring" make -s exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET keyring_file_add_key key4 ${dhchap_path}/key4" + echo "ℹ️ bdevperf add DHCHAP key name key5 to keyring" + make -s exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET keyring_file_add_key key5 ${dhchap_path}/key5" + echo "ℹ️ bdevperf add DHCHAP key name key6 to keyring" + make -s exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET keyring_file_add_key key6 ${dhchap_path}/key6" echo "ℹ️ bdevperf list keyring" make -s exec SVC=bdevperf OPTS=-T CMD="$rpc -s $BDEVPERF_SOCKET keyring_get_keys" @@ -414,7 +424,18 @@ function demo_bdevperf_dhchap() [[ `echo $conns | jq -r '.connections[2].use_psk'` == "false" ]] [[ `echo $conns | jq -r '.connections[2].use_dhchap'` == "false" ]] - [[ `echo $conns | jq -r '.connections[3]'` == "null" ]] + [[ `echo $conns | jq -r '.connections[3].nqn'` == "${NQN}host4" ]] + [[ `echo $conns | jq -r '.connections[3].trsvcid'` == 0 ]] + [[ `echo $conns | jq -r '.connections[3].traddr'` == "" ]] + [[ `echo $conns | jq -r '.connections[3].adrfam'` == "ipv4" ]] + [[ `echo $conns | jq -r '.connections[3].trtype'` == "" ]] + [[ `echo $conns | jq -r '.connections[3].qpairs_count'` == -1 ]] + [[ `echo $conns | jq -r '.connections[3].controller_id'` == -1 ]] + [[ `echo $conns | jq -r '.connections[3].connected'` == "false" ]] + [[ `echo $conns | jq -r '.connections[3].use_psk'` == "true" ]] + [[ `echo $conns | jq -r '.connections[3].use_dhchap'` == "true" ]] + + [[ `echo $conns | jq -r '.connections[4]'` == "null" ]] echo "ℹ️ bdevperf perform_tests" eval $(make run SVC=bdevperf OPTS="--entrypoint=env" | grep BDEVPERF_TEST_DURATION | tr -d '\n\r' ) @@ -458,6 +479,24 @@ function demo_bdevperf_dhchap() make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_attach_controller -b Nvme5 -t tcp -a $NVMEOF_IP_ADDRESS -s ${NVMEOF_IO_PORT} -f ipv4 -n ${NQN} -q ${NQN}host -l -1 -o 10 --dhchap-key key4" make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_detach_controller Nvme5" + echo "ℹ️ bdevperf tcp connect ip: $NVMEOF_IP_ADDRESS port: ${port4} nqn: ${NQN}host4 using no PSK key" + set +e + make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_attach_controller -b Nvme6 -t tcp -a $NVMEOF_IP_ADDRESS -s ${port4} -f ipv4 -n ${NQN} -q ${NQN}host4 -l -1 -o 10 --dhchap-key key5" + if [[ $? -eq 0 ]]; then + echo "Connecting using no PSK key should fail" + exit 1 + fi + set -e + + echo "ℹ️ bdevperf tcp connect ip: $NVMEOF_IP_ADDRESS port: ${port4} nqn: ${NQN}host4 using PSK key" + make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_attach_controller -b Nvme6 -t tcp -a $NVMEOF_IP_ADDRESS -s ${port4} -f ipv4 -n ${NQN} -q ${NQN}host4 -l -1 -o 10 --dhchap-key key5 --psk key6" + + echo "ℹ️ verify connection list with PSK" + conns=`cephnvmf_func --output stdio --format json connection list --subsystem $NQN` + + [[ `echo $conns | jq -r '.status'` == "0" ]] + [[ `echo $conns | jq -r '.subsystem_nqn'` == "${NQN}" ]] + echo "ℹ️ verify DHCHAP key files removal" dhchap_key_list=`make -s exec SVC=nvmeof OPTS=-T CMD="/usr/local/bin/spdk_rpc -s /var/tmp/spdk.sock keyring_get_keys"` path1=`echo ${dhchap_key_list} | jq -r '.[0].path'` @@ -508,6 +547,7 @@ set -x rpc="/usr/libexec/spdk/scripts/rpc.py" port2=`expr ${NVMEOF_IO_PORT} + 10` port3=`expr ${NVMEOF_IO_PORT} + 20` +port4=`expr ${NVMEOF_IO_PORT} + 30` case "$1" in test_unsecured) demo_test_unsecured diff --git a/tests/test_psk.py b/tests/test_psk.py index fc8ed64f..31c7a99f 100644 --- a/tests/test_psk.py +++ b/tests/test_psk.py @@ -31,6 +31,8 @@ hostpsk3 = "junk" hostpsk4 = "NVMeTLSkey-1:01:YzrPElk4OYy1uUERriPwiiyEJE/+J5ckYpLB+5NHMsR2iBuT:" +hostdhchap1 = "DHHC-1:00:MWPqcx1Ug1debg8fPIGpkqbQhLcYUt39k7UWirkblaKEH1kE:" + host_name = socket.gethostname() addr = "127.0.0.1" config = "ceph-nvmeof.conf" @@ -69,17 +71,13 @@ def test_setup(caplog, gateway): cli(["namespace", "add", "--subsystem", subsystem, "--rbd-pool", pool, "--rbd-image", image, "--rbd-create-image", "--size", "16MB"]) assert f"Adding namespace 1 to {subsystem}: Successful" in caplog.text -def test_allow_any_host(caplog, gateway): +def test_create_secure_with_any_host(caplog, gateway): caplog.clear() cli(["host", "add", "--subsystem", subsystem, "--host-nqn", "*"]) assert f"Allowing open host access to {subsystem}: Successful" in caplog.text - -def test_create_secure_with_any_host(caplog, gateway): caplog.clear() cli(["listener", "add", "--subsystem", subsystem, "--host-name", host_name, "-a", addr, "-s", "5001", "--secure"]) assert f"Secure channel is only allowed for subsystems in which \"allow any host\" is off" in caplog.text - -def test_remove_any_host_access(caplog, gateway): caplog.clear() cli(["host", "del", "--subsystem", subsystem, "--host-nqn", "*"]) assert f"Disabling open host access to {subsystem}: Successful" in caplog.text @@ -174,14 +172,8 @@ def test_allow_any_host_with_psk(caplog, gateway): def test_psk_with_dhchap(caplog, gateway): caplog.clear() - rc = 0 - try: - cli(["host", "add", "--subsystem", subsystem, "--host-nqn", hostnqn10, "--psk", hostpsk1, "--dhchap-key", "junk"]) - except SystemExit as sysex: - rc = int(str(sysex)) - pass - assert rc == 2 - assert f"error: PSK and DH-HMAC-CHAP keys are mutually exclusive" in caplog.text + cli(["host", "add", "--subsystem", subsystem, "--host-nqn", hostnqn10, "--psk", hostpsk1, "--dhchap-key", hostdhchap1]) + assert f"Adding host {hostnqn10} to {subsystem}: Successful" in caplog.text def test_list_listeners(caplog, gateway): caplog.clear()