O que significa se um contêiner Linux (contêiner LXC) é chamado de "não privilegiado"?
O que significa se um contêiner Linux (contêiner LXC) é chamado de "não privilegiado"?
Respostas:
Os contêineres LXC não privilegiados são os que utilizam os espaços de nome de usuário ( usuários ). Ou seja, de um recurso do kernel que permite mapear um intervalo de UIDs no host para um espaço de nome dentro do qual um usuário com UID 0 pode existir novamente.
Ao contrário da minha percepção inicial de contêineres LXC sem privilégios por um tempo, isso não significa que o contêiner precise pertencer a um usuário host sem privilégios. Essa é apenas uma possibilidade.
Relevante é:
usermod [-v|-w|--add-sub-uids|--add-sub-gids]
)lxc.id_map = ...
)Assim, root
pode possuir até contêineres sem privilégios, pois os UIDs efetivos dos processos de contêiner no host terminarão dentro do intervalo definido pelo mapeamento.
No entanto, root
é necessário definir os IDs subordinados primeiro. Ao contrário dos usuários criados via adduser
, root
não terá um intervalo de IDs subordinados definidos por padrão.
Lembre-se também de que toda a gama fornecida está à sua disposição, para que você possa ter três contêineres com as seguintes linhas de configuração (apenas o mapeamento UID mostrado):
lxc.id_map = u 0 100000 100000
lxc.id_map = u 0 200000 100000
lxc.id_map = u 0 300000 100000
supondo que ele root
possua os UIDs subordinados entre 100000 e 400000. Toda a documentação encontrada sugere o uso de 65536 IDs subordinados por contêiner, alguns usam 100000 para torná-lo mais legível para humanos.
Em outras palavras: você não precisa atribuir o mesmo intervalo a cada contêiner.
Com mais de 4 bilhões (~ 2^32
) de IDs subordinados possíveis, significa que você pode ser generoso ao negociar os intervalos subordinados aos usuários do host.
Para esfregar isso de novo. Um convidado LXC sem privilégio não precisa ser executado por um usuário sem privilégio no host.
Configurando seu contêiner com um mapeamento UID / GID subordinado assim:
lxc.id_map = u 0 100000 100000
lxc.id_map = g 0 100000 100000
onde o usuário root
no host possuir esse intervalo de ID subordinado, permitirá restringir os convidados ainda melhor.
No entanto, há uma vantagem adicional importante nesse cenário (e sim, eu verifiquei que funciona): você pode iniciar automaticamente seu contêiner na inicialização do sistema.
Normalmente, ao vasculhar a Web em busca de informações sobre o LXC, você será informado de que não é possível iniciar automaticamente um convidado LXC sem privilégios. No entanto, isso só é verdade por padrão para os contêineres que não estão no armazenamento de contêineres em todo o sistema (geralmente algo parecido /var/lib/lxc
). Se eles são (o que geralmente significa que foram criados pela raiz e iniciados pela raiz), é uma história totalmente diferente.
lxc.start.auto = 1
fará o trabalho muito bem, depois de colocá-lo na sua configuração de contêiner.
Lutei com isso um pouco, então estou adicionando uma seção aqui.
Além do snippet de configuração incluído por meio do lxc.include
qual geralmente se chama o nome /usr/share/lxc/config/$distro.common.conf
(onde $distro
está o nome de uma distribuição), você deve verificar se há também um /usr/share/lxc/config/$distro.userns.conf
no seu sistema e incluí-lo também. Por exemplo:
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
Além disso, adicione os mapeamentos de ID subordinado:
lxc.id_map = u 0 100000 65535
lxc.id_map = g 0 100000 65535
o que significa que o host UID 100000 está root
dentro do espaço de nome do usuário do convidado LXC.
Agora verifique se as permissões estão corretas. Se o nome do seu convidado fosse armazenado na variável de ambiente, $lxcguest
você executaria o seguinte:
# Directory for the container
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest
chmod ug=rwX,o=rX $(lxc-config lxc.lxcpath)/$lxcguest
# Container config
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest/config
chmod u=rw,go=r $(lxc-config lxc.lxcpath)/$lxcguest/config
# Container rootfs
chown 100000:100000 $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
chmod u=rwX,go=rX $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
Isso deve permitir que você execute o contêiner após sua primeira tentativa ter causado alguns erros relacionados à permissão.
chroot
isso, pode ajudar, mas o LXC combina vários espaços de nome (UTS, montagem etc ...) para conter o sistema inteiro.
unshare
isso já é admirável em todos / todos os vários namespaces - e você ainda recebe uma /proc
montagem privada e separada com um único switch cli. Se seu aplicativo único é init
e você chroot
é initramfs
, você recebe um contêiner inteiro em segundos.
Para followup em 0xC0000022L, cuja solução funcionou bem para mim, eu escrevi um increase-uid-gid.pl script Perl para automatizar a propriedade necessária alterações necessárias para que os arquivos dentro dos recipientes LXC estão devidamente mapeada.
Sem ele, com esta configuração proposta, um arquivo dentro de rootfs de contêiner LXC pertencentes a 0 / root no host principal será, dentro do próprio contêiner LXC, mapeado para 65534 / ninguém. Para serem mapeados para 0 / root no contêiner LXC, eles devem pertencer a 100000 no host.
Isso é descrito aqui https://yeupou.wordpress.com/2017/06/23/setting-up-lxc-containers-with-mapped-giduid/ e o script pode ser obtido diretamente no gitlab https://gitlab.com /yeupou/stalag13/blob/master/usr/local/bin/increase-uid-gid.pl
lxc
não é uma necessidade para esse tipo de coisa. Você pode criar um recipiente namespace de qualquer tipo utilizando autil-linux
ferramentaunshare
. Você pode entrar no referido contêiner usando autil-linux
ferramentansenter
. A última ferramenta também permite adicionar processos em execução a um contêiner já criado a partir dele. O suporte ao namespace é implementado no kernel.