feat(runtime): add authenticated system backends
This commit is contained in:
6 files changed
+210
-38
No files matched your search
+11
-5
@@ -70,17 +70,23 @@ RUN set -eu; \
|
||||
mkdir -p /limbo/plugins
|
||||
# Drop the login+readiness plugin in beside Limbo.jar.
|
||||
COPY --from=plugin /felis-limbo.jar /limbo/plugins/felis-limbo.jar
|
||||
# The entrypoint pins the game port to the operator's GamePort before launching Limbo.
|
||||
# The entrypoint pins the game port AND enables Velocity modern forwarding — refusing to
|
||||
# start without the secret, because a login gate that derives offline UUIDs would let
|
||||
# anyone claim any Minecraft identity (the Owner's included).
|
||||
COPY deploy/limbo/entrypoint.sh /usr/local/bin/felis-entrypoint.sh
|
||||
|
||||
# The operator mounts the world PVC at /data. Runtime state lives there; /limbo
|
||||
# remains the immutable image seed copied into the volume by the entrypoint.
|
||||
WORKDIR /data
|
||||
|
||||
ENV FELIS_HEALTH_PORT=8080
|
||||
# FELIS_GAME_PORT is the port the entrypoint pins Limbo to; it MUST equal the operator's
|
||||
# GamePort (internal/operator/builders.go). Default 25565 — override only in lockstep
|
||||
# with the operator.
|
||||
ENV FELIS_GAME_PORT=25565
|
||||
EXPOSE 25565 8080
|
||||
# felis-entrypoint.sh pins server-port then execs `java -jar Limbo.jar --nogui` (headless:
|
||||
# the pod has no console). Limbo writes the rest of server.properties on first run and
|
||||
# loads ./spawn.schem as the spawn world. Invoked via `sh` so no +x bit is needed from the
|
||||
# (Windows) build host.
|
||||
# felis-entrypoint.sh pins server-port + velocity-modern/forwarding-secrets, then execs
|
||||
# `java -jar Limbo.jar --nogui` from /data (headless: the pod has no console). Limbo writes
|
||||
# the rest of server.properties on the persistent volume and loads ./spawn.schem as the
|
||||
# spawn world. Invoked via `sh` so no +x bit is needed from the (Windows) build host.
|
||||
ENTRYPOINT ["/bin/sh", "/usr/local/bin/felis-entrypoint.sh"]
|
||||
@@ -142,6 +142,6 @@ set them by hand:
|
||||
or a control-namespace ingress fence, it must also open the login-pod →
|
||||
felis-api-internal (8081) path.
|
||||
|
||||
The Velocity default-landing and waiting-park wiring is printed by `felis setup`
|
||||
and enforces the invariant: fresh connections hit `login` first; nothing falls
|
||||
back to the lobby.
|
||||
The Velocity gate/lobby wiring is printed by `felis setup` and enforces the
|
||||
invariant: fresh connections hit `login` first, and only an authenticated release
|
||||
from that gate can enter the post-auth lobby or a remembered user backend.
|
||||
+76
-20
@@ -1,31 +1,87 @@
|
||||
#!/bin/sh
|
||||
# Felis login-limbo entrypoint.
|
||||
#
|
||||
# Pin Limbo's game port to the pod-facing port the operator contract uses. LOOHP/Limbo
|
||||
# defaults server-port to 30000, but the Felis operator drives everything — the Service
|
||||
# Port/TargetPort, the TCP/HTTP readiness probe, the container port and the Velocity
|
||||
# NetworkPolicy — off a single GamePort const (25565). A backend that bound 30000 would
|
||||
# be unreachable through that fence. Limbo writes a full server.properties on first run
|
||||
# and merges any partial we leave in place, so seeding/patching just server-port here is
|
||||
# enough; the spawn schematic still loads from ./spawn.schem.
|
||||
# Two things must be true before Limbo accepts a connection, and both are settings
|
||||
# Limbo writes into server.properties on first run:
|
||||
#
|
||||
# Idempotent by design: it runs on every start and rewrites only the server-port line,
|
||||
# so a persisted world volume that already carries a server.properties keeps all its
|
||||
# other settings.
|
||||
# server-port — pinned to the pod-facing port the operator contract uses. LOOHP/Limbo
|
||||
# defaults it to 30000, but the Felis operator drives everything (the
|
||||
# Service Port/TargetPort, the readiness probe, the container port and
|
||||
# the Velocity NetworkPolicy) off a single GamePort const (25565). A
|
||||
# backend that bound 30000 would be unreachable through that fence.
|
||||
#
|
||||
# velocity-modern — Velocity modern player-info forwarding. This is the ONLY reason the
|
||||
# forwarding-secrets login gate can be trusted to know WHO joined. With it on, Limbo
|
||||
# verifies the proxy's HMAC over the login payload and takes the
|
||||
# player's UUID from that signed payload (ClientConnection.java:
|
||||
# validateVelocityModernResponse → getVelocityDataFrom → new Player(...,
|
||||
# data.getUuid())). With it off, Limbo derives an OFFLINE UUID from the
|
||||
# username — and the felis-limbo plugin would then mint a /link code
|
||||
# bound to the WRONG Minecraft identity. The Owner IS a Minecraft
|
||||
# account, claimed by joining this gate, so that is account takeover,
|
||||
# not a cosmetic bug.
|
||||
#
|
||||
# Hence: NO SECRET, NO START. Refusing to boot is the safe failure — the operator marks the
|
||||
# server Failed, `felis setup` surfaces the reason and stops before asking for a link code.
|
||||
# A limbo that came up in offline mode would look perfectly healthy while handing out
|
||||
# forgeable identities. forwarding-secrets is Limbo's ';'-separated list; Felis writes one.
|
||||
#
|
||||
# Idempotent by design: it runs on every start and rewrites only the keys below, so a
|
||||
# persisted volume that already carries a server.properties keeps its other settings (and
|
||||
# the spawn schematic still loads from ./spawn.schem).
|
||||
set -eu
|
||||
|
||||
PORT="${FELIS_GAME_PORT:-25565}"
|
||||
SECRET="${FELIS_FORWARDING_SECRET:-}"
|
||||
RUNTIME_DIR="/limbo"
|
||||
DATA_DIR="/data"
|
||||
PROPS="server.properties"
|
||||
|
||||
if [ -f "$PROPS" ]; then
|
||||
if grep -q '^server-port=' "$PROPS"; then
|
||||
sed -i "s/^server-port=.*/server-port=${PORT}/" "$PROPS"
|
||||
else
|
||||
printf 'server-port=%s\n' "$PORT" >> "$PROPS"
|
||||
fi
|
||||
else
|
||||
printf 'server-port=%s\n' "$PORT" > "$PROPS"
|
||||
if [ -z "$SECRET" ]; then
|
||||
echo "felis-limbo: FATAL — FELIS_FORWARDING_SECRET is empty." >&2
|
||||
echo " The login gate authenticates the Owner, so it must not run without Velocity modern" >&2
|
||||
echo " forwarding: an unverified UUID would let anyone claim any Minecraft identity." >&2
|
||||
echo " Provision the secret with deploy/bootstrap.sh, then re-run 'sudo felis setup'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "felis-limbo: pinned server-port=${PORT} (operator GamePort)"
|
||||
exec java -jar Limbo.jar --nogui "$@"
|
||||
# Keep mutable server state on the operator-mounted PVC. Refresh code artifacts on
|
||||
# every boot so an image upgrade takes effect without replacing worlds or config.
|
||||
mkdir -p "$DATA_DIR/plugins"
|
||||
cp -f "$RUNTIME_DIR/Limbo.jar" "$DATA_DIR/Limbo.jar"
|
||||
cp -f "$RUNTIME_DIR/plugins/felis-limbo.jar" "$DATA_DIR/plugins/felis-limbo.jar"
|
||||
if [ -f "$RUNTIME_DIR/spawn.schem" ] && [ ! -f "$DATA_DIR/spawn.schem" ]; then
|
||||
cp "$RUNTIME_DIR/spawn.schem" "$DATA_DIR/spawn.schem"
|
||||
fi
|
||||
cd "$DATA_DIR"
|
||||
|
||||
# set_prop KEY VALUE — replace the key's line, or append it if absent.
|
||||
set_prop() {
|
||||
if [ -f "$PROPS" ] && grep -q "^$1=" "$PROPS"; then
|
||||
# The secret is base64/hex-ish, but a '/' or '&' would still break a bare sed s///.
|
||||
# '|' as the delimiter plus escaping it is enough for every value we write.
|
||||
esc=$(printf '%s' "$2" | sed 's/[|\\&]/\\&/g')
|
||||
sed -i "s|^$1=.*|$1=${esc}|" "$PROPS"
|
||||
else
|
||||
printf '%s=%s\n' "$1" "$2" >> "$PROPS"
|
||||
fi
|
||||
}
|
||||
|
||||
set_prop server-port "$PORT"
|
||||
# velocity-modern is mutually exclusive with the two legacy schemes in Limbo's own
|
||||
# check — pin them off so a stale persisted properties file cannot silently downgrade
|
||||
# the gate to a forwarding mode that carries no signature at all.
|
||||
set_prop bungeecord false
|
||||
set_prop bungee-guard false
|
||||
set_prop velocity-modern true
|
||||
set_prop forwarding-secrets "$SECRET"
|
||||
|
||||
echo "felis-limbo: server-port=${PORT}, velocity-modern=true (forwarding secret loaded, UUIDs are Mojang-verified)"
|
||||
JAVA_MEMORY_ARG=""
|
||||
if [ -n "${JAVA_MEMORY:-}" ]; then
|
||||
JAVA_MEMORY_ARG="-Xmx${JAVA_MEMORY}"
|
||||
fi
|
||||
set -f
|
||||
# JAVA_FLAGS is emitted by the operator as a whitespace-separated JVM argument list.
|
||||
# shellcheck disable=SC2086
|
||||
exec java $JAVA_MEMORY_ARG ${JAVA_FLAGS:-} -jar Limbo.jar --nogui "$@"
|
||||
Reference in new issue
Block a user