Skip to content

Commit 3cd238a

Browse files
authored
feat(e2e): enable mTLS for Podman compute driver (#1430)
* feat(e2e): enable mTLS for Podman compute driver e2e harness The Podman driver already supported mTLS certificate injection into sandbox containers, but the e2e test harness explicitly blocked HTTPS and ran plaintext-only gateways. Generate ephemeral PKI (CA, server, client certs) with host.containers.internal in the server SANs, wire guest_tls_* paths into the TOML config, replace --disable-tls with --tls-cert/--tls-key/--tls-client-ca, and switch to mTLS gateway registration. The health check remains on the plaintext health port. Closes #1428 * refactor(e2e): extract shared PKI generation into gateway-common.sh The Docker and Podman e2e scripts had near-identical 35-line PKI generation blocks differing only in the host-gateway SAN. Extract into e2e_generate_pki(pki_dir, host_alias) in gateway-common.sh, which also eliminates the cd/cd pattern by using absolute paths throughout. * refactor(e2e): use generate-certs instead of raw openssl for PKI Replace the hand-rolled openssl PKI generation in e2e_generate_pki() with the gateway's built-in generate-certs --output-dir command. This uses the same PKI generation as production deployments (Helm and RPM). The helper now takes the gateway binary path and passes extra SANs via --server-san (host.openshell.internal always, plus the driver's host alias for Podman). The default SAN list already includes host.docker.internal and localhost. Update all cert path references to match the generate-certs output layout (server/tls.{crt,key}, client/tls.{crt,key}) and remove the openssl preflight checks from both gateway scripts.
1 parent a54758c commit 3cd238a

4 files changed

Lines changed: 43 additions & 56 deletions

File tree

e2e/rust/e2e-podman.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# Run the Rust e2e suite against a standalone gateway running the bundled Podman
66
# compute driver. Set OPENSHELL_GATEWAY_ENDPOINT=http://host:port to reuse an
7-
# existing plaintext gateway instead of starting an ephemeral one.
7+
# existing gateway instead of starting an ephemeral one.
88

99
set -euo pipefail
1010

e2e/support/gateway-common.sh

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ e2e_pick_port() {
3434
python3 -c 'import socket; s=socket.socket(); s.bind(("",0)); print(s.getsockname()[1]); s.close()'
3535
}
3636

37+
e2e_generate_pki() {
38+
local gateway_bin=$1
39+
local pki_dir=$2
40+
shift 2
41+
# Remaining args are extra --server-san values (e.g. host.containers.internal).
42+
# host.docker.internal and localhost are already in the default SAN list.
43+
44+
local san_args=()
45+
san_args+=(--server-san host.openshell.internal)
46+
for san in "$@"; do
47+
san_args+=(--server-san "${san}")
48+
done
49+
50+
"${gateway_bin}" generate-certs --output-dir "${pki_dir}" "${san_args[@]}"
51+
}
52+
3753
e2e_register_plaintext_gateway() {
3854
local config_home=$1
3955
local name=$2
@@ -63,9 +79,9 @@ e2e_register_mtls_gateway() {
6379
local gateway_config_dir="${config_home}/openshell/gateways/${name}"
6480

6581
mkdir -p "${gateway_config_dir}/mtls"
66-
cp "${pki_dir}/ca.crt" "${gateway_config_dir}/mtls/ca.crt"
67-
cp "${pki_dir}/client.crt" "${gateway_config_dir}/mtls/tls.crt"
68-
cp "${pki_dir}/client.key" "${gateway_config_dir}/mtls/tls.key"
82+
cp "${pki_dir}/ca.crt" "${gateway_config_dir}/mtls/ca.crt"
83+
cp "${pki_dir}/client/tls.crt" "${gateway_config_dir}/mtls/tls.crt"
84+
cp "${pki_dir}/client/tls.key" "${gateway_config_dir}/mtls/tls.key"
6985
cat >"${gateway_config_dir}/metadata.json" <<EOF
7086
{
7187
"name": "${name}",

e2e/with-docker-gateway.sh

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,6 @@ if ! docker info >/dev/null 2>&1; then
234234
echo "ERROR: docker daemon is not reachable (docker info failed)" >&2
235235
exit 2
236236
fi
237-
if ! command -v openssl >/dev/null 2>&1; then
238-
echo "ERROR: openssl is required to generate ephemeral PKI" >&2
239-
exit 2
240-
fi
241237
if [ "${GPU_MODE}" = "1" ]; then
242238
DOCKER_CDI_SPEC_DIRS="$(docker info --format '{{json .CDISpecDirs}}' 2>/dev/null || true)"
243239
if [ -z "${DOCKER_CDI_SPEC_DIRS}" ] \
@@ -390,41 +386,7 @@ if ! docker image inspect "${SANDBOX_IMAGE}" >/dev/null 2>&1; then
390386
fi
391387

392388
PKI_DIR="${WORKDIR}/pki"
393-
mkdir -p "${PKI_DIR}"
394-
cd "${PKI_DIR}"
395-
396-
cat > openssl.cnf <<'EOF'
397-
[req]
398-
distinguished_name = dn
399-
prompt = no
400-
[dn]
401-
CN = openshell-server
402-
[san_server]
403-
subjectAltName = @alt_server
404-
[alt_server]
405-
DNS.1 = localhost
406-
DNS.2 = host.openshell.internal
407-
DNS.3 = host.docker.internal
408-
IP.1 = 127.0.0.1
409-
IP.2 = ::1
410-
[san_client]
411-
subjectAltName = DNS:openshell-client
412-
EOF
413-
414-
openssl req -x509 -newkey rsa:2048 -nodes -days 30 \
415-
-keyout ca.key -out ca.crt -subj "/CN=openshell-e2e-ca" >/dev/null 2>&1
416-
417-
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr \
418-
-config openssl.cnf >/dev/null 2>&1
419-
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
420-
-out server.crt -days 30 -extfile openssl.cnf -extensions san_server >/dev/null 2>&1
421-
422-
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr \
423-
-subj "/CN=openshell-client" >/dev/null 2>&1
424-
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
425-
-out client.crt -days 30 -extfile openssl.cnf -extensions san_client >/dev/null 2>&1
426-
427-
cd "${ROOT}"
389+
e2e_generate_pki "${GATEWAY_BIN}" "${PKI_DIR}"
428390

429391
HOST_PORT=$(e2e_pick_port)
430392
STATE_DIR="${WORKDIR}/state"
@@ -473,8 +435,8 @@ GATEWAY_CONFIG="${STATE_DIR}/gateway.toml"
473435
printf 'default_image = %s\n' "$(toml_string "${SANDBOX_IMAGE}")"
474436
printf 'image_pull_policy = "IfNotPresent"\n'
475437
printf 'guest_tls_ca = %s\n' "$(toml_string "${PKI_DIR}/ca.crt")"
476-
printf 'guest_tls_cert = %s\n' "$(toml_string "${PKI_DIR}/client.crt")"
477-
printf 'guest_tls_key = %s\n' "$(toml_string "${PKI_DIR}/client.key")"
438+
printf 'guest_tls_cert = %s\n' "$(toml_string "${PKI_DIR}/client/tls.crt")"
439+
printf 'guest_tls_key = %s\n' "$(toml_string "${PKI_DIR}/client/tls.key")"
478440
# DOCKER_SUPERVISOR_ARGS holds either ("--docker-supervisor-bin" "<path>")
479441
# or ("--docker-supervisor-image" "<image>"); both map to TOML keys on
480442
# the docker driver config.
@@ -498,8 +460,8 @@ GATEWAY_ARGS=(
498460
--bind-address 0.0.0.0
499461
--port "${HOST_PORT}"
500462
--drivers docker
501-
--tls-cert "${PKI_DIR}/server.crt"
502-
--tls-key "${PKI_DIR}/server.key"
463+
--tls-cert "${PKI_DIR}/server/tls.crt"
464+
--tls-key "${PKI_DIR}/server/tls.key"
503465
--tls-client-ca "${PKI_DIR}/ca.crt"
504466
--db-url "sqlite:${STATE_DIR}/gateway.db?mode=rwc"
505467
)

e2e/with-podman-gateway.sh

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
# - OPENSHELL_GATEWAY_ENDPOINT=http://host:port:
1212
# Use the existing plaintext gateway endpoint and run the command.
1313
#
14-
# Podman e2e currently uses plaintext gateway traffic. The Podman driver does
15-
# not yet inject gateway mTLS client materials into sandbox containers.
14+
# HTTPS endpoint-only mode is intentionally unsupported here. Use a named
15+
# gateway config when mTLS materials are needed.
1616

1717
set -euo pipefail
1818

@@ -277,12 +277,12 @@ if [ -n "${OPENSHELL_GATEWAY_ENDPOINT:-}" ]; then
277277
case "${OPENSHELL_GATEWAY_ENDPOINT}" in
278278
http://*) ;;
279279
https://*)
280-
echo "ERROR: OPENSHELL_GATEWAY_ENDPOINT endpoint mode is HTTP-only for Podman e2e." >&2
281-
echo " Podman e2e does not yet support sandbox mTLS client material injection." >&2
280+
echo "ERROR: OPENSHELL_GATEWAY_ENDPOINT endpoint mode is HTTP-only for e2e." >&2
281+
echo " Register a named gateway with mTLS config instead of using a raw HTTPS endpoint." >&2
282282
exit 2
283283
;;
284284
*)
285-
echo "ERROR: OPENSHELL_GATEWAY_ENDPOINT must start with http:// for Podman e2e endpoint mode." >&2
285+
echo "ERROR: OPENSHELL_GATEWAY_ENDPOINT must start with http:// for e2e endpoint mode." >&2
286286
exit 2
287287
;;
288288
esac
@@ -328,6 +328,9 @@ if ! podman_cmd image exists "${SANDBOX_IMAGE}" 2>/dev/null; then
328328
podman_cmd pull "${SANDBOX_IMAGE}"
329329
fi
330330

331+
PKI_DIR="${WORKDIR}/pki"
332+
e2e_generate_pki "${GATEWAY_BIN}" "${PKI_DIR}" "host.containers.internal"
333+
331334
HOST_PORT=$(e2e_pick_port)
332335
HEALTH_PORT=$(e2e_pick_port)
333336
STATE_DIR="${WORKDIR}/state"
@@ -366,6 +369,9 @@ GATEWAY_CONFIG="${STATE_DIR}/gateway.toml"
366369
printf 'default_image = %s\n' "$(toml_string "${SANDBOX_IMAGE}")"
367370
printf 'image_pull_policy = "missing"\n'
368371
printf 'supervisor_image = %s\n' "$(toml_string "${SUPERVISOR_IMAGE}")"
372+
printf 'guest_tls_ca = %s\n' "$(toml_string "${PKI_DIR}/ca.crt")"
373+
printf 'guest_tls_cert = %s\n' "$(toml_string "${PKI_DIR}/client/tls.crt")"
374+
printf 'guest_tls_key = %s\n' "$(toml_string "${PKI_DIR}/client/tls.key")"
369375
# The in-process Podman driver reads `socket_path` from TOML only — the
370376
# OPENSHELL_PODMAN_SOCKET env var is honoured by the standalone driver
371377
# binary, not the in-process driver used here. Pin the socket to the one
@@ -382,7 +388,9 @@ GATEWAY_ARGS=(
382388
--port "${HOST_PORT}"
383389
--health-port "${HEALTH_PORT}"
384390
--drivers podman
385-
--disable-tls
391+
--tls-cert "${PKI_DIR}/server/tls.crt"
392+
--tls-key "${PKI_DIR}/server/tls.key"
393+
--tls-client-ca "${PKI_DIR}/ca.crt"
386394
--db-url "sqlite:${STATE_DIR}/gateway.db?mode=rwc"
387395
--log-level info
388396
)
@@ -401,12 +409,13 @@ GATEWAY_PID=$!
401409
printf '%s\n' "${GATEWAY_PID}" >"${GATEWAY_PID_FILE}"
402410

403411
GATEWAY_NAME="openshell-e2e-podman-${HOST_PORT}"
404-
CLI_GATEWAY_ENDPOINT="http://127.0.0.1:${HOST_PORT}"
405-
e2e_register_plaintext_gateway \
412+
CLI_GATEWAY_ENDPOINT="https://127.0.0.1:${HOST_PORT}"
413+
e2e_register_mtls_gateway \
406414
"${XDG_CONFIG_HOME}" \
407415
"${GATEWAY_NAME}" \
408416
"${CLI_GATEWAY_ENDPOINT}" \
409-
"${HOST_PORT}"
417+
"${HOST_PORT}" \
418+
"${PKI_DIR}"
410419

411420
export OPENSHELL_GATEWAY="${GATEWAY_NAME}"
412421
export OPENSHELL_PROVISION_TIMEOUT="${OPENSHELL_PROVISION_TIMEOUT:-300}"

0 commit comments

Comments
 (0)