Привилегированные контейнеры и возможности
Если я запускаю контейнер в привилегированном режиме, имеет ли он все возможности ядра или мне нужно добавить их отдельно?
Ответы
Ответ 1
Работа в привилегированном режиме действительно дает контейнеру все возможности. Но хорошей практикой является всегда предоставлять контейнеру минимальные требования, в которых он нуждается.
Если вы посмотрите документы Docker, они также ссылаются на этот флаг:
Полные возможности контейнера (--privileged)
Флаг --privileged предоставляет все возможности контейнеру, а также снимает все ограничения, налагаемые контроллером cgroup устройств. Другими словами, контейнер может сделать почти все, что может сделать хост. Этот флаг существует, чтобы разрешить особые варианты использования, такие как запуск Docker в Docker.
Вы можете дать определенные возможности, используя --cap-add
. Для получения дополнительной информации об этих возможностях см. man 7 capabilities
возможностей. Могут использоваться буквенные имена, например --cap-add CAP_FOWNER
.
Ответ 2
Вы никогда не хотите запускать контейнер, используя --privileged
.
Я делаю это на моем ноутбуке с накопителями NVMe, но он будет работать для любого хоста:
docker run --privileged -t -i --rm ubuntu:latest bash
Сначала давайте сделаем что-то незначительное, чтобы протестировать файловую систему /proc
Из контейнера:
[email protected]:/# cat /proc/sys/vm/swappiness
60
[email protected]:/# echo "61" > /proc/sys/vm/swappiness
[email protected]:/# cat /proc/sys/vm/swappiness
60
Хорошо, это изменило это для контейнера или для хоста?
$ cat /proc/sys/vm/swappiness
61
OOPS! Мы можем произвольно изменить параметры ядра хоста. Но это всего лишь ситуация в DOS, давайте посмотрим, сможем ли мы собрать привилегированную информацию с родительского хоста.
Давайте /sys
дереву /sys
и найдем младший младший номер для загрузочного диска.
Примечание: у меня есть два диска NVMe и контейнеры, работающие под LVM на другом диске
[email protected]:/proc# cat /sys/block/nvme1n1/dev
259:2
Хорошо, давайте создадим файл устройства в месте, где правила dbus не будут автоматически сканироваться:
[email protected]:/proc# mknod /devnvme1n1 b 259 2
[email protected]:/proc# sfdisk -d /devnvme1n1
label: gpt
label-id: 1BE1DF1D-3523-4F22-B22A-29FEF19F019E
device: /devnvme1n1
unit: sectors
first-lba: 34
last-lba: 2000409230
<SNIP>
Хорошо, мы можем прочитать загрузочный диск, давайте создадим файл устройства для одного из разделов. Хотя мы не можем смонтировать его, так как он будет открыт, мы все равно можем использовать dd
для его копирования.
[email protected]:/proc# mknod /devnvme1n1p1 b 259 3
[email protected]:/# dd if=devnvme1n1p1 of=foo.img
532480+0 records in
532480+0 records out
272629760 bytes (273 MB, 260 MiB) copied, 0.74277 s, 367 MB/s
Хорошо, давайте смонтируем его и посмотрим, сработали ли наши усилия !!!
[email protected]:/# mount -o loop foo.img /foo
[email protected]:/# ls foo
EFI
[email protected]:/# ls foo/EFI/
Boot Microsoft ubuntu
Таким образом, практически любой контейнерный хост, на котором вы позволяете кому-либо запускать контейнер --privileged
аналогичен предоставлению им корневого доступа ко всем контейнерам на этом хосте.
К сожалению, проект Docker выбрал модель доверенных вычислений, и вне плагинов аутентификации нет способа защититься от этого, поэтому всегда добавляйте необходимые функции по сравнению с использованием --privileged
.
Ответ 3
Об этом есть хорошая статья от RedHat.
Хотя Docker-контейнер, работающий как "root", имеет меньше привилегий, чем root на хосте, он все же может нуждаться в усилении защиты в зависимости от вашего варианта использования (использование в качестве среды разработки против общего производственного кластера).