Переместите непривилегированный контейнер LXC между пользователями

В аналогичной ситуации (дифференциальное резервное копирование) я делаю это сначала:

find /directory/ -printf . &>/dev/null

Таким образом, я добираюсь, все метаданные файла в кэш с оптимальной производительностью жесткого диска (вероятно, не имел бы большого смысла с SSD).

7
19.09.2014, 22:41
2 ответа

Теперь я знаю, как это сделать. Если вы не можете следовать этому объяснению, спросите его, но также убедитесь, что вы прочитали о пользователях в показаниях, которые я даю внизу

Предварительные предположения

Я буду придерживаться следующих предположений, расширенных из того, что у меня есть из вашего вопроса:

  1. хост имеет user1 и user2 , если информация не относится к одному, мы будем использовать userX
  2. контейнер будет назван переменной, которую мы будем отображать как домашние папки $ container
  3. для user1 и user2 будут указаны в обозначении, известном из Bash. как ~ user1 и ~ user2 .
  4. мы предположим, что подчиненные диапазоны UID и GID равны 100000..165536 для user1 и 200000..265536 для user2 только для краткости
  5. корневой папки FS для $ container будет отображаться как $ rootfs , независимо от того, где он окажется ( ~ userX / .local / share / lxc / $ container / rootfs )
  6. конфигурация контейнера по умолчанию находится в ~ userX / .local / share / lxc / $ container / config

Перемещение контейнера

Есть два важных элемента данных, которые управляют пользователями контейнеры:

  1. владелец и группа для файлов / папок в папках, составляющих $ container
  2. подчиненные UID и GID, назначенные в двух местах: / etc / sub {uid, gid } для учетной записи пользователя (управляется с помощью usermod - {add, del} -sub- {uid, gid} s ) и lxc.id_map в конфигурации $ container ( ~ userX / .local / share / lxc / $ container / config ) соответственно
    • Я не знать наверняка, можно ли определять разные диапазоны в конфигурации контейнера для каждого контейнера. Например. если пользователь хоста userX имеет 65536 подчиненных GID и UID, можно было бы назначить от 5000 до 65 различных контейнеров, но я не проверял эту гипотезу.
    • однако очевидно, что этот параметр передает LXC допустимые диапазоны для GID и UID в дочернем пространстве имен.

Таким образом, суть в том, что вам нужно убедиться, что владелец файла / папки и группа для контейнера соответствуют конфигурации, которая, в свою очередь, должна быть допустимым подмножеством подчиненных GID / UID хоста, назначенных для user1 и user2 соответственно.

Если вы, например, используете Bash, вы можете использовать $ ((выражение)) для арифметических выражений и let для присвоения арифметических выражений переменным. Это очень полезно, если вы знаете базовое значение (100000 и 200000 соответственно) и GID / UID для «внутренних» пользователей.

Основные моменты:

  1. возможно
  2. либо , CAP_CHOWN , либо требуются права суперпользователя

Вот сценарий, который, вероятно, потребует доработки (пример: миграция из контейнера, созданного root, в непривилегированный), но у меня это работает для этой цели:

#!/usr/bin/env bash

function syntax
{
    echo "SYNTAX: ${0##*/} <from-user> <to-user> <container-name>"
    [[ -n "$1" ]] && echo -e "\nERROR: ${1}."
    exit 1
}

# Checks
[[ -n "$1" ]] || syntax "<from-user> is not set"
[[ -n "$2" ]] || syntax "<to-user> is not set"
[[ -n "$3" ]] || syntax "<container-name> is not set"
[[ "$UID" -eq "0" ]] || syntax "${0##*/}" "You must be superuser to make use of this script"
# Constants with stuff we need
readonly USERFROM=$1
readonly USERTO=$2
shift; shift
readonly CONTAINER=${1:-*}
LXCLOCAL=".local/share/lxc"
readonly HOMEFROM=$(eval echo ~$USERFROM)
readonly HOMETO=$(eval echo ~$USERTO)
readonly LXCFROM="$HOMEFROM/$LXCLOCAL"
readonly LXCTO="$HOMETO/$LXCLOCAL"
readonly GIDBASEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$2}" /etc/subgid)
readonly UIDBASEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$2}" /etc/subuid)
readonly GIDSIZEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$3}" /etc/subgid)
readonly UIDSIZEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$3}" /etc/subuid)
readonly GIDBASETO=$(awk -F : "\$1 ~/$USERTO/ {print \$2}" /etc/subgid)
readonly UIDBASETO=$(awk -F : "\$1 ~/$USERTO/ {print \$2}" /etc/subuid)
readonly GIDSIZETO=$(awk -F : "\$1 ~/$USERTO/ {print \$3}" /etc/subgid)
readonly UIDSIZETO=$(awk -F : "\$1 ~/$USERTO/ {print \$3}" /etc/subuid)
unset LXCLOCAL
# More checks
[[ -d "$LXCFROM" ]] || syntax "Could not locate '$LXCFROM'. It is not a directory as expected"
[[ -e "$LXCTO" ]] && syntax "Destination '$LXCTO' already exists. However, it must not"
for i in GIDBASEFROM UIDBASEFROM GIDBASETO UIDBASETO; do
    (($i > 0)) || syntax "Could not determine base/offset of subordinate UID/GID range"
done
for i in GIDSIZEFROM UIDSIZEFROM GIDSIZETO UIDSIZETO; do
    (($i > 0)) || syntax "Could not determine length of subordinate UID/GID range"
done

echo "Going to migrate container: $CONTAINER"
echo -e "\tfrom user $USERFROM ($HOMEFROM): subUID=${UIDBASEFROM}..$((UIDBASEFROM+UIDSIZEFROM)); subGID=${GIDBASEFROM}..$((GIDBASEFROM+GIDSIZEFROM))"
echo -e "\tto user $USERTO ($HOMETO): subUID=${UIDBASETO}..$((UIDBASETO+UIDSIZETO)); subGID=${GIDBASETO}..$((GIDBASETO+GIDSIZETO))"
while read -p "Do you want to continue? (y/N) "; do
    case ${REPLY:0:1} in
        y|Y)
            break;
            ;;
        *)
            echo "User asked to abort."
            exit 1
            ;;
    esac
done

# Find the UIDs and GIDs in use in the container
readonly SUBGIDSFROM=$(find -H "$LXCFROM" -printf '%G\n'|sort -u)
readonly SUBUIDSFROM=$(find -H "$LXCFROM" -printf '%U\n'|sort -u)

# Change group
for gid in $SUBGIDSFROM; do
    let GIDTO=$(id -g "$USERTO")
    if ((gid == $(id -g "$USERFROM"))); then
        echo "Changing group from $USERFROM ($gid) to $USERTO ($GIDTO)"
        find -H "$LXCFROM/$CONTAINER" -gid $gid -exec chgrp $GIDTO {} +
    elif ((gid >= GIDBASEFROM )) && ((gid <= GIDBASEFROM+GIDSIZEFROM)); then
        let GIDTO=$((gid-GIDBASEFROM+GIDBASETO))
        echo "Changing group $gid -> $GIDTO"
        find -H "$LXCFROM/$CONTAINER" -gid $gid -exec chgrp $GIDTO {} +
    else
        echo "ERROR: Some file/folder inside '$LXCFROM/$CONTAINER' has a group not assigned to $USERFROM (assigned subordinate GIDs)."
        echo -e "Use:\n\tfind -H '$LXCFROM/$CONTAINER' -gid $gid\nto list those files/folders."
        exit 1
    fi
done

# Change owner
for uid in $SUBUIDSFROM; do
    let UIDTO=$(id -u "$USERTO")
    if ((uid == $(id -u "$USERFROM"))); then
        echo "Changing owner from $USERFROM ($uid) to $USERTO ($UIDTO)"
        find -H "$LXCFROM/$CONTAINER" -uid $uid -exec chown $UIDTO {} +
    elif ((uid >= UIDBASEFROM )) && ((uid <= UIDBASEFROM+UIDSIZEFROM)); then
        let UIDTO=$((uid-UIDBASEFROM+UIDBASETO))
        echo "Changing owner $uid -> $UIDTO"
        find -H "$LXCFROM/$CONTAINER" -uid $uid -exec chown $UIDTO {} +
    else
        echo "ERROR: Some file/folder inside '$LXCFROM/$CONTAINER' has an owner not assigned to $USERFROM (assigned subordinate UIDs)."
        echo -e "Use:\n\tfind -H '$LXCFROM/$CONTAINER' -uid $uid\nto list those files/folders."
        exit 1
    fi
done
mv "$LXCFROM/$CONTAINER" "$LXCTO/" || { echo "ERROR: failed to move to destination: ${LXCTO}/${CONTAINER}."; exit 1; }

В дополнение к условиям лицензии сети StackExchange я помещаю это в общественное достояние.Поэтому используйте его повторно и модифицируйте для любых целей, но он предоставляется без каких-либо гарантий, и я не должен нести ответственности за его использование или злоупотребление.

Использование
SYNTAX: lxc-reassign-userns.sh <from-user> <to-user> <container-name>

Предполагается find , sort , uniq , awk ( mawk и gawk должны работать), id , bash , chown , chmod и т. Д., Чтобы быть доступными и понимать все параметры командной строки, которые он использует. Для Bash только чтение и let и арифметические выражения считаются понятными. Для find предполагает, что + является допустимым ограничителем для действия -exec .

Этот список, вероятно, неполный.

Резервные копии

Да, вы можете создавать резервные копии и восстанавливать их в другом месте, если вы также соответствующим образом измените владельца файла и группу.

Однако, если вы используете что-то вроде tar , есть предостережение: tar будет игнорировать сокеты, поэтому $ rootfs / dev / log вызовет проблему. - другие могут также создать аналогичную проблему.

Ресурсы:

2
27.01.2020, 20:18

fuidshiftбыл создан для этой цели. Кажется, это часть LXD.

http://manpages.ubuntu.com/manpages/xenial/man1/fuidshift.1.html

2
27.01.2020, 20:18

Теги

Похожие вопросы