Compare commits

...

2 Commits

Author SHA1 Message Date
MasterofJOKers 845e3fe30e Add remap-uid-and-gid-for-lv
I've used this script to remap files' uids/gids of containers created
without a custom userns into their new range.  It's inferior to
`fuidshift` from the `lxc` project in that it doesn't handle ACLs and is
quite slow - probably because it calls a binary for every file.

By default, it runs in debug mode only printing the chown command
instead of executing it. You need to edit the file to use it.

It also only works with LVs (logical volumes from LVM), mounting them
automatically.
2023-02-25 17:15:23 +01:00
MasterofJOKers 271d7009cf Add get-lxc-idmap-config script
This script handles uid/gid ranges for creating unprivileged containers as root.
2023-02-25 17:13:12 +01:00
2 changed files with 151 additions and 0 deletions

80
lxc/get-lxc-idmap-config Executable file
View File

@ -0,0 +1,80 @@
#!/bin/sh
# Manage uid/gid maps for containers
#
# This script manages uids/gids assigned to certain containers or groups of containers. It uses /etc/subuid and
# /etc/subgid by default to save the information. All the ranges are owned by root as we don't want to support creation
# of containers by unprivileged users, but rather want to create unprivileged containers as root user.
USER_ID=0
FIRST_ID=1000000
DEFAULT_COUNT=65536
FILENAME="/etc/sub_____id"
get_filename () (
TYPE="${1}"
echo "${FILENAME}" | sed "s/_____/${TYPE}/"
)
find_range () (
TYPE="${1}"
NAME="${2}"
FILENAME="$(get_filename ${TYPE})"
grep -A 1 "^# ${NAME}$" "${FILENAME}" -A 1 | tail -n 1
)
get_last_range () (
TYPE="${1}"
grep "^${USER_ID}:" "$(get_filename ${TYPE})" | tail -n 1
)
get_new_range () (
TYPE="${1}"
LAST_RANGE=$(get_last_range "${TYPE}")
if [ "${LAST_RANGE}" = "" ]; then
NEW_ID=$FIRST_ID;
else
LAST_ID=$(echo "${LAST_RANGE}" | cut -d : -f 2)
LAST_COUNT=$(echo "${LAST_RANGE}" | cut -d : -f 3)
NEW_ID=$(( $LAST_ID + $LAST_COUNT ))
fi
echo "${USER_ID}:${NEW_ID}:${DEFAULT_COUNT}"
)
append_range () (
TYPE="${1}"
FILENAME="$(get_filename ${TYPE})"
NAME="${2}"
RANGE="${3}"
printf "# ${NAME}\n${RANGE}\n" >> "${FILENAME}"
)
usage () {
echo "usage: get-lxc-idmap-config <u|g> <container-group-name>"
exit 1
}
TYPE="${1}"
if [ "${TYPE}" = "" || "${TYPE}" == "--help" || "${TYPE}" == "-h" ]; then
usage
fi
NAME="${2}"
if [ "${NAME}" = "" ]; then
usage
fi
RANGE=$(find_range "${TYPE}" "${NAME}")
if [ "${RANGE}" = "" ]; then
RANGE=$(get_new_range "${TYPE}")
if [ "${RANGE}" = "" ]; then
exit 1
fi
append_range "${TYPE}" "${NAME}" "${RANGE}"
fi
RANGE_START=$(echo ${RANGE} | cut -d : -f 2)
RANGE_COUNT=$(echo ${RANGE} | cut -d : -f 3)
printf "lxc.idmap = %s 0 %s %s\n" "${TYPE}" "${RANGE_START}" "$(( ${RANGE_COUNT} - 1))"

71
lxc/remap-uid-and-gid-for-lv Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
# Remap all files uid/gid to a new range
#
# This is an inferior version of `fuidshift` from the `lxd-tools` Debian package, as it only handles uid/gid and
# doesn't handle ACLs and thus journalctl's files and by that hinders updating systemd inside the container. It's also
# quite slow.
usage () {
echo "remap-uid-and-gid <container-name> [<target-lv>]"
printf "\nIf <target-lv> is not given it is computed from a default value with the given container name\n"
exit 1
}
CONTAINER_NAME="${1}"
if [ "${CONTAINER_NAME}" = "" ]; then
usage
fi
TARGET_LV="${2}"
if [ "${TARGET_LV}" = "" ]; then
GUESSED_LV="/dev/mapper/daffy--vg-lxc--${CONTAINER_NAME}"
if [ -e "${GUESSED_LV}" ]; then
TARGET_LV="${GUESSED_LV}"
fi
fi
if [ "${TARGET_LV}" = "" ]; then
usage
fi
if mount | grep -qF " on /mnt"; then
echo "Mountpoint /mnt is already in use."
exit 1
fi
mount "${TARGET_LV}" /mnt
cd /mnt
ROOT_USER_ID=$(get-lxc-idmap-config u $CONTAINER_NAME | cut -d ' ' -f 5)
ROOT_GROUP_ID=$(get-lxc-idmap-config g $CONTAINER_NAME | cut -d ' ' -f 5)
printf "uid: %s gid: %s\n" $ROOT_USER_ID $ROOT_GROUP_ID
# We ignore links here, because they might not point to a valid location and would make our program fail. They are also
# owned by whoever mounted the filesystem it seems, so don't need a chown.
find . -xdev -not -type l -printf "%U %G %p\n" | \
while read F; do
U=$(echo $F | cut -d ' ' -f 1)
if [ ${U} -lt ${ROOT_USER_ID} ] || [ ${U} -gt $(( ${ROOT_USER_ID} + 65535 )) ]; then
NEW_U=$(( ${U} + ${ROOT_USER_ID} ))
else
NEW_U=${U}
fi
G=$(echo $F | cut -d ' ' -f 2)
if [ ${G} -lt ${ROOT_GROUP_ID} ] || [ ${G} -gt $(( ${ROOT_GROUP_ID} + 65535 )) ]; then
NEW_G=$(( ${G} + ${ROOT_GROUP_ID} ))
else
NEW_G=${G}
fi
if [ "${U}" = "${NEW_U}" ] && [ "${G}" = "${NEW_G}" ]; then
continue
fi
P=$(echo $F | cut -d ' ' -f 3-)
printf "chown %s:%s %s\n" ${NEW_U} ${NEW_G} "${P}"
# chown ${NEW_U}:${NEW_G} "${P}"
done
cd /
umount /mnt