Skip to content

Commit 59d9b37

Browse files
authored
Merge pull request #881 from gbregman/devel
Implement inband authentication
2 parents d293976 + 94e96be commit 59d9b37

File tree

12 files changed

+987
-267
lines changed

12 files changed

+987
-267
lines changed

.env

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,15 @@ BDEVPERF_CONTAINER_NAME="${COMPOSE_PROJECT_NAME}-bdevperf-1"
8686
DISC1="${COMPOSE_PROJECT_NAME}-discovery-1"
8787
GW1="${COMPOSE_PROJECT_NAME}-nvmeof-1"
8888
GW2="${COMPOSE_PROJECT_NAME}-nvmeof-2"
89+
90+
# Keys for security tests
91+
PSK_KEY1="NVMeTLSkey-1:01:YzrPElk4OYy1uUERriPwiiyEJE/+J5ckYpLB+5NHMsR2iBuT:" # generated using "nvme gen-tls-key"
92+
PSK_KEY2="NVMeTLSkey-1:01:vUrPe33Auz/sgAAcYctjI0oOOEFM5lheeLy7U+yTsD/LHm9q:"
93+
PSK_KEY3="NVMeTLSkey-1:01:IuIuyghntsi1iX5LdnlRp7MjON1QuYe4hELKYr5VwsL4AgHU:"
94+
95+
DHCHAP_KEY1="DHHC-1:01:rPTE0Q73nd3hEqqEuQNaPL11G/aFXpOHtldWXz9vNCeef4WV:" # generated using "nvme gen-dhchap-key"
96+
DHCHAP_KEY2="DHHC-1:01:x7ecfGgIdOEl+J5cJ9JcZHOS2By2Me6eDJUnrsT9MVrCWRYV:"
97+
DHCHAP_KEY3="DHHC-1:01:eNNXGjidEHHStbUi2Gmpps0JcnofReFfy+NaulguGgt327hz:"
98+
DHCHAP_KEY4="DHHC-1:01:c8D8fVPP/wcuxxRCd8mdQQFjOWtjcS2KmspzvkeOEoF6SUm6:"
99+
DHCHAP_KEY5="DHHC-1:01:zNZ6nrs5JDIpqbH/ZP1VTAATxNf5i/rH44dci+vvjhsyI2ha:"
100+
DHCHAP_KEY6="DHHC-1:01:Bu4tZd7X2oW7XxmVH5tGCdoS30pDX6bZvexHYoudeVlJW9yz:"

.github/workflows/build-container.yml

Lines changed: 9 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ jobs:
133133
strategy:
134134
fail-fast: false
135135
matrix:
136-
test: ["cli", "cli_change_lb", "state", "multi_gateway", "server", "grpc", "omap_lock", "old_omap", "log_files", "nsid", "psk"]
136+
test: ["cli", "cli_change_lb", "state", "multi_gateway", "server", "grpc", "omap_lock", "old_omap", "log_files", "nsid", "psk", "dhchap"]
137137
runs-on: ubuntu-latest
138138
env:
139139
HUGEPAGES: 512 # for multi gateway test, approx 256 per gateway instance
@@ -248,6 +248,10 @@ jobs:
248248
249249
demo:
250250
needs: [build, build-ceph]
251+
strategy:
252+
fail-fast: false
253+
matrix:
254+
security_protocol: ["unsecured", "psk", "dhchap"]
251255
runs-on: ubuntu-latest
252256
env:
253257
HUGEPAGES: 512
@@ -297,155 +301,15 @@ jobs:
297301

