Recentemente, experimentei o Docker na criação de alguns serviços para brincar e uma coisa que me incomoda é colocar senhas em um arquivo Docker. Como sou desenvolvedor, o armazenamento de senhas na fonte parece um soco na cara. Isso deveria ser uma preocupação? Existem boas convenções sobre como lidar com senhas no Dockerfiles?
162
Respostas:
Definitivamente, é uma preocupação. Dockerfiles geralmente são registrados nos repositórios e compartilhados com outras pessoas. Uma alternativa é fornecer credenciais (nomes de usuário, senhas, tokens, qualquer coisa sensível) como variáveis de ambiente em tempo de execução . Isso é possível através do
-e
argumento (para vars individuais na CLI) ou do--env-file
argumento (para várias variáveis em um arquivo) paradocker run
. Leia isto para usar ambiental com docker-compose.--env-file
Definitivamente, usar é uma opção mais segura, pois ela protege contra os segredos que aparecemps
nos logs ou nos logs, se usadosset -x
.No entanto, os env vars também não são particularmente seguros. Eles são visíveis via
docker inspect
e, portanto, estão disponíveis para qualquer usuário que possa executardocker
comandos. (Obviamente, qualquer usuário que tenha acesso aodocker
host também terá raiz, de qualquer maneira.)Meu padrão preferido é usar um script de wrapper como o
ENTRYPOINT
ouCMD
. O script do wrapper pode primeiro importar segredos de um local externo para o contêiner no tempo de execução, depois executar o aplicativo, fornecendo os segredos. A mecânica exata disso varia com base no seu ambiente de tempo de execução. Na AWS, você pode usar uma combinação de funções do IAM, o Key Management Service e o S3 para armazenar segredos criptografados em um bucket do S3. Algo como o HashiCorp Vault ou credstash é outra opção.AFAIK não existe um padrão ideal para o uso de dados confidenciais como parte do processo de construção. Na verdade, eu tenho uma pergunta SO sobre esse tópico. Você pode usar o docker-squash para remover as camadas de uma imagem. Mas não há funcionalidade nativa no Docker para esse fim.
Você pode encontrar comentários de shykes sobre configuração em contêineres úteis.
fonte
.config
arquivo.docker inspect
.docker inspect
. Se o invasor já puder executar o sudo, a retirada de sua senha da inspeção do docker provavelmente está muito baixa na sua lista de coisas que agora podem dar errado. Esse detalhe em particular parece um risco aceitável para mim.Nossa equipe evita colocar credenciais em repositórios, o que significa que eles não podem entrar
Dockerfile
. Nossa prática recomendada nos aplicativos é usar creds de variáveis de ambiente.Nós resolvemos isso usando
docker-compose
.Dentro
docker-compose.yml
, você pode especificar um arquivo que contenha as variáveis de ambiente para o contêiner:Certifique-se de adicionar
.env
a e.gitignore
, em seguida, defina as credenciais no.env
arquivo como:Armazene o
.env
arquivo localmente ou em um local seguro, onde o resto da equipe possa pegá-lo.Consulte: https://docs.docker.com/compose/environment-variables/#/the-env-file
fonte
.gitignore
para que o.env
arquivo com informações confidenciais não seja verificado no GitHub. Eu tenho certeza que isso não vai funcionar se você adicioná-lo.dockerignore
.env
faço o check-in do arquivo e faço uma implantação em um servidor no local, você sugere criar o.env
arquivo novamente no servidor manualmente?O Docker agora (versão 1.13 ou 17.06 e superior) tem suporte para gerenciar informações secretas. Aqui está uma visão geral e uma documentação mais detalhada
Recurso semelhante existe nos kubernetes e no DCOS
fonte
docker secret create
:: criar um segredodocker secret inspect
: exibir informações detalhadas sobre um segredodocker secret ls
: exibir todos os segredosdocker secret rm
: remover um--secret
sinalizador de segredo específico paradocker service create
: criar um segredo durante a criação do serviço--secret-add
e--secret-rm
sinalizadores paradocker service update
: atualizar o valor de um segredo ou remover um segredo durante a tarefa de atualização de serviço. Os segredos do Docker são protegidos em repouso nos nós do gerenciador e provisionados aos nós do trabalhador durante a inicialização do contêiner.Você nunca deve adicionar credenciais a um contêiner, a menos que esteja bem transmitindo os cleds para quem puder fazer o download da imagem. Em particular, fazer e
ADD creds
mais tardeRUN rm creds
não é seguro porque o arquivo creds permanece na imagem final em uma camada intermediária do sistema de arquivos. É fácil para qualquer pessoa com acesso à imagem extraí-la.A solução típica que eu vi quando você precisa de creds para fazer check-out de dependências é usar um contêiner para criar outro. Ou seja, normalmente você tem algum ambiente de construção em seu contêiner base e precisa invocá-lo para criar seu contêiner de aplicativo. Portanto, a solução simples é adicionar a fonte do aplicativo e
RUN
os comandos de compilação. Isso é inseguro se você precisar de ajudaRUN
. Em vez disso, o que você faz é colocar sua origem em um diretório local, execute (como nodocker run
) o contêiner para executar a etapa de construção com o diretório de origem local montado como volume e os cleds injetados ou montados como outro volume. Após a conclusão da etapa de construção, você constrói seu contêiner final simplesmenteADD
inserindo o diretório de origem local que agora contém os artefatos construídos.Espero que o Docker adicione alguns recursos para simplificar tudo isso!
Atualização: parece que o método daqui para frente será ter builds aninhados. Em resumo, o dockerfile descreveria um primeiro contêiner usado para criar o ambiente de tempo de execução e, em seguida, um segundo contêiner aninhado que pode montar todas as peças no contêiner final. Dessa forma, o material em tempo de construção não está no segundo contêiner. Este é um aplicativo Java em que você precisa do JDK para criar o aplicativo, mas apenas do JRE para executá-lo. Há várias propostas em discussão, é melhor começar em https://github.com/docker/docker/issues/7115 e seguir alguns dos links para propostas alternativas.
fonte
Uma alternativa ao uso de variáveis de ambiente, que podem ficar confusas se você tiver muitas delas, é usar volumes para tornar um diretório no host acessível no contêiner.
Se você colocar todas as suas credenciais como arquivos nessa pasta, o contêiner poderá ler os arquivos e usá-los como desejar.
Por exemplo:
Muitos programas podem ler suas credenciais a partir de um arquivo separado; portanto, você pode simplesmente apontar o programa para um dos arquivos.
fonte
solução somente em tempo de execução
docker-compose também fornece uma solução no modo não-enxame (desde a v1.11: Segredos usando montagens de ligação ).
Os segredos são montados como arquivos abaixo
/run/secrets/
pelo docker-compondo. Isso resolve o problema no tempo de execução (executando o contêiner), mas não no tempo de construção (construção da imagem), porque/run/secrets/
não é montado no tempo de construção. Além disso, esse comportamento depende da execução do contêiner com docker-compose.Exemplo:
Dockerfile
docker-compose.yml
Para construir, execute:
Leitura adicional:
fonte
Com o Docker v1.9, é possível usar a instrução ARG para buscar argumentos passados pela linha de comando para a imagem na ação de compilação . Simplesmente use o sinalizador --build-arg . Portanto, você pode evitar manter uma senha explícita (ou outras informações confidenciais) no arquivo Docker e passá-las rapidamente.
fonte: https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg
Exemplo:
Dockerfile
comando build image
durante a construção imprimir
Espero que ajude! Tchau.
fonte
--build-arg var=secret
a passagem de uma chave privada SSH para uma imagem, não há justificativa documentada. Alguém pode explicar isso?docker history
expõebuild-arg
/ARG
variáveis. Pode-se extrair qualquer imagem, inspecioná-la e ver quaisquer segredos passados durante a compilação como um parâmetrobuild-arg
/ARG
.Minha abordagem parece funcionar, mas provavelmente é ingênua. Diga-me porque está errado.
Os ARGs configurados durante a construção do docker são expostos pelo subcomando history, portanto, não é necessário ir para lá. No entanto, ao executar um contêiner, as variáveis de ambiente fornecidas no comando executar estão disponíveis para o contêiner, mas não fazem parte da imagem.
Portanto, no Dockerfile, faça a instalação que não envolve dados secretos. Defina um CMD de algo parecido
/root/finish.sh
. No comando run, use variáveis de ambiente para enviar dados secretos para o contêiner.finish.sh
usa as variáveis essencialmente para concluir as tarefas de construção.Para facilitar o gerenciamento dos dados secretos, coloque-os em um arquivo carregado pela janela de encaixe executada com o
--env-file
comutador. Obviamente, mantenha o arquivo em segredo..gitignore
e tal.Para mim,
finish.sh
executa um programa Python. Ele verifica se não foi executado antes e termina a instalação (por exemplo, copia o nome do banco de dados no Djangosettings.py
).fonte
Há um novo comando do docker para gerenciamento de "segredos". Mas isso só funciona para grupos de enxames.
fonte
A metodologia do aplicativo de 12 fatores informa que qualquer configuração deve ser armazenada em variáveis de ambiente.
A composição do Docker pode fazer a substituição de variáveis na configuração, para que possa ser usada para passar senhas do host para o docker.
fonte
Embora eu concorde totalmente, não há uma solução simples. Continua a haver um único ponto de falha. O dockerfile, etcd e assim por diante. O Apcera tem um plano que se parece com o ajudante - autenticação dupla. Em outras palavras, dois contêineres não podem falar, a menos que haja uma regra de configuração do Apcera. Na demonstração, o uid / pwd estava limpo e não pôde ser reutilizado até que o administrador configurasse a ligação. Para que isso funcione, no entanto, provavelmente significou corrigir o Docker ou, pelo menos, o plug-in de rede (se houver).
fonte