feat: bind each node to the binary it runs at its first handshake; refuse changes that are not in a CI-signed manifest [CI]
ci/woodpecker/push/main-amd64-build Pipeline failed
ci/woodpecker/push/main-amd64-build Pipeline failed
This commit is contained in:
1 parent
117d34a2af
commit
4841f7b15b
40 files changed
+1011
-21
No files matched your search
@@ -122,11 +122,11 @@ fetch_offer() {
|
||||
cp "$OFFER_MANIFEST" "$WORK/feed.manifest"; cp "$OFFER_SIG" "$WORK/feed.sig"
|
||||
fi
|
||||
fetch_mailbox
|
||||
# 信箱里没有东西,而仓库里的清单有问题(不是「已经装过」):留下仓库的那份,让后面照常报出验证失败的原因,而不是悄悄当作没有更新
|
||||
case "$feed_error" in
|
||||
""|"stale manifest"*) ;;
|
||||
*) if [ ! -s "$OFFER_MANIFEST" ]; then cp "$WORK/feed.manifest" "$OFFER_MANIFEST"; cp "$WORK/feed.sig" "$OFFER_SIG"; fi ;;
|
||||
esac
|
||||
# 信箱里没有东西,而仓库里的清单没通过(验证失败,或者就是已经装的这一份):留下仓库的那份,让后面照常报出原因,
|
||||
# 而不是悄悄当作没有更新;「已经装的这一份」也要留下,因为要把它交给节点握手时带给 Backend
|
||||
if [ -n "$feed_error" ] && [ ! -s "$OFFER_MANIFEST" ]; then
|
||||
cp "$WORK/feed.manifest" "$OFFER_MANIFEST"; cp "$WORK/feed.sig" "$OFFER_SIG"
|
||||
fi
|
||||
}
|
||||
|
||||
# 把业务进程放的清单和签名复制到临时目录;不是普通文件(缺失、符号链接)就当作没有
|
||||
@@ -165,6 +165,36 @@ write_status() { # state available_json error
|
||||
fi
|
||||
}
|
||||
|
||||
# 节点握手时要带给 Backend 的「我是从哪份 CI 签名清单安装的」:Backend 用 CI 公钥验过,才相信清单里列的官方二进制哈希。
|
||||
# 写在节点只读挂载的状态目录里(节点自己改不了),清单在前、签名在后;内容没变就不写(保护路由器的闪存)。
|
||||
write_installed() {
|
||||
if cmp -s "$OFFER_MANIFEST" "$STATE_DIR/$COMPONENT.installed.manifest" 2>/dev/null && cmp -s "$OFFER_SIG" "$STATE_DIR/$COMPONENT.installed.sig" 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
for pair in "installed.manifest:$OFFER_MANIFEST" "installed.sig:$OFFER_SIG"; do
|
||||
name="${pair%%:*}"; src="${pair#*:}"
|
||||
if [ -n "$DATA_VOLUME" ]; then
|
||||
"$ENGINE" run --pull=never --rm -i --user 0 --network none --read-only --cap-drop ALL --cap-add DAC_OVERRIDE --security-opt no-new-privileges \
|
||||
-v "$STATUS_VOLUME:/status" --entrypoint /bin/sh "$HELPER_IMAGE" \
|
||||
-c 'tmp=$(mktemp /status/.installed.XXXXXX); cat > "$tmp"; chmod 644 "$tmp"; mv -f "$tmp" "/status/$1"' sh "$name" < "$src" || return 0
|
||||
else
|
||||
destination="$(mktemp "$STATUS_DIR/.installed.XXXXXX")"
|
||||
cp "$src" "$destination"
|
||||
chmod 644 "$destination"
|
||||
mv -f "$destination" "$STATUS_DIR/$name"
|
||||
fi
|
||||
done
|
||||
cp "$OFFER_MANIFEST" "$STATE_DIR/$COMPONENT.installed.manifest"
|
||||
cp "$OFFER_SIG" "$STATE_DIR/$COMPONENT.installed.sig"
|
||||
}
|
||||
|
||||
# 第一次部署(deploy-node.sh 已经验过签并按 digest 固定)时还没有安装记录:清单的 digest 就是正在跑的这个镜像,就记下来,不当作「有更新」
|
||||
seed_installed() {
|
||||
[ ! -r "$INSTALLED" ] || return 0
|
||||
running="$(sed -n 's/^IMAGE=.*@\(sha256:[0-9a-f]*\)$/\1/p' "$ENV_FILE" 2>/dev/null | head -n 1)"
|
||||
if [ -n "$running" ] && [ "$running" = "$M_DIGEST" ]; then printf '%s\n%s\n' "$M_SEQ" "$M_DIGEST" > "$INSTALLED"; fi
|
||||
}
|
||||
|
||||
current_digest() { [ -r "$INSTALLED" ] && sed -n 2p "$INSTALLED" || echo ""; }
|
||||
installed_seq() { [ -r "$INSTALLED" ] && sed -n 1p "$INSTALLED" || echo 0; }
|
||||
|
||||
@@ -251,13 +281,19 @@ do_check() {
|
||||
if ! verify_offer; then
|
||||
# 没有新清单,或者清单已经安装过:不算错误,只是没有更新
|
||||
case "$ERR" in
|
||||
"no offer"|"stale manifest"*) write_status up_to_date null "" ;;
|
||||
"no offer") write_status up_to_date null "" ;;
|
||||
"stale manifest"*)
|
||||
# 就是已经装的这一份(同一个 seq、同一个 digest):交给节点握手时带给 Backend
|
||||
if [ "$M_SEQ" = "$(installed_seq)" ] && [ "$M_DIGEST" = "$(current_digest)" ]; then write_installed; fi
|
||||
write_status up_to_date null "" ;;
|
||||
*) write_status invalid null "$ERR"; echo "offer rejected: $ERR" >&2 ;;
|
||||
esac
|
||||
return 0
|
||||
fi
|
||||
adopt_next_key
|
||||
seed_installed
|
||||
if [ "$M_DIGEST" = "$(current_digest)" ]; then
|
||||
write_installed
|
||||
write_status up_to_date null ""
|
||||
return 0
|
||||
fi
|
||||
@@ -303,6 +339,7 @@ do_apply() {
|
||||
fi
|
||||
if [ "$healthy" = true ] && service_ctl is-active --quiet "$UNIT" && [ "$before" = "$after" ]; then
|
||||
printf '%s\n%s\n' "$M_SEQ" "$M_DIGEST" > "$INSTALLED"
|
||||
write_installed
|
||||
write_status up_to_date null ""
|
||||
echo "updated to $M_TAG"
|
||||
return 0
|
||||
|
||||
Reference in new issue
Block a user