298302
- name: Test
299303
run: |
300-
make demo OPTS=-T
301-
302-
- name: List resources
303-
run: |
304-
# https://github.com/actions/toolkit/issues/766
305-
shopt -s expand_aliases
306-
eval $(make alias)
307-
cephnvmf subsystem list
308-
subs=$(cephnvmf --output stdio --format json subsystem list | grep nqn | sed 's/"nqn": "//' | sed 's/",$//')
309-
for sub in $subs
310-
do
311-
cephnvmf namespace list --subsystem $sub
312-
cephnvmf listener list --subsystem $sub
313-
cephnvmf host list --subsystem $sub
314-
done
315-
316-
- name: Run bdevperf
317-
run: |
318-
# see https://spdk.io/doc/nvmf_multipath_howto.html
319-
shopt -s expand_aliases
320-
eval $(make alias)
321-
. .env
322-
set -x
323-
echo -n "ℹ️ Starting bdevperf container"
324-
docker compose up -d bdevperf
325-
sleep 10
326-
echo "ℹ️ bdevperf start up logs"
327-
make logs SVC=bdevperf
328-
eval $(make run SVC=bdevperf OPTS="--entrypoint=env" | grep BDEVPERF_SOCKET | tr -d '\n\r' )
329-
330-
rpc="/usr/libexec/spdk/scripts/rpc.py"
331-
echo "ℹ️ bdevperf bdev_nvme_set_options"
332-
make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_set_options -r -1"
333-
echo "ℹ️ bdevperf tcp connect ip: $NVMEOF_IP_ADDRESS port: $NVMEOF_IO_PORT nqn: $NQN"
334-
make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_attach_controller -b Nvme0 -t tcp -a $NVMEOF_IP_ADDRESS -s $NVMEOF_IO_PORT -f ipv4 -n $NQN -q ${NQN}host -l -1 -o 10"
335-
echo "ℹ️ verify connection list"
336-
conns=$(cephnvmf --output stdio --format json connection list --subsystem $NQN)
337-
echo $conns | grep -q '"status": 0'
338-
echo $conns | grep -q "\"nqn\": \"${NQN}host\""
339-
echo $conns | grep -q "\"trsvcid\": ${NVMEOF_IO_PORT}"
340-
echo $conns | grep -q "\"traddr\": \"${NVMEOF_IP_ADDRESS}\""
341-
echo $conns | grep -q "\"adrfam\": \"ipv4\""
342-
echo $conns | grep -q "\"trtype\": \"TCP\""
343-
con_cnt=$(echo $conns | xargs -n 1 | grep traddr | wc -l)
344-
if [ $con_cnt -ne 1 ]; then
345-
echo "Number of connections ${con_cnt}, expected 1 list: ${conns}"
346-
exit 1
347-
fi
348-
echo $conns | grep -q "\"qpairs_count\": 1"
349-
echo $conns | grep -q "\"connected\": true"
350-
echo "ℹ️ bdevperf perform_tests"
351-
eval $(make run SVC=bdevperf OPTS="--entrypoint=env" | grep BDEVPERF_TEST_DURATION | tr -d '\n\r' )
352-
timeout=$(expr $BDEVPERF_TEST_DURATION \* 2)
353-
bdevperf="/usr/libexec/spdk/scripts/bdevperf.py"
354-
make exec SVC=bdevperf OPTS=-T CMD="$bdevperf -v -t $timeout -s $BDEVPERF_SOCKET perform_tests"
355-
356-
- name: Check coredump existence
357-
if: success() || failure()
358-
id: check_coredumps
359-
uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2, pinned to SHA for security reasons
360-
with:
361-
files: "/tmp/coredump/core.*"
362-
363-
- name: Upload demo core dumps
364-
if: steps.check_coredumps.outputs.files_exists == 'true'
365-
uses: actions/upload-artifact@v4
366-
with:
367-
name: core_demo
368-
path: /tmp/coredump/core.*
369-
370-
# For debugging purposes (provides an SSH connection to the runner)
371-
# - name: Setup tmate session
372-
# uses: mxschmitt/action-tmate@v3
373-
# with:
374-
# limit-access-to-actor: true
375-
376-
- name: Display logs
377-
if: success() || failure()
378-
run: make logs OPTS=''
379-
380-
- name: Tear down
381-
if: success() || failure()
382-
run: |
383-
make down
384-
make clean
385-
386-
demo-secure:
387-
needs: [build, build-ceph]
388-
runs-on: ubuntu-latest
389-
env:
390-
HUGEPAGES: 512
391-
steps:
392-
- name: Checkout code
393-
uses: actions/checkout@v4
394-
395-
- name: Setup huge-pages
396-
run: make setup HUGEPAGES=$HUGEPAGES
397-
398-
- name: Download container images
399-
uses: actions/download-artifact@v4
400-
with:
401-
pattern: container_images*
402-
merge-multiple: true
403-
404-
- name: Load container images
405-
run: |
406-
docker load < nvmeof.tar
407-
docker load < nvmeof-cli.tar
408-
docker load < ceph.tar
409-
docker load < bdevperf.tar
410-
411-
- name: Start containers
412-
timeout-minutes: 3
413-
run: |
414-
make up
415-
416-
- name: Wait for the Gateway to be listening
417-
timeout-minutes: 3
418-
run: |
419-
. .env
420-
421-
echo using gateway $NVMEOF_IP_ADDRESS port $NVMEOF_GW_PORT
422-
until nc -z $NVMEOF_IP_ADDRESS $NVMEOF_GW_PORT; do
423-
echo -n .
424-
sleep ${{ env.WAIT_INTERVAL_SECS }}
425-
done
426-
427-
- name: List containers
428-
if: success() || failure()
429-
run: make ps
430-
431-
- name: List processes
432-
if: success() || failure()
433-
run: make top
434-
435-
- name: Test
436-
run: |
437-
. .env
438-
port2=`expr ${NVMEOF_IO_PORT} + 10`
439-
make demosecure OPTS=-T HOSTNQN="${NQN}host" HOSTNQN2="${NQN}host2" NVMEOF_IO_PORT2=${port2}
304+
./tests/ha/demo_test.sh test_${{ matrix.security_protocol }}
440305
441306
- name: List resources
442307
run: |
443308
# https://github.com/actions/toolkit/issues/766
444309
shopt -s expand_aliases
445310
eval $(make alias)
446-
cephnvmf get_subsystems
447311
cephnvmf subsystem list
448-
subs=$(cephnvmf --output stdio --format json subsystem list | grep nqn | sed 's/"nqn": "//' | sed 's/",$//')
312+
subs=$(cephnvmf --output stdio --format json subsystem list | jq -r '.subsystems[].nqn')
449313
for sub in $subs
450314
do
451315
cephnvmf namespace list --subsystem $sub
@@ -455,70 +319,7 @@ jobs:
455319
456320
- name: Run bdevperf
457321
run: |
458-
# see https://spdk.io/doc/nvmf_multipath_howto.html
459-
shopt -s expand_aliases
460-
eval $(make alias)
461-
. .env
462-
set -x
463-
echo -n "ℹ️ Starting bdevperf container"
464-
docker compose up -d bdevperf
465-
sleep 10
466-
echo "ℹ️ bdevperf start up logs"
467-
make logs SVC=bdevperf
468-
eval $(make run SVC=bdevperf OPTS="--entrypoint=env" | grep BDEVPERF_SOCKET | tr -d '\n\r' )
469-
psk_path_prefix="/tmp/psk/"
470-
psk_path="${psk_path_prefix}${NQN}"
471-
mkdir -p ${psk_path}
472-
echo -n "NVMeTLSkey-1:01:YzrPElk4OYy1uUERriPwiiyEJE/+J5ckYpLB+5NHMsR2iBuT:" > ${psk_path}/${NQN}host
473-
chmod 600 ${psk_path}/${NQN}host
474-
docker cp ${psk_path_prefix} ${BDEVPERF_CONTAINER_NAME}:${psk_path_prefix}
475-
476-
rpc="/usr/libexec/spdk/scripts/rpc.py"
477-
port2=`expr ${NVMEOF_IO_PORT} + 10`
478-
echo "ℹ️ bdevperf bdev_nvme_set_options"
479-
make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_set_options -r -1"
480-
echo "ℹ️ bdevperf tcp connect ip: $NVMEOF_IP_ADDRESS port: $NVMEOF_IO_PORT nqn: $NQN"
481-
make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_attach_controller -b Nvme0 -t tcp -a $NVMEOF_IP_ADDRESS -s $NVMEOF_IO_PORT -f ipv4 -n $NQN -q ${NQN}host -l -1 -o 10 --psk ${psk_path}/${NQN}host"
482-
echo "ℹ️ verify connection list"
483-
conns=$(cephnvmf --output stdio --format json connection list --subsystem $NQN)
484-
echo $conns | grep -q '"status": 0'
485-
echo $conns | grep -q "\"nqn\": \"${NQN}host\""
486-
echo $conns | grep -q "\"trsvcid\": ${NVMEOF_IO_PORT}"
487-
echo $conns | grep -q "\"traddr\": \"${NVMEOF_IP_ADDRESS}\""
488-
echo $conns | grep -q "\"adrfam\": \"ipv4\""
489-
echo $conns | grep -q "\"trtype\": \"TCP\""
490-
echo $conns | grep -q "\"qpairs_count\": 1"
491-
echo $conns | grep -q "\"connected\": true"
492-
echo $conns | grep -q "\"secure\": true"
493-
echo $conns | grep -q -v "\"secure\": false"
494-
echo $conns | grep -q "\"use_psk\": true"
495-
echo $conns | grep -q "\"use_psk\": false"
496-
con_cnt=$(echo $conns | xargs -n 2 | grep traddr | grep -v "n/a" | wc -l)
497-
if [ $con_cnt -ne 1 ]; then
498-
echo "Number of connections ${con_cnt}, expected 1, list: ${conns}"
499-
exit 1
500-
fi
501-
echo "ℹ️ bdevperf tcp connect ip: $NVMEOF_IP_ADDRESS port: ${port2} nqn: ${NQN}host2"
502-
make exec SVC=bdevperf OPTS=-T CMD="$rpc -v -s $BDEVPERF_SOCKET bdev_nvme_attach_controller -b Nvme1 -t tcp -a $NVMEOF_IP_ADDRESS -s ${port2} -f ipv4 -n $NQN -q "${NQN}host2" -l -1 -o 10"
503-
echo "ℹ️ verify connection list again"
504-
conns=$(cephnvmf --output stdio --format json connection list --subsystem $NQN)
505-
con_cnt=$(echo $conns | xargs -n 2 | grep traddr | grep -v "n/a" | wc -l)
506-
if [ $con_cnt -ne 2 ]; then
507-
echo "Number of connections ${con_cnt}, expected 2, list: ${conns}"
508-
exit 1
509-
fi
510-
echo $conns | grep -q "\"nqn\": \"${NQN}host2\""
511-
echo $conns | grep -q "\"trsvcid\": ${port2}"
512-
echo $conns | grep -q "\"secure\": true"
513-
echo $conns | grep -q "\"secure\": false"
514-
echo $conns | grep -q "\"use_psk\": true"
515-
echo $conns | grep -q "\"use_psk\": false"
516-
echo "ℹ️ bdevperf tcp connect ip: $NVMEOF_IP_ADDRESS port: ${port2} nqn: ${NQN}host2"
517-
echo "ℹ️ bdevperf perform_tests"
518-
eval $(make run SVC=bdevperf OPTS="--entrypoint=env" | grep BDEVPERF_TEST_DURATION | tr -d '\n\r' )
519-
timeout=$(expr $BDEVPERF_TEST_DURATION \* 2)
520-
bdevperf="/usr/libexec/spdk/scripts/bdevperf.py"
521-
make exec SVC=bdevperf OPTS=-T CMD="$bdevperf -v -t $timeout -s $BDEVPERF_SOCKET perform_tests"
322+
./tests/ha/demo_test.sh bdevperf_${{ matrix.security_protocol }}
522323
523324
- name: Check coredump existence
524325
if: success() || failure()
@@ -886,7 +687,7 @@ jobs:
886687

