HTTPS for stateless overlays and phone-home
CI / agent (push) Successful in 3s
CI / site (push) Successful in 3s
CI / go (push) Failing after 21s

The stateless overlay client (rollcall-overlay in the compute image)
takes rollcall.tls= and rollcall.ca= like the agents: the CA is accepted
only by its fingerprint and the overlay (munge.key and the like) comes
over HTTPS, with no fallback. A deployed OS calls home over HTTPS when
its rack serves it (it trusts the Rollcall CA from first boot).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ilker ManapandClaude Opus 5.5 committed 2026-10-30 07:12:55 +01:00
1 parent 97959af899
commit 179fdcdec5
2 files changed
+33 -3

No files matched your search

+5 -1
View File
@@ -297,7 +297,11 @@ func (a *App) renderSeed(j *Job, sp DeploySpec, token string) []seedFile {
if len(sp.Packages) > 0 { if len(sp.Packages) > 0 {
fmt.Fprintf(&b, "packages: %s\n", yamlList(sp.Packages)) 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 b.WriteString("final_message: \"rollcall: deployed, up after $UPTIME s\"\n") // only $UPTIME/$TIMESTAMP/$DATASOURCE/$VERSION are expanded
ud = b.String() ud = b.String()
} }
@@ -3,13 +3,18 @@
# Fetches this node's overlay tarball from the rollcall server (identified by # 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 # the rollcall.node token on the kernel command line), applies it over / when
# it changed, then runs /run/rollcall/post-<stage>.sh if the overlay shipped one. # it changed, then runs /run/rollcall/post-<stage>.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 set -eu
stage=${1:-system} stage=${1:-system}
SERVER=""; TOKEN="" SERVER=""; TOKEN=""; TLS=""; CA=""
for t in $(cat /proc/cmdline); do for t in $(cat /proc/cmdline); do
case $t in case $t in
rollcall.server=*) SERVER=${t#*=} ;; rollcall.server=*) SERVER=${t#*=} ;;
rollcall.node=*) TOKEN=${t#*=} ;; rollcall.node=*) TOKEN=${t#*=} ;;
rollcall.tls=*) TLS=${t#*=} ;;
rollcall.ca=*) CA=$(echo "${t#*=}" | tr -d ':' | tr 'A-F' 'a-f') ;;
esac esac
done done
if [ -z "$SERVER" ] || [ -z "$TOKEN" ]; then if [ -z "$SERVER" ] || [ -z "$TOKEN" ]; then
@@ -17,9 +22,30 @@ if [ -z "$SERVER" ] || [ -z "$TOKEN" ]; then
exit 0 exit 0
fi fi
mkdir -p /run/rollcall 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 tmp=/run/rollcall/$stage.tar.new
i=0 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 "$SERVER/api/v1/nodes/self/overlay?stage=$stage" -o "$tmp"; do
i=$((i+1)) i=$((i+1))
if [ "$i" -ge 60 ]; then echo "rollcall-overlay: server unreachable" >&2; exit 1; fi if [ "$i" -ge 60 ]; then echo "rollcall-overlay: server unreachable" >&2; exit 1; fi