Proteger contentores com o AppArmor

O AppArmor é um módulo de segurança do kernel do Linux que pode usar para restringir as capacidades dos processos em execução no sistema operativo anfitrião. Cada processo pode ter o seu próprio perfil de segurança. O perfil de segurança permite ou não permite capacidades específicas, como o acesso à rede ou as autorizações de leitura/escrita/execução de ficheiros.

Pode usar o AppArmor com os contentores Docker em execução nas suas instâncias do SO otimizado para contentores. Para qualquer contentor, pode aplicar o perfil de segurança do AppArmor predefinido fornecido com o Docker ou um perfil de segurança personalizado que fornecer.

Usar o perfil de segurança AppArmor do Docker predefinido

Quando inicia um contentor na sua instância do SO otimizado para contentores, o sistema aplica automaticamente o docker-defaultperfil de segurança do AppArmor. O seguinte comando de exemplo executa um contentor com o perfil de segurança docker-default:

docker run --rm -it debian:jessie bash -i

Para testar o perfil de segurança docker-default, pode tentar ler o ficheiro /proc/sysrq-trigger com o comando cat, da seguinte forma:

root@88cef496c1a5:/# cat /proc/sysrq-trigger

O resultado deve conter um erro "Permission Denied" (Autorização recusada), semelhante ao seguinte:

cat: /proc/sysrq-trigger: Permission denied

Aplicar um perfil de segurança personalizado

Para aplicar um perfil de segurança diferente, use a opção de linha de comandos apparmor=<profile-name> quando executar o contentor. O comando de exemplo seguinte executa um contentor com um perfil de segurança denominado no-ping:

docker run --rm -i --security-opt apparmor=no-ping debian:jessie bash -i

Consulte a secção Criar um perfil de segurança personalizado mais adiante neste tópico para obter mais informações sobre a criação do perfil no-ping especificado no exemplo.

Também pode especificar unconfined com a opção apparmor para indicar que o contentor deve ser executado sem perfil de segurança, como no seguinte exemplo:

docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i

Ver os perfis de segurança do AppArmor ativos

Pode ver que perfil do AppArmor, se existir, se aplica aos processos na sua instância do SO otimizado para contentores inspecionando o ficheiro /proc/<pid>/attr/current, onde <pid> é o ID do processo.

Suponhamos que tem os seguintes processos em execução na sua instância (apresentados pelo comando ps -ef | grep '[b]ash -i'):

root      1903  1897  0 21:58 pts/3    00:00:00 docker run --rm -it debian:jessie bash -i
root      1927  1913  0 21:58 pts/4    00:00:00 bash -i
root      1978  1001  0 22:01 pts/0    00:00:00 docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i
root      2001  1988  0 22:01 pts/2    00:00:00 bash -i

Se inspecionar /proc/1927/attr/current, deve ver o seguinte resultado que indica que o processo (pid 1927) foi executado com o perfil de segurança do Docker predefinido:

# cat /proc/1927/attr/current
docker-default (enforce)

Se inspecionar /proc/2001/attr/current, deve ver o seguinte resultado que indica que o processo (pid 2001) foi executado sem um perfil de segurança (ou seja, com a opção apparmor=unconfined):

# cat /proc/2001/attr/current
unconfined

Criar um perfil de segurança personalizado

Se o processo exigir um perfil de segurança diferente de docker-default, pode escrever o seu próprio perfil personalizado. Para usar um perfil personalizado, tem de criar o ficheiro de perfil e, em seguida, carregar esse ficheiro para o AppArmor.

Por exemplo, suponhamos que quer um perfil de segurança que não permita todo o tráfego de rede não processado. O seguinte script cria um ficheiro para um perfil de segurança denominado no-ping em /etc/apparmor.d/no_raw_net:

cat > /etc/apparmor.d/no_raw_net <<EOF
#include <tunables/global>

profile no-ping flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>

  network inet tcp,
  network inet udp,
  network inet icmp,

  deny network raw,
  deny network packet,
  file,
  mount,
}
EOF

Depois de criar o ficheiro do perfil de segurança, pode usar apparmor_parser para carregar o perfil no AppArmor:

/sbin/apparmor_parser --replace --write-cache /etc/apparmor.d/no_raw_net

Depois de carregado, pode testar o perfil no-ping da seguinte forma:

$ docker run --rm -i --security-opt apparmor=no-ping debian:jessie ping -c3 8.8.8.8

O comando cria um contentor com o perfil de segurança no-ping e tenta executar ping a partir do contentor. O perfil de segurança deve não permitir o tráfego, o que resulta num erro semelhante ao seguinte:

ping: Lacking privilege for raw socket.

Para garantir que o seu perfil de segurança personalizado está presente quando a instância do SO otimizado para contentores é iniciada e permanece persistente nos reinícios, pode usar cloud-init para instalar o perfil em /etc/apparmor.d. Para tal, adicione um script cloud-config aos metadados da sua instância como o valor da chave user-data.

O seguinte guião cloud-config adiciona o perfil no-ping a /etc/apparmor.d:

#cloud-configs

write_files:
- path: /etc/apparmor.d/no_raw_net
  permissions: 0644
  owner: root
  content: |
    #include <tunables/global>

    profile no-ping flags=(attach_disconnected,mediate_deleted) {
      #include <abstractions/base>

      network inet tcp,
      network inet udp,
      network inet icmp,

      deny network raw,
      deny network packet,
      file,
      mount,
    }

Para garantir que o ficheiro de serviço carrega o seu perfil personalizado no AppArmor e indica ao Docker para o usar, execute os seguintes comandos na sua instância:

ExecStartPre=/sbin/apparmor_parser -r -W /etc/apparmor.d/no_raw_net
ExecStart=/usr/bin/docker run --security-opt apparmor=no-ping ...

Depois de executar os comandos, reinicie a instância e, em seguida, pode executar o contentor confinado pelo seu perfil do AppArmor personalizado.