887688
push-images-to-ceph-registry:
888689
if: github.event_name == 'release'
889-
needs: [pytest, demo, demo-secure, discovery, ha, atom, build-arm64]
690+
needs: [pytest, demo, discovery, ha, atom, build-arm64]
890691
runs-on: ubuntu-latest
891692

892693
steps:

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[submodule "spdk"]
22
path = spdk
33
url = https://github.com/ceph/spdk.git
4-
branch = ceph-nvmeof-v24.05
4+
branch = ceph-nvmeof-v24.05

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ endif
2121
# Includes
2222
include mk/containerized.mk
2323
include mk/demo.mk
24-
include mk/demosecure.mk
24+
include mk/demosecurepsk.mk
25+
include mk/demosecuredhchap.mk
2526
include mk/misc.mk
2627
include mk/autohelp.mk
2728

control/cli.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,14 +1056,28 @@ def host_add(self, args):
10561056
if args.psk:
10571057
if len(args.host_nqn) > 1:
10581058
self.cli.parser.error(f"Can't have more than one host NQN when PSK keys are used")
1059+
if args.dhchap_key:
1060+
self.cli.parser.error(f"PSK and DH-HMAC-CHAP keys are mutually exclusive")
1061+
1062+
if args.dhchap_key:
1063+
if len(args.host_nqn) > 1:
1064+
self.cli.parser.error(f"Can't have more than one host NQN when DH-HMAC-CHAP keys are used")
1065+
1066+
if args.dhchap_ctrlr_key:
1067+
if not args.dhchap_key:
1068+
self.cli.parser.error(f"DH-HMAC-CHAP controller keys can not be used without DH-HMAC-CHAP keys")
10591069

10601070
for i in range(len(args.host_nqn)):
10611071
one_host_nqn = args.host_nqn[i]
10621072

10631073
if one_host_nqn == "*" and args.psk:
1064-
self.cli.parser.error(f"PSK is only allowed for specific hosts")
1074+
self.cli.parser.error(f"PSK key is only allowed for specific hosts")
1075+
1076+
if one_host_nqn == "*" and args.dhchap_key:
1077+
self.cli.parser.error(f"DH-HMAC-CHAP key is only allowed for specific hosts")
10651078

1066-
req = pb2.add_host_req(subsystem_nqn=args.subsystem, host_nqn=one_host_nqn, psk=args.psk)
1079+
req = pb2.add_host_req(subsystem_nqn=args.subsystem, host_nqn=one_host_nqn,
1080+
psk=args.psk, dhchap_key=args.dhchap_key, dhchap_ctrlr_key=args.dhchap_ctrlr_key)
10671081
try:
10681082
ret = self.stub.add_host(req)
10691083
except Exception as ex:
@@ -1173,14 +1187,15 @@ def host_list(self, args):
11731187
hosts_list.append(["Any host", "n/a"])
11741188
for h in hosts_info.hosts:
11751189
use_psk = "Yes" if h.use_psk else "No"
1176-
hosts_list.append([h.nqn, use_psk])
1190+
use_dhchap = "Yes" if h.use_dhchap else "No"
1191+
hosts_list.append([h.nqn, use_psk, use_dhchap])
11771192
if len(hosts_list) > 0:
11781193
if args.format == "text":
11791194
table_format = "fancy_grid"
11801195
else:
11811196
table_format = "plain"
11821197
hosts_out = tabulate(hosts_list,
1183-
headers = ["Host NQN", "Uses PSK"],
1198+
headers = ["Host NQN", "Uses PSK", "Uses DHCHAP"],
11841199
tablefmt=table_format, stralign="center")
11851200
out_func(f"Hosts allowed to access {args.subsystem}:\n{hosts_out}")
11861201
else:
@@ -1210,7 +1225,9 @@ def host_list(self, args):
12101225
]
12111226
host_add_args = host_common_args + [
12121227
argument("--host-nqn", "-t", help="Host NQN list", nargs="+", required=True),
1213-
argument("--psk", help="Hosts PSK key list", required=False),
1228+
argument("--psk", help="Hosts PSK key", required=False),
1229+
argument("--dhchap-key", help="Host DH-HMAC-CHAP key", required=False),
1230+
argument("--dhchap-ctrlr-key", help="Host DH-HMAC-CHAP controller key", required=False),
12141231
]
12151232
host_del_args = host_common_args + [
12161233
argument("--host-nqn", "-t", help="Host NQN list", nargs="+", required=True),
@@ -1251,6 +1268,7 @@ def connection_list(self, args):
12511268
for conn in connections_info.connections:
12521269
conn_secure = "<n/a>"
12531270
conn_psk = "Yes" if conn.use_psk else "No"
1271+
conn_dhchap = "Yes" if conn.use_dhchap else "No"
12541272
if conn.connected:
12551273
conn_secure = "Yes" if conn.secure else "No"
12561274
connections_list.append([conn.nqn,
@@ -1259,14 +1277,15 @@ def connection_list(self, args):
12591277
conn.qpairs_count if conn.connected else "<n/a>",
12601278
conn.controller_id if conn.connected else "<n/a>",
12611279
conn_secure,
1262-
conn_psk])
1280+
conn_psk,
1281+
conn_dhchap])
12631282
if len(connections_list) > 0:
12641283
if args.format == "text":
12651284
table_format = "fancy_grid"
12661285
else:
12671286
table_format = "plain"
12681287
connections_out = tabulate(connections_list,
1269-
headers = ["Host NQN", "Address", "Connected", "QPairs Count", "Controller ID", "Secure", "PSK"],
1288+
headers = ["Host NQN", "Address", "Connected", "QPairs Count", "Controller ID", "Secure", "Uses\nPSK", "Uses\nDHCHAP"],
12701289
tablefmt=table_format)
12711290
out_func(f"Connections for {args.subsystem}:\n{connections_out}")
12721291
else:

0 commit comments

Comments
 (0)