HTTPS for stateless overlays and phone-home
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:
1 parent
97959af899
commit
179fdcdec5
2 files changed
+33
-3
No files matched your search
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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-<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
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user