From 4040e971f57fa74508c59c2adc91c48305ac9047 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Wed, 16 Aug 2023 19:41:22 -0500 Subject: [PATCH] Improve whitelist/ops handling with caching, UUID, and offline support (#2342) --- Dockerfile | 2 +- docs/configuration/server-properties.md | 62 +++++++----- notes/rbac-processing.mmd | 93 ++++++++++++++++++ scripts/start-setupRbac | 122 ++++++++---------------- 4 files changed, 171 insertions(+), 108 deletions(-) create mode 100644 notes/rbac-processing.mmd diff --git a/Dockerfile b/Dockerfile index afcf9be0..3edb3d14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,7 +42,7 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ --var version=1.9.0 --var app=mc-server-runner --file {{.app}} \ --from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz -ARG MC_HELPER_VERSION=1.33.5 +ARG MC_HELPER_VERSION=1.34.0 ARG MC_HELPER_BASE_URL=https://github.com/itzg/mc-image-helper/releases/download/${MC_HELPER_VERSION} # used for cache busting local copy of mc-image-helper ARG MC_HELPER_REV=1 diff --git a/docs/configuration/server-properties.md b/docs/configuration/server-properties.md index 21b9801e..f500e258 100644 --- a/docs/configuration/server-properties.md +++ b/docs/configuration/server-properties.md @@ -42,47 +42,63 @@ values. ### Whitelist Players -!!! note +!!! warning "For public servers" - It is very important to set this with servers exposed to the internet where you want only limited players to join. + It is very important to consider setting a whitelist of expected players. To whitelist players for your Minecraft server, you can: -- Provide a list of usernames and/or UUIDs separated by commas via the `WHITELIST` environment variable - `docker run -d -e WHITELIST=user1,uuid2 ...` -- Provide the url or path to a whitelist file via `WHITELIST_FILE` environment variable - `docker run -d -e WHITELIST_FILE=/extra/whitelist.json ...` +- Provide a list of usernames and/or UUIDs separated by commas or newlines via the `WHITELIST` environment variable +- Provide the URL or container path to a whitelist file via `WHITELIST_FILE` that will be retrieved/copied into the standard location -When either is set, [whitelisting of connecting users](https://minecraft.fandom.com/wiki/Server.properties#white-list) is enabled . If managing the list manually, `ENABLE_WHITELIST` can be set to "true" to set the `white-list` property. +!!! example -If whitelist configuration already exists, `WHITELIST_FILE` will not be retrieved and any usernames in `WHITELIST` are **added** to the whitelist configuration. You can enforce regeneration of the whitelist on each server startup by setting `OVERRIDE_WHITELIST` to "true". This will delete the whitelist file before processing whitelist configuration. + In a compose file, a text block can be used to improve maintainability, such as -!!! note + ```yaml + WHITELIST: | + user1 + user2 + user3 + ``` - You can provide both `WHITELIST_FILE` and `WHITELIST`, which are processed in that order. +When either is set, [whitelisting of connecting users](https://minecraft.fandom.com/wiki/Server.properties#white-list) is enabled. + +Use of `WHITELIST_FILE` will **overwrite** an existing `whitelist.json` file; however, the option can be combined with `WHITELIST` to refine the list. + +By default, `WHITELIST` will keep the `whitelist.json` fully synchronized with the given list. All whitelist entries can be removed by setting `WHITELIST` to an empty string. To only append new users, set `APPEND_WHITELIST` to "true". !!! note - - UUIDs passed via `WHITELIST` need to be the dashed variant, otherwise it not be recognised and instead added as a username. - - If running Minecraft 1.7.5 or earlier, these variables will apply to `white-list.txt`, with 1.7.6 implementing support for `whitelist.json`. Make sure your `WHITELIST_FILE` is in the appropriate format. -To [enforce the whitelist changes immediately](https://minecraft.fandom.com/wiki/Server.properties#enforce-whitelist) when whitelist commands are used , set `ENFORCE_WHITELIST` to "true". + For versions prior to 1.7.3, `white-list.txt` will be maintained instead. Only usernames are supported for those versions. + +To [enforce the whitelist changes immediately](https://minecraft.fandom.com/wiki/Server.properties#enforce-whitelist) when whitelist commands are used , set `ENFORCE_WHITELIST` to "true". If managing the whitelist file manually, `ENABLE_WHITELIST` can be set to "true" to set the `white-list` property. ### Op/Administrator Players -Similar to the whitelist, to add users as operators (aka adminstrators) to your Minecraft server, you can: +Similar to the whitelist, to add users as operators (aka administrators) to your Minecraft server, you can: -- Provide te url or path to an ops file via `OPS_FILE` environment variable - `docker run -d -e OPS_FILE=https://config.example.com/extra/ops.json ...` -- Provide a list of usernames and/or UUIDs separated by commas via the `OPS` environment variable - `docker run -d -e OPS=user1,uuid2 ...` +- Provide a list of usernames and/or UUIDs separated by commas or newlines via the `OPS` environment variable +- Provide the URL or container path to an ops file via `OPS_FILE` that will be retrieved/copied into the standard location -If ops configuration already exists, `OPS_FILE` will not be retrieved and any usernames in `OPS` are **added** to the ops configuration. You can enforce regeneration of the ops configuration on each server startup by setting `OVERRIDE_OPS` to "true". This will delete the ops file before processing ops configuration. +!!! example -!!! note + In a compose file, a text block can be used to improve maintainability, such as - Similar to whitelists, you can provide both `OPS_FILE` and `OPS`, and Minecraft 1.7.5 or earlier will use `ops.txt` rather than `ops.json`. + ```yaml + OPS: | + user1 + user2 + user3 + ``` + +Use of `OPS_FILE` will **overwrite** an existing `ops.json` file; however, the option can be combined with `OPS` to refine the list. + +By default, `OPS` will keep the `ops.json` fully synchronized with the given list. All ops entries can be removed by setting `OPS` to an empty string. To only append new users, set `APPEND_OPS` to "true". New entries will be assigned [level 4](https://glimpse.me/blog/how-to-op-yourself-in-minecraft/) and not bypass player limit. Manual changes to those fields will be retained. + +!!! note + + For versions prior to 1.7.3, `ops.txt` will be maintained instead. Only usernames are supported for those versions. ### Enable/disable initial selection of datapacks diff --git a/notes/rbac-processing.mmd b/notes/rbac-processing.mmd new file mode 100644 index 00000000..12f1382c --- /dev/null +++ b/notes/rbac-processing.mmd @@ -0,0 +1,93 @@ +[Scia Reto](https://sciareto.org) mind map +> __version__=`1.1`,showJumps=`true` +--- + +# RBAC processing + +## inputs + +### whitelist + +#### command or space limited + +##### uuid + +##### username + +### ops + +#### username + +#### uuid + +### whitelist file + +#### url? + +##### yes + +###### download + +##### no + +###### copy + +### override whitelist? + +#### yes + +##### replace all with given input list + +#### no + +##### append only + +## format + +### version \< 1\.7\.6? + +#### yes + +##### text file listing usernames + +###### white\-list\.txt + +###### ops\.txt + +#### no +> leftSide=`true` + + +##### json file + +###### array of objects + +####### name + +######## can be any string, even an empty one + +####### uuid +> leftSide=`true` + + +######## username to UUID API +- LINK +
https://wiki.vg/Mojang_API#Username_to_UUID
+ +######## needs to be "dashed" UUID syntax +> leftSide=`true` + + +####### ops? + +######## yes + +######### also includes + +########## level + +########### integer, usually a 4 + +########## bypassesPlayerLimit + +########### boolean diff --git a/scripts/start-setupRbac b/scripts/start-setupRbac index 9c92764b..1c822b54 100644 --- a/scripts/start-setupRbac +++ b/scripts/start-setupRbac @@ -1,98 +1,52 @@ #!/bin/bash +set -euo pipefail +IFS=$'\n\t' # shellcheck source=start-utils . "${SCRIPTS:-/}start-utils" isDebugging && set -x -if versionLessThan 1.7.6; then - opsFile=ops.txt - whitelistFile=white-list.txt -else - opsFile=ops.json - whitelistFile=whitelist.json +sharedArgs=(--version="$VERSION") +if isFalse "${ONLINE_MODE:-true}"; then + sharedArgs+=( --offline ) fi -function process_user_file() { - local output=$1 - local source=$2 - - if isURL "$source"; then - log "Downloading $output from $source" - if ! get -o "/data/$output" "$source"; then - log "ERROR: failed to download from $source" - exit 2 - fi - else - log "Copying $output from $source" - if ! cp "$source" "/data/$output"; then - log "ERROR: failed to copy from $source" - exit 1 - fi +if [[ -v OPS_FILE ]]; then + mc-image-helper manage-users \ + "${sharedArgs[@]}" \ + --type=JAVA_OPS \ + --input-is-file \ + "$OPS_FILE" +fi +if [[ -v OPS ]]; then + args=() + if isTrue "${APPEND_OPS:-false}" || isFalse "${OVERRIDE_OPS:-true}"; then + args+=(--append-only) fi -} + # shellcheck disable=SC2086 + mc-image-helper manage-users \ + "${sharedArgs[@]}" "${args[@]}" \ + --type=JAVA_OPS \ + $OPS +fi -function process_user_csv() { - local output=$1 - local list=$2 - local playerDataList - - if [[ "$output" == *"ops"* ]]; then - # Extra data for ops.json - userData='{"uuid": .id, "name": .username, "level": 4}' - else - userData='{"uuid": .id, "name": .username}' +if [[ -v WHITELIST_FILE ]]; then + mc-image-helper manage-users \ + "${sharedArgs[@]}" \ + --type=JAVA_WHITELIST \ + --input-is-file \ + "$WHITELIST_FILE" +fi +if [[ -v WHITELIST ]]; then + args=() + if isTrue "${APPEND_WHITELIST:-false}" || isFalse "${OVERRIDE_WHITELIST:-true}"; then + args+=(--append-only) fi - - log "Updating ${output%.*}" - for i in ${list//,/ } - do - if [ -e "$output" ] && grep -q "$i" "$output"; then - log "$i already present in $output, skipping" - continue - fi - if ! playerData=$(get "https://playerdb.co/api/player/minecraft/$i" | jq -re ".data.player"); then - log "WARNING: Could not lookup user $i for ${output} addition" - else - playerDataList=$playerDataList$(echo "$playerData" | jq -r "$userData") - fi - done - local newUsers=$(echo "$playerDataList" | jq -s .) - if [[ $output =~ .*\.txt ]]; then - # username list for txt config (Minecraft <= 1.7.5) - echo $newUsers | jq -r '.[].name' >> "/data/${output}" - sort -u /data/${output} -o /data/${output} - elif [ -e /data/${output} ]; then - # Merge with existing json file - local currentUsers=$(cat "/data/${output}") - jq --argjson current "$currentUsers" --argjson new "$newUsers" -n '$new + $current | unique_by(.uuid)' > "/data/${output}" - else - # New json file - echo $newUsers > "/data/${output}" - fi -} - -if isTrue "${OVERRIDE_OPS}"; then - log "Recreating ${opsFile} file at server startup" - rm -f /data/${opsFile} + # shellcheck disable=SC2086 + mc-image-helper manage-users \ + "${sharedArgs[@]}" "${args[@]}" \ + --type=JAVA_WHITELIST \ + $WHITELIST fi -if [ -n "${OPS_FILE}" ] && [ ! -e "/data/${opsFile}" ]; then - process_user_file ${opsFile} "$OPS_FILE" -fi -if [ -n "${OPS}" ]; then - process_user_csv ${opsFile} "$OPS" -fi - -if isTrue "${OVERRIDE_WHITELIST}"; then - log "Recreating ${whitelistFile} file at server startup" - rm -f /data/${whitelistFile} -fi -if [ -n "${WHITELIST_FILE}" ] && [ ! -e "/data/${whitelistFile}" ]; then - process_user_file ${whitelistFile} "$WHITELIST_FILE" -fi -if [ -n "${WHITELIST}" ]; then - process_user_csv ${whitelistFile} "$WHITELIST" -fi - - exec "${SCRIPTS:-/}start-finalExec" "$@"