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

У меня установлена ​​установка сервера Ubuntu 14.04, которая действует как хост LXC. Он имеет двух пользователей: user1 и user2.

user1 владеет непривилегированным контейнером LXC, который использует каталог (внутри /home/user1/.local / …) в качестве хранилища резервных копий.

Как сделать полную копию контейнера для пользователя2? Я не могу просто скопировать файлы, потому что они сопоставлены с владельцами от 100000 до 100000 + что-то, что связано с user1.

Кроме того, я считаю, в основном, тот же вопрос, как я могу безопасно сделать резервную копию контейнера LXC моего user1, чтобы восстановить его позже на другом компьютере и / или пользователе?

  • Как повлиять на назначение подчиненных UID / GID при создании учетных записей пользователей?
  • Построение непривилегированных (userns) контейнеров LXC с нуля, путем переноса привилегированного контейнера в непривилегированный
  • Что делает firefox внутри контейнера запускает новое окно firefox снаружи на хосте с UID хост-пользователя? Разве это не странно для LXC?
  • Что такое непривилегированный контейнер LXC?
  • контейнер userns не запускается, как отслеживать причину?
  • Подчиненные GIDs / UID с LXC и для непривилегированного пользователя?
  • Не удается подключиться к sshd у моего непривилегированного гостя LXC. Что делать?
  • У меня проблемы с анализом причины этого (firefox) segfault
  • 2 Solutions collect form web for “Перенести непривилегированный контейнер LXC между пользователями”

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

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

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

    1. хост имеет user1 и user2 , если информация не является конкретной для одного, мы будем использовать userX
    2. контейнер будет называться переменной, которую мы будем отображать как $container
    3. домашние папки для user1 и user2 будут указаны в обозначениях, известных из Bash как ~user1 и ~user2 .
    4. мы будем предполагать, что подчиненные диапазоны UID и GID равны 100000..165536 для user1 и 200000..265536 для пользователя2 только для краткости
    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 хоста, назначенных пользователю1 и user2 соответственно.

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

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

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

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

     #!/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 readonly и let и арифметические выражения предполагаются понятными. Для find предполагает, что + является допустимым терминатором для -exec действия.

    Этот список, вероятно, не завершен.

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

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

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

    Ресурсы:

    • subuid(5)
    • subgid(5)
    • newuidmap(1)
    • newgidmap(1)
    • user_namespaces(7)

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

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

    Linux и Unix - лучшая ОС в мире.