fix(rotate-token): 加确认步骤、velocity 热加载免踢人,补齐 registry/forwarding/db 轮换
This commit is contained in:
16 files changed
+1568
-195
No files matched your search
+12
-5
@@ -3859,13 +3859,20 @@ EOF
|
||||
# velocity_fingerprint hashes what the proxy process runs: its unit (JVM flags and system
|
||||
# properties), the JRE, the jars and the files the installer writes for it. The Via config
|
||||
# and whatever else plugins write at runtime stay out; Via rewrites its config on every load.
|
||||
# So does the service-token line of felis-link.properties: the plugin re-reads it on its own
|
||||
# (`felis rotate-token velocity` counts on that), and a restart for it would only disconnect
|
||||
# every player.
|
||||
velocity_fingerprint() {
|
||||
local f
|
||||
local f sum
|
||||
for f in "$VELOCITY_SERVICE" "${JRE_DIR}/release" "${VELOCITY_DIR}/velocity.jar" \
|
||||
"${VELOCITY_DIR}/velocity.toml" "${VELOCITY_DIR}/forwarding.secret" \
|
||||
"${VELOCITY_DIR}/plugins/felis-link/felis-link.properties" "${VELOCITY_DIR}"/plugins/*.jar; do
|
||||
[ -f "$f" ] || continue
|
||||
printf '%s %s\n' "$(sha256sum <"$f" | cut -d' ' -f1)" "$f"
|
||||
case "$f" in
|
||||
*/felis-link.properties) sum="$({ grep -v '^service-token=' "$f" || true; } | sha256sum | cut -d' ' -f1)" ;;
|
||||
*) sum="$(sha256sum <"$f" | cut -d' ' -f1)" ;;
|
||||
esac
|
||||
printf '%s %s\n' "$sum" "$f"
|
||||
done | sha256sum | cut -d' ' -f1
|
||||
}
|
||||
|
||||
@@ -4187,12 +4194,13 @@ load_or_make_secrets() {
|
||||
# to its own routes and a leak is contained to that caller: SERVICE_TOKEN is the
|
||||
# proxy's (felis-link.properties), LIMBO_TOKEN the login gate's, BUILD_TOKEN what a
|
||||
# build Job fetches its context with, OPS_TOKEN what `felis backup-now` presents.
|
||||
# `felis rotate-token <caller>` rewrites the matching line here.
|
||||
# `felis rotate-token <caller>` replaces one of them, and `felis rotate-token
|
||||
# registry|forwarding|db` the other values persisted below: every line of secrets.env
|
||||
# has a rotation that rewrites it (cmd/felis TestInstallerSecretsAreAllRotatable).
|
||||
SERVICE_TOKEN="${SERVICE_TOKEN:-$(openssl rand -hex 32)}"
|
||||
LIMBO_TOKEN="${LIMBO_TOKEN:-$(openssl rand -hex 32)}"
|
||||
BUILD_TOKEN="${BUILD_TOKEN:-$(openssl rand -hex 32)}"
|
||||
OPS_TOKEN="${OPS_TOKEN:-$(openssl rand -hex 32)}"
|
||||
SESSION_SECRET="${SESSION_SECRET:-$(openssl rand -hex 32)}"
|
||||
# The Velocity modern-forwarding key. It is what makes a backend's UUID trustworthy:
|
||||
# the proxy does the Mojang handshake and HMACs the resulting profile with this key,
|
||||
# and a backend that cannot verify it would fall back to an offline UUID derived from
|
||||
@@ -4213,7 +4221,6 @@ SERVICE_TOKEN=${SERVICE_TOKEN}
|
||||
LIMBO_TOKEN=${LIMBO_TOKEN}
|
||||
BUILD_TOKEN=${BUILD_TOKEN}
|
||||
OPS_TOKEN=${OPS_TOKEN}
|
||||
SESSION_SECRET=${SESSION_SECRET}
|
||||
FORWARDING_SECRET=${FORWARDING_SECRET}
|
||||
REGISTRY_PLATFORM_TOKEN=${REGISTRY_PLATFORM_TOKEN}
|
||||
REGISTRY_BUILD_TOKEN=${REGISTRY_BUILD_TOKEN}
|
||||
|
||||
@@ -1643,7 +1643,7 @@ run_atomic() { # script; under the installer's shell options, its temp files rem
|
||||
mode_of() { ls -l "$1" | cut -c1-10; }
|
||||
|
||||
printf 'A=1\nB=2\n' > "$wadir/in.new"
|
||||
printf 'DB_PASSWORD=new\nSESSION_SECRET=new\n' > "$wadir/in.replace"
|
||||
printf 'DB_PASSWORD=new\nSERVICE_TOKEN=new\n' > "$wadir/in.replace"
|
||||
out="$(run_atomic "umask 000; write_file_atomic '$wadir/new.env' 0600 < '$wadir/in.new'; echo done")"
|
||||
expect "an atomic write finishes" "done" "$out"
|
||||
expect "an atomic write holds all of its input" "$(printf 'A=1\nB=2')" "$(cat "$wadir/new.env")"
|
||||
@@ -1651,11 +1651,11 @@ expect "an atomic write is private under a permissive umask" "-rw-------" "$(mod
|
||||
run_atomic "write_file_atomic '$wadir/new.env' 0640 < '$wadir/in.new'" >/dev/null
|
||||
expect "an atomic write sets the mode it is given" "-rw-r-----" "$(mode_of "$wadir/new.env")"
|
||||
|
||||
printf 'DB_PASSWORD=old-and-whole\nSESSION_SECRET=kept\n' > "$wadir/old.env"
|
||||
printf 'DB_PASSWORD=old-and-whole\nSERVICE_TOKEN=kept\n' > "$wadir/old.env"
|
||||
out="$(run_atomic "cat() { head -c 7; return 1; }; write_file_atomic '$wadir/old.env' 0600 < '$wadir/in.replace'; echo survived")"
|
||||
expect "a write that fails halfway dies" "DIE: could not write $wadir/old.env; it is left as it was" "$out"
|
||||
expect "a write that fails halfway leaves the old file whole" \
|
||||
"$(printf 'DB_PASSWORD=old-and-whole\nSESSION_SECRET=kept')" "$(cat "$wadir/old.env")"
|
||||
"$(printf 'DB_PASSWORD=old-and-whole\nSERVICE_TOKEN=kept')" "$(cat "$wadir/old.env")"
|
||||
out="$(run_atomic "sync() { return 1; }; write_file_atomic '$wadir/old.env' 0600 < '$wadir/in.replace'")"
|
||||
expect "content that did not reach the disk does not replace the old file" "DIE: could not write $wadir/old.env" "$out"
|
||||
expect "the old file survives a failed sync" "DB_PASSWORD=old-and-whole" "$(cat "$wadir/old.env")"
|
||||
@@ -2675,6 +2675,20 @@ expect "a new heap size restarts the proxy" "SYSTEMCTL restart felis-velocity" "
|
||||
expect "the unit carries the new ceiling" "java -Xms512M -Xmx3G " "$(cat "$vdir/unit")"
|
||||
run_velocity_service 1 384M >/dev/null
|
||||
expect "a ceiling below 512M is also the initial heap" "java -Xms384M -Xmx384M " "$(cat "$vdir/unit")"
|
||||
# `felis rotate-token velocity` rewrites service-token, which the plugin re-reads by itself:
|
||||
# that line alone changing leaves the proxy running, and any other change restarts it.
|
||||
props="$vdir/v/plugins/felis-link/felis-link.properties"
|
||||
printf 'api-base-url=http://a\nservice-token=one\n' > "$props"
|
||||
expect "new proxy properties restart the proxy" "SYSTEMCTL restart felis-velocity" "$(run_velocity_service 1 384M)"
|
||||
printf 'api-base-url=http://a\nservice-token=two\n' > "$props"
|
||||
out="$(run_velocity_service 1 384M)"
|
||||
case "$out" in
|
||||
*"SYSTEMCTL restart"*) echo "FAIL a new service-token alone restarted the proxy"; fails=$((fails + 1)) ;;
|
||||
*"felis-velocity unchanged; left running"*) echo "PASS a new service-token alone leaves the proxy running" ;;
|
||||
*) echo "FAIL install_velocity_service died on a new service-token: $out"; fails=$((fails + 1)) ;;
|
||||
esac
|
||||
printf 'api-base-url=http://b\nservice-token=two\n' > "$props"
|
||||
expect "another change to the proxy properties restarts the proxy" "SYSTEMCTL restart felis-velocity" "$(run_velocity_service 1 384M)"
|
||||
rm -rf "$vdir"
|
||||
|
||||
ssblock="$(awk '/^restart_existing_system_servers\(\) \{/,/^}/' "$BS")"
|
||||
|
||||
@@ -144,7 +144,7 @@ set them by hand:
|
||||
the minecraft namespace (and `felis setup` refreshes that replica from the control
|
||||
namespace), and the operator injects it into the `login` pod (only) as
|
||||
`FELIS_SERVICE_TOKEN` via a `secretKeyRef`, keyed off the reserved `login` name.
|
||||
`sudo felis rotate-token limbo` replaces it and restarts the pod. Until the token is
|
||||
`sudo felis rotate-token -yes limbo` replaces it and restarts the pod. Until the token is
|
||||
present the plugin fail-safes to readiness-only, so the gate is never broken — it
|
||||
simply does not authenticate yet.
|
||||
- **Service:** the login pod dials `FELIS_API_BASE_URL`, which resolves to the
|
||||
|
||||
Reference in new issue
Block a user