diff --git a/cmd/rollcall/deploy.go b/cmd/rollcall/deploy.go index 2e098c9..4dfdf4e 100644 --- a/cmd/rollcall/deploy.go +++ b/cmd/rollcall/deploy.go @@ -297,7 +297,11 @@ func (a *App) renderSeed(j *Job, sp DeploySpec, token string) []seedFile { if len(sp.Packages) > 0 { fmt.Fprintf(&b, "packages: %s\n", yamlList(sp.Packages)) } - fmt.Fprintf(&b, "phone_home:\n url: %s/api/v1/phone-home/%s\n post: [instance_id, hostname, fqdn, pub_key_ed25519]\n tries: 10\n", base, token) + home := base + if t := a.agentTLS(base); t != "" && a.ca != nil { + home = t // the deployed OS trusts the Rollcall CA (bootcmd below), so it calls home over HTTPS + } + fmt.Fprintf(&b, "phone_home:\n url: %s/api/v1/phone-home/%s\n post: [instance_id, hostname, fqdn, pub_key_ed25519]\n tries: 10\n", home, token) b.WriteString("final_message: \"rollcall: deployed, up after $UPTIME s\"\n") // only $UPTIME/$TIMESTAMP/$DATASOURCE/$VERSION are expanded ud = b.String() } diff --git a/images/compute-debian13/includes/usr/local/sbin/rollcall-overlay b/images/compute-debian13/includes/usr/local/sbin/rollcall-overlay index fba4d9e..8e6e703 100755 --- a/images/compute-debian13/includes/usr/local/sbin/rollcall-overlay +++ b/images/compute-debian13/includes/usr/local/sbin/rollcall-overlay @@ -3,13 +3,18 @@ # Fetches this node's overlay tarball from the rollcall server (identified by # the rollcall.node token on the kernel command line), applies it over / when # it changed, then runs /run/rollcall/post-.sh if the overlay shipped one. +# With rollcall.tls= and rollcall.ca= on the command line it talks HTTPS: the +# CA certificate is accepted only by that SHA-256, and there is no fallback +# to HTTP (the overlay carries secrets such as munge.key). set -eu stage=${1:-system} -SERVER=""; TOKEN="" +SERVER=""; TOKEN=""; TLS=""; CA="" for t in $(cat /proc/cmdline); do case $t in rollcall.server=*) SERVER=${t#*=} ;; rollcall.node=*) TOKEN=${t#*=} ;; + rollcall.tls=*) TLS=${t#*=} ;; + rollcall.ca=*) CA=$(echo "${t#*=}" | tr -d ':' | tr 'A-F' 'a-f') ;; esac done if [ -z "$SERVER" ] || [ -z "$TOKEN" ]; then @@ -17,9 +22,30 @@ if [ -z "$SERVER" ] || [ -z "$TOKEN" ]; then exit 0 fi mkdir -p /run/rollcall +CURL_CA="" +if [ -n "$TLS" ] && [ -n "$CA" ]; then + cafile=/run/rollcall/ca.pem + if [ ! -s "$cafile" ]; then + i=0 + until curl -fsS --connect-timeout 5 "$SERVER/ca.pem" -o "$cafile.new"; do + i=$((i+1)); [ "$i" -ge 30 ] && { echo "rollcall-overlay: cannot fetch the CA certificate" >&2; exit 1; } + sleep 5 + done + got=$(openssl x509 -in "$cafile.new" -outform DER | sha256sum | cut -d' ' -f1) + if [ "$got" != "$CA" ]; then + rm -f "$cafile.new" + echo "rollcall-overlay: the CA certificate does not match rollcall.ca; not fetching the overlay" >&2 + exit 1 + fi + mv -f "$cafile.new" "$cafile" + fi + SERVER=$TLS + CURL_CA="--cacert $cafile" +fi tmp=/run/rollcall/$stage.tar.new i=0 -until curl -fsS --connect-timeout 5 -H "X-Rollcall-Node: $TOKEN" \ +# shellcheck disable=SC2086 # CURL_CA is two words or none +until curl -fsS --connect-timeout 5 $CURL_CA -H "X-Rollcall-Node: $TOKEN" \ "$SERVER/api/v1/nodes/self/overlay?stage=$stage" -o "$tmp"; do i=$((i+1)) if [ "$i" -ge 60 ]; then echo "rollcall-overlay: server unreachable" >&2; exit 1; fi