From bac52f2cb7b41dfc6b27303391d1b91cc3757c3e Mon Sep 17 00:00:00 2001 From: Seungjae Yoo Date: Mon, 6 Jul 2026 08:00:27 +0000 Subject: [PATCH] podcvd: Support trusted TLS for operator on container instances --- container/debian/control | 3 ++ .../cuttlefish-podcvd.cuttlefish-podcvd.init | 43 +++++++++++++++++++ container/debian/cuttlefish-podcvd.postrm | 11 +++++ container/debian/podcvd-setup | 10 +++++ container/src/podcvd/internal/host.go | 2 + 5 files changed, 69 insertions(+) create mode 100644 container/debian/cuttlefish-podcvd.postrm diff --git a/container/debian/control b/container/debian/control index badde957411..71a56349398 100644 --- a/container/debian/control +++ b/container/debian/control @@ -13,7 +13,10 @@ Architecture: any Depends: acl, adb, android-sdk-platform-tools-common, + ca-certificates, crun, + libnss3-tools, + openssl, podman (>= 4.4), yq, Pre-Depends: ${misc:Pre-Depends} diff --git a/container/debian/cuttlefish-podcvd.cuttlefish-podcvd.init b/container/debian/cuttlefish-podcvd.cuttlefish-podcvd.init index f162391b182..b6745e8471e 100644 --- a/container/debian/cuttlefish-podcvd.cuttlefish-podcvd.init +++ b/container/debian/cuttlefish-podcvd.cuttlefish-podcvd.init @@ -33,6 +33,47 @@ podcvd_cidr=${podcvd_cidr:-192.168.112.0/20} podcvd_ifname="podcvd" +gen_cert() { + local CA_DIR="/etc/cuttlefish-podcvd/ca" + local CERT_DIR="/etc/cuttlefish-podcvd" + mkdir -p "$CA_DIR" "$CERT_DIR" + + # Create Root CA if missing + if [ ! -f "$CA_DIR/podcvd-root-ca.pem" ] || [ ! -f "$CA_DIR/podcvd-root-ca.key" ]; then + openssl req -x509 -new -nodes -keyout "$CA_DIR/podcvd-root-ca.key" -out "$CA_DIR/podcvd-root-ca.pem" \ + -subj "/CN=Podcvd Local Root CA/O=Google Cuttlefish" -days 3650 -sha256 >/dev/null 2>&1 + chmod 644 "$CA_DIR/podcvd-root-ca.pem" + chmod 600 "$CA_DIR/podcvd-root-ca.key" + fi + + # Register Root CA into System Trust Store + if [ -d /usr/local/share/ca-certificates ]; then + ln -sf "$CA_DIR/podcvd-root-ca.pem" /usr/local/share/ca-certificates/podcvd-root-ca.crt + update-ca-certificates >/dev/null 2>&1 || true + fi + + # Generate server certificates + if [ ! -f "$CERT_DIR/cert.pem" ] || [ ! -f "$CERT_DIR/key.pem" ]; then + local ip mask a b c d + IFS='/ ' read -r ip mask <<< "$podcvd_cidr" + IFS='.' read -r a b c d <<< "$ip" + local num_subnets=$(( 2 ** (24 - mask) )) + local start_c=$(( c & ~ (num_subnets - 1) )) + local end_c=$(( start_c + num_subnets - 1 )) + local sans="IP:127.0.0.1" + for ((i=start_c; i<=end_c; i++)); do + sans+=",$(seq -s ",IP:${a}.${b}.${i}." 0 255 | sed "s/^/IP:${a}.${b}.${i}./")" + done + + openssl req -new -nodes -newkey rsa:2048 \ + -keyout "$CERT_DIR/key.pem" -out "$CERT_DIR/cert.pem" \ + -subj "/CN=podcvd-operator" -addext "subjectAltName=$sans" \ + -x509 -CA "$CA_DIR/podcvd-root-ca.pem" -CAkey "$CA_DIR/podcvd-root-ca.key" \ + -days 3650 -sha256 >/dev/null 2>&1 + chmod 644 "$CERT_DIR/cert.pem" "$CERT_DIR/key.pem" + fi +} + start() { modprobe vhost_net || true modprobe vhost_vsock || true @@ -40,6 +81,8 @@ start() { ip link add "${podcvd_ifname}" type dummy ip link set "${podcvd_ifname}" up ip route add local "${podcvd_cidr}" dev "${podcvd_ifname}" + + gen_cert } stop() { diff --git a/container/debian/cuttlefish-podcvd.postrm b/container/debian/cuttlefish-podcvd.postrm new file mode 100644 index 00000000000..2757f278498 --- /dev/null +++ b/container/debian/cuttlefish-podcvd.postrm @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +if [ "$1" = "purge" ]; then + rm -rf /etc/cuttlefish-podcvd + rm -f /usr/local/share/ca-certificates/podcvd-root-ca.crt + update-ca-certificates --fresh >/dev/null 2>&1 || true +fi + +#DEBHELPER# diff --git a/container/debian/podcvd-setup b/container/debian/podcvd-setup index 0870609716f..50294ec0255 100755 --- a/container/debian/podcvd-setup +++ b/container/debian/podcvd-setup @@ -186,6 +186,15 @@ setup_nvidia_gpu() { done } +trust_ca_in_chrome() { + local ca_pem="/etc/cuttlefish-podcvd/ca/podcvd-root-ca.pem" + local user_home=$(eval echo "~$username") + for nss_dir in "$user_home/.pki/nssdb" "$user_home/snap/"*"/current/.pki/nssdb"; do + [ -d "$(dirname "$nss_dir")" ] || continue + sudo -u "$username" certutil -d "sql:$nss_dir" -A -t "TCu,cu,cu" -n "Podcvd Local Root CA" -i "$ca_pem" >/dev/null + done +} + USER_CONFIG="/etc/podcvd.users" username="${1:-${SUDO_USER:-$(id -un)}}" if [ -z "$username" ] || ! id "$username" >/dev/null 2>&1; then @@ -202,5 +211,6 @@ setup_device_permissions setup_rootless_podman # This is working only when both nvidia-smi and nvidia-ctk works fine. setup_nvidia_gpu || echo "Skipping NVIDIA GPU setup." +trust_ca_in_chrome echo "Setup complete! You can now run 'podcvd'." diff --git a/container/src/podcvd/internal/host.go b/container/src/podcvd/internal/host.go index 8895ab06370..9589ad8d217 100644 --- a/container/src/podcvd/internal/host.go +++ b/container/src/podcvd/internal/host.go @@ -213,6 +213,8 @@ func collectMountSpecs(pathsToMount []string, hostOut, productOut, cvdDataHome, bindMap["/root/.local/share/cvd"] = fmt.Sprintf("%s:/root/.local/share/cvd:ro", cvdDataHome) bindMap["/podcvd_home"] = fmt.Sprintf("%s:/podcvd_home:rw", podcvdHomeDir) bindMap["/var/tmp/cvd/0/cache"] = fmt.Sprintf("%s:/var/tmp/cvd/0/cache:rw", cacheDir) + bindMap["/etc/cuttlefish-common/operator/cert/cert.pem"] = "/etc/cuttlefish-podcvd/cert.pem:/etc/cuttlefish-common/operator/cert/cert.pem:ro" + bindMap["/etc/cuttlefish-common/operator/cert/key.pem"] = "/etc/cuttlefish-podcvd/key.pem:/etc/cuttlefish-common/operator/cert/key.pem:ro" for _, p := range pathsToMount { if spec, ok := bindMap[p]; ok { host := strings.SplitN(spec, ":", 2)[0]