Moby: Segredos: escrever melhores práticas, fazer e não fazer, roteiro

Criado em 26 mai. 2015  ·  203Comentários  ·  Fonte: moby/moby

O tratamento de segredos (senhas, chaves e relacionados) no Docker é um tópico recorrente. Muitas solicitações pull foram 'sequestradas' por pessoas que queriam (mal) usar um recurso específico para lidar com segredos.

Até agora, nós apenas _desencorajamos_ as pessoas a usar esses recursos, porque eles são comprovadamente inseguros ou não foram projetados para lidar com segredos, portanto, "possivelmente" inseguros. Nós _não_ oferecemos a eles alternativas reais, pelo menos não para todas as situações e _se_, então sem um exemplo prático.

Eu só acho que "segredos" é algo que foi deixado por muito tempo. Isso resulta em usuários (erroneamente) usando recursos que não são projetados para isso (com o efeito colateral de que as discussões ficam poluídas com solicitações de recursos nesta área) e fazendo com que eles pulem obstáculos apenas para poderem trabalhar com segredos.

Recursos / hacks que são (mal) usados ​​para segredos

Esta lista provavelmente está incompleta, mas vale a pena mencionar

  • Variáveis ​​de ambiente . Provavelmente o mais utilizado, pois faz parte do "aplicativo 12 fatores" . Variáveis ​​de ambiente são desencorajadas, porque elas são;

    • Acessível por qualquer processo no contêiner, portanto, facilmente "vazado"

    • Preservado nas camadas intermediárias de uma imagem e visível no docker inspect

    • Compartilhado com qualquer contêiner vinculado ao contêiner

  • Variáveis ​​de ambiente de tempo de construção (https://github.com/docker/docker/pull/9176, https://github.com/docker/docker/pull/15182). As variáveis ​​de ambiente de tempo de construção não foram projetadas para lidar com segredos. Por falta de outras opções, as pessoas estão planejando usá-los para isso. Para evitar dar a _impressão_ de que eles são adequados para segredos, foi decidido não criptografar deliberadamente essas variáveis ​​no processo.
  • Mark .. Squash / Flatten layers . (https://github.com/docker/docker/issues/332, https://github.com/docker/docker/pull/12198, https://github.com/docker/docker/pull/4232, https : //github.com/docker/docker/pull/9591). A compressão de camadas removerá as camadas intermediárias da imagem final; no entanto, os segredos usados ​​nessas camadas intermediárias ainda irão parar no cache de compilação.
  • Volumes . Algumas pessoas do IIRC foram capazes de usar o fato de que os volumes são recriados para cada etapa de construção, permitindo que armazenem segredos. Não tenho certeza se isso realmente funciona e não consigo encontrar a referência de como isso é feito.
  • Construindo contêineres manualmente . Ignore o uso de um Dockerfile e crie manualmente um contêiner, confirmando os resultados em uma imagem
  • Hacks personalizados . Por exemplo, hospedar segredos em um servidor, curl -ing os segredos e removê-los depois, tudo em uma única camada. (consulte também https://github.com/dockito/vault)

Então, o que é necessário?

  • Adicione documentação sobre o que fazer e não fazer ao lidar com segredos; @diogomonica fez alguns comentários excelentes em https://github.com/docker/docker/pull/9176#issuecomment -99542089
  • Descreva a forma oficialmente "endossada" / aprovada de lidar com segredos, se possível, usando os recursos _correntes_
  • Fornece um roteiro / design para lidar oficialmente com segredos, podemos querer torná-lo plugável, para que não tenhamos que reinventar a roda e usar as ofertas existentes nesta área, por exemplo, Vault , Keywiz , Sneaker

O acima deve ser escrito / projetado com os segredos de tempo de construção e tempo de execução em mente

@calavera criou uma prova de conceito rápida e suja sobre como os novos Drivers de Volume (https://github.com/docker/docker/pull/13161) poderiam ser usados ​​para isso; https://github.com/calavera/docker-volume-keywhiz-fs

Observação: as variáveis ​​de ambiente são usadas como o padrão de fato para passar configurações / definições, incluindo segredos para contêineres. Isso inclui imagens oficiais no Docker Hub (por exemplo, MySQL , WordPress , PostgreSQL ). Essas imagens devem adotar as novas 'melhores práticas' quando escritas / implementadas.

Em boa tradição, aqui estão algumas propostas mais antigas para lidar com segredos;

aresecurity statuneeds-attention

Comentários muito úteis

Sei que está fora do assunto, mas alguém mais notou que esta edição já está ativa há quase um ano! Amanhã é seu aniversário. 👏

Todos 203 comentários

ping @ewindisch @diogomonica @NathanMcCauley Este é apenas um rápido artigo. Sinta-se à vontade para modificar / atualizar a descrição se achar que isso é necessário :)

@ dreamcat4 existem alguns planos para implementar uma "API secreta" genérica, que permitiria usar o Vault, o Keywiz ou você-nome-lo com o Docker, mas tudo da mesma maneira. É apenas uma ideia inicial, por isso exigirá pesquisas adicionais.

@thaJeztah Sim, desculpe, não quero diminuir esses esforços / discussão de forma alguma. Estou mais pensando que talvez seja um exercício útil também (como parte desse processo mais longo e enquanto esperamos) para ver até onde podemos ir agora. Em seguida, mostra mais claramente para os outros os limites e deficiências do processo atual. O que está faltando e mais precisa ser adicionado para melhorar os segredos.

Também vale a pena considerar as diferentes situações de segredos de tempo de execução VS segredos de tempo de construção. Para o qual também existe uma área de sobreposição de área.

E talvez também (para docker) também valha a pena considerar as limitações (prós / contras) entre as soluções que fornecem um mecanismo para lidar com os segredos "na memória". Ao contrário de métodos de segredos baseados em arquivos mais pesados ​​ou baseados em rede, por exemplo, servidor de segredos locais. Quais são os hacks atuais na mesa (até a API segredos adequada). Isso pode nos ajudar a entender alguns dos valores exclusivos (por exemplo, de segurança mais forte) adicionados por uma API de segredos do docker que não poderia ser obtida usando hacks no conjunto de recursos do docker atual. No entanto, não sou um especialista em segurança. Portanto, não posso comentar sobre essas coisas com tanta certeza.

@ dreamcat4 sim, você está certo; para o curto prazo, esses links são realmente úteis.

Também vale a pena considerar as diferentes situações de segredos de tempo de execução VS segredos de tempo de construção. Para o qual também existe uma área de sobreposição de área.

Obrigado! Acho que tinha isso na minha descrição original, devo ter me perdido no processo. Vou adicionar uma bala

No entanto, não sou um especialista em segurança.

Nem eu, é por isso que "pinguei" os mantenedores da segurança; IMO, isso deve ser algo escrito por eles 😇

@thaJeztah ótimo resumo. Vou tentar cutucar isso sempre que tiver tempo.

@diogomonica embora não esteja _diretamente_ relacionado, há uma longa solicitação de recurso aberta para encaminhar o agente de chave SSH durante a compilação; https://github.com/docker/docker/issues/6396 dado o número de comentários, seria bom pensar nisso também. (Se for para tomar uma decisão sobre se pode / deve ser implementado ou não)

Supondo que você pudesse montar volumes como um usuário diferente de root (eu sei que é impossível, mas me dê graça), essa seria uma abordagem favorável para colocar segredos em contêineres?

Nesse caso, eu advogaria por uma alternativa para -v host_dir:image_dir que espera o uso de um contêiner somente de dados e pode ser semelhante a -vc host_dir:image_dir (ou seja, cópia de volume) em que o conteúdo de host_dir é copiado para o volume image_dir no contêiner somente de dados.

Poderíamos então enfatizar um paradigma secure-data-only containers e permitir que esses volumes sejam criptografados

Recentemente li um bom artigo sobre isso de @jrslv, onde ele propõe construir uma imagem docker especial com segredos apenas para construir seu aplicativo e, em

Então você tem dois Dockerfiles:

  • Dockerfile.build (aqui você simplesmente copia todos os seus segredos)
  • Dockerfile.dist (este você enviará para o registro)

Agora podemos construir nossa distribuição assim:

# !/bin/sh
docker build -t hello-world-build -f Dockerfile.build .
docker run hello-world-build >build.tar.gz 
docker build -t hello-world -f Dockerfile.dist ^

Seus segredos estão seguros, já que você nunca empurra hello-world-build imagem.

Eu recomendo ler o artigo @jrslv para mais detalhes http://resources.codeship.com/ebooks/continuous-integration-continuous-delivery-with-docker

Obrigado por compartilhar @kepkin !
Acabei de ler o artigo. Muito conciso!

Gosto da ideia de exportar os arquivos e carregá-los por meio de um Dockerfile separado. É como se estivesse comprimindo sem o problema de "camadas intermediárias no cache de construção".

No entanto, estou nervoso com a possibilidade de complicar o desenvolvimento e exigir um terceiro Dockerfile para simplificar.

@kepkin sem ofensa, mas isso não faz sentido. Definitivamente, os segredos não são seguros, pois estão no tarball e o tarball está sendo ADD ed para a imagem de produção - mesmo se você remover o tarball, sem comprimir, ele vazará em alguma camada.

@TomasTomecek se eu entendi o exemplo corretamente, o tarball _não_ é as camadas de imagem, mas apenas o binário que foi construído dentro do contêiner de compilação. Veja por exemplo; https://github.com/docker-library/hello-world/blob/master/update.sh (nenhum segredo envolvido aqui, mas apenas um exemplo simples de um contêiner de construção)

@TomasTomecek Estou falando sobre os segredos para a construção de imagens Docker. Por exemplo, você precisa passar a chave ssh para verificar o código-fonte do seu repositório GitHub privado. E o tarball contém apenas artefatos de construção, mas não contém a chave do GitHub.

@kepkin certo, agora li sua postagem novamente e posso vê-la. Desculpe por isso. Infelizmente, isso não resolve o problema quando você precisa de segredos durante a implantação / construção da imagem de distribuição (por exemplo, buscar artefatos e autenticar com serviço de artefato). Mas é definitivamente uma boa solução para separação entre o processo de construção e o processo de liberação.

@TomasTomecek é exatamente como eu

Na imagem Docker.build, faço o download de algumas dependências binárias da imagem do Amazon S3 que exigem chave e segredo AWS. Depois de recuperar e construir, eu crio um tarball com tudo que preciso.

Existe um artigo canônico sobre "melhores práticas" - os "Faça" conforme informado aos "Não Faça" - que vocês recomendariam ler?

Vale a pena notar (para qualquer outra pessoa como eu que esteja se deparando com isso) que o Docker Compose tem suporte para uma opção env_file .

https://docs.docker.com/compose/compose-file/#env -file

O próprio http://docs.docker.com/engine/reference/commandline/run/#set -environment-variables-e-env-env-file, mas esses env-vars ainda irão aparecem nos mesmos lugares, então não faça diferença por "vazamento"

@kepkin é assim que passo uma chave ssh para docker build :

# serve the ssh private key once over http on a private port.
which ncat
if [ "$?" = "0" ]; then
  ncat -lp 8000 < $HOME/.ssh/id_rsa &
else
  nc -lp 8000 < $HOME/.ssh/id_rsa &
fi
nc_pid=$!
docker build --no-cache -t bob/app .
kill $nc_pid || true

e dentro do Dockerfile, em que 172.17.0.1 é o IP do docker gateway:

RUN \
  mkdir -p /root/.ssh && \
  curl -s http://172.17.0.1:8000 > /root/.ssh/id_rsa && \
  chmod 600 /root/.ssh/id_rsa && chmod 700 /root/.ssh && \
  ssh-keyscan -t rsa,dsa github.com > ~/.ssh/known_hosts && \
  git clone --depth 1 --single-branch --branch prod [email protected]/app.git . && \
  npm i --production && \
  ... && \
  rm -rf /root/.npm /root/.node-gyp /root/.ssh

Se alguem tiver algo mais simples nos avise.

Então, qual é o status atual disso?

Durante todo o verão houve longas cadeias de conversas, indicando o quão disseminada é essa preocupação. Isso foi arquivado em maio e ainda está aberto. Por exemplo, como eu definiria a senha do Postgres?

@thaJeztah O que pode ser feito para levar isso adiante? Acho que muitos olhos em diferentes projetos downstream estão voltados para essa questão ... ej. https://github.com/rancher/rancher/issues/1269

Acho que o que está sendo feito aqui é mantido _secreto_: D

Este é o maior problema para nós por integrar o Docker em nossa pilha de produção. Existe um roteiro ou outro documento em algum lugar que aponta para algum progresso nesse sentido?

Algum conteúdo relevante sobre este tópico de k8s .

O que você acha disso como uma forma potencial de abordar os segredos do tempo de execução?
https://github.com/docker/docker/issues/19508

Acho que esse problema seria melhor abordado concentrando-se em alguns cenários que precisam ser suportados e certificando-se de que haja um conjunto de instruções para cada um. Como eles são implementados é menos importante do que se, no final do processo, há um conjunto coerente de recursos que podem ser combinados para preencher a necessidade.

Alguns que eu vi serem mencionados que parecem ser preocupações bastante legítimas incluem:

Credenciais de tempo de execução

  • Informações de usuário / senha coordenadas entre dois contêineres que compartilham um link
  • As informações são fáceis de manter fora do seu repositório git
  • É fácil manter as informações fora das imagens enviadas (e os contêineres locais?)
  • É fácil manter as informações fora de .bash_history (possivelmente uma ponte muito longe?)
  • Alguns aplicativos esperam segredos como parte de um arquivo de configuração que contém outras informações
  • Alguns aplicativos esperam segredos como uma variável de ambiente
  • Alguns aplicativos permitem ambos

Quando digo 'fácil', quero dizer que há uma abordagem ergonomicamente sã para lidar com essas variáveis ​​que protege o usuário de fazer acidentalmente a coisa errada e acionar um boletim de segurança. O estresse da experiência frequentemente fica associado (leia-se: atribuído a culpa) as ferramentas envolvidas no erro.

Credenciais de tempo de construção

  • O projeto é construído a partir de um ou mais repositórios privados (ex: package.json permite urls git)
  • O construtor pode estar atrás de um proxy protegido por senha
  • O construtor pode estar usando um cache protegido por senha
  • O usuário final só se preocupa com uma imagem de trabalho (ou seja, eles usarão pull ou FROM, nunca docker build )
  • É fácil manter as informações fora das imagens enviadas

1ª Edição:

Documentação do que é ou não "vazado" em uma imagem típica, contêiner

  • Quais arquivos acabam na imagem (apenas a CÓPIA e o ADICIONE? Mais alguma coisa?)
  • O que a docker-machine mantém após a criação de uma imagem (especialmente boot2docker, mas e as outras?)
  • Como as variáveis ​​de ambiente e de linha de comando são capturadas na imagem e onde são capturadas
  • Expectativas dos emissores de RP em relação à mudança desses comportamentos

Eu sinto que estou perdendo alguns grandes aqui. Alguém tem algo que esqueci?

Chaves de API para quaisquer serviços json.

Por exemplo (e este é meu caso de uso real), Docker build compila um programa, a API Key é necessária para me autenticar e fazer upload do (s) produto (s) de build para Bintray.com.

@ dreamcat4 Eu poderia estar muito longe do que você está dizendo, mas aqui vai:

Você está falando sobre usar imagens docker para compilações de implantação contínua e enviar os artefatos de compilação para um arquivo no final de uma compilação bem-sucedida? Pessoalmente, prefiro fazer isso mais para cima (por exemplo, um script de pós-construção no Jenkins), mas se você estiver compilando de forma cruzada, isso pode ser um pouco mais complicado.

No meu mundo, o agente de compilação apenas cria binários / arquivos e os retém como 'artefatos' do processo de compilação, e outra coisa os empurra para a infraestrutura, marca o repositório git etc. Isso me dá um backup de emergência dos artefatos se eu tenho um problema de produção e, digamos, meu repositório npm, docker ou Artifactory está inativo para atualizações ou a rede está com problemas em mim.

O que eu estava tentando enfatizar era sobre o uso de chaves de API em geral. Existem muitos serviços JSON / rest online diferentes e variados com os quais um contêiner pode precisar interagir (tanto no tempo de construção quanto no tempo de execução) ... o que requer chaves de API. Não precisa ser especificamente relacionado à construção.

@dreamcat oh, então tokens de autenticação para endpoints REST? Você acha que eles são tratados de maneira substancialmente diferente do que, digamos, sua senha do postgres em um arquivo conf, ou você os trataria de forma semelhante?

Sim, acho que esses dois tipos devem ser considerados de forma diferente em termos de avaliação de seu nível mínimo básico de segurança.

Os tokens de autenticação de API costumam ser:

  • Não são senhas
  • Pode ser revogado
  • Alguns (um subconjunto muito menor) são de uso único - jogue fora. E, essencialmente, invalidá-los.
  • Freqüentemente, os serviços de API são limitados em seu escopo a apenas um subconjunto de funcionalidade. (ou seja, somente leitura ou só pode desencadear uma ação específica).

As senhas tendem a ser / são frequentemente:

  • Para um acesso / controle de conta mais completo.
  • Uma vez comprometido, pode ser alterado pelo invasor para outra coisa (bloqueio). Ou outra backdoor inserida (como modificação de banco de dados de outras contas mantidas no banco de dados, no caso de SQL).
  • Ser uma senha representa um risco muito alto de "reutilização da mesma senha" entre outras contas. As chaves de API do Wheras tendem a ser sempre exclusivas e não podem ser usadas para mais nada.

Portanto, isso não significa necessariamente que a solução secreta _deve ser diferente_ para esses 2 tipos. Apenas que o nível básico mínimo aceitável de segurança pode ser um pouco menor para chaves de API.

Este nível mínimo é importante se ter uma segurança forte for mais complexo / problemático de configurar. (o que pode ser verdade aqui no caso de segredos do docker, ou não dependendo de quão viável / elegante a solução).

E, ocasionalmente, as chaves API de senhas podem ter segurança mais forte / mais fraca. Apenas isso se um tamanho único não for possível.

Por exemplo - minha chave de API bintray: que é mantida no mesmo repositório .git que meu Dockerfile. Portanto, para mantê-lo seguro, ele é mantido no repositório git PRIVATE (acessado via SSH). Portanto, obter acesso à chave API é relativamente bem protegida lá. No entanto, sem que o docker tenha qualquer funcionalidade / proteção própria de segredos incorporados, a imagem do docker incorporada sempre inclui a chave de API em texto simples. Portanto, a imagem de compilação do Docker resultante deve ser mantida privada como o repositório git ... o que tem uma repercussão (efeito indesejável) que ninguém mais pode ver / ver publicamente os logs de compilação / status de compilação lá.

Bem, isso não é ideal de muitas maneiras. Mas a solução geral é bastante simples e realmente funciona (como em: ontem). Se houvesse um mecanismo melhor feito no futuro, eu consideraria mudar para ele. Mas não se esse mecanismo fosse significativamente mais caro / complexo de configurar do que a solução atual que já criei. Portanto, a segurança extra-forte (embora bem-vinda) pode ser um exagero no caso de apenas 1 chave de API. Que apenas precisa ser mantido fora do cache de camadas de imagem do docker com algum tipo de nova opção / comando do Dockerfile NOCAHCE.

Onde uma senha precisa de algo como cofre ou cofre-ansible e deve ser criptografada com outra senha ou outro mecanismo de autenticação fortemente seguro. (O que esperamos que não, mas pode ser uma coisa complexa de configurar).

Acho que um modelo cliente / servidor (como no vault ) para gerenciar e otimizar (leia-se: auditoria, quebra de vidro) todas as coisas relacionadas a segredos seria uma boa prática e cobriria a maioria dos casos de uso, se a implementação fosse feita com cuidado. Eu, pessoalmente, não sou fã de adotar uma abordagem não holística, porque esta é uma oportunidade de subir a barra nas melhores práticas.

Isso implica em um cliente de longa execução (responsabilidade da pessoa que implementa uma imagem) e / ou um cliente de tempo de construção (responsabilidade do construtor). Talvez o anterior possa ser transferido para o daemon do docker de alguma forma, o que fornece segredos autorizados em tempo de execução.

Na verdade - concordo plenamente com o comentário anterior. Não que eu não admire as formas criativas com que as pessoas estão resolvendo o problema, mas não acho que seja assim - vamos tentar e pensar em uma solução que poderia ser usada tanto durante CI / D quanto em tempo de execução , além de levar em consideração que os contêineres podem ser orquestrados por Mesos / Kubernetes etc.

Bem, acho que um pouco de documentação ainda seria útil aqui, uma vez que o Docker apresenta algumas torções extras no espaço do problema.

Parece que talvez os caras do Vault também estejam olhando para isso do lado deles. Acho que esse tíquete é o único a se observar:

https://github.com/hashicorp/vault/issues/165

Talvez isso seja algo em que possamos colaborar.

@jdmarshall

Talvez isso seja algo em que possamos colaborar.

+1

+1 Docker + Hashi Corp Vault

Desculpe, mas eu não gosto de como as soluções estão ficando mais complexas à medida que mais pessoas participam. Hashi Corp Vault, por exemplo, é uma solução cliente-servidor completa com armazenamento de back-end criptografado. Isso adiciona partes móveis consideráveis. Tenho certeza de que alguns casos de uso exigem esse nível de complexidade, mas duvido que a maioria sim. Se a solução concorrente é usar variáveis ​​de ambiente de host, tenho quase certeza de quais acabarão sendo usadas pela maioria dos desenvolvedores.

Estou procurando uma solução que cobre o desenvolvimento (por exemplo: chaves github) e implantação (por exemplo: chaves de certificação nginx, credenciais de banco de dados). Não quero poluir o host com env vars ou ferramentas de construção e, claro, nenhum segredo deve acabar no github (não criptografado) ou em um diretório de imagem do docker, mesmo que seja privado.

@gittycat Concordo com você no sentido de que provavelmente existem vários casos de uso distintos. Em que algumas das soluções devem ser mais simples do que outras.

Certamente devemos evitar recorrer a ENV vars.

Minha preferência é inclinar-se para a ideia de que o armazenamento de chave simples pode ser alcançado com algo semelhante ao mecianismo de "abóbada" do ansible. Onde você tem um arquivo de texto criptografado mantido dentro do contexto de construção (ou fontes fora / junto com o contexto de construção). Então, uma chave de desbloqueio pode desbloquear quaisquer senhas de texto simples ou chaves de API, etc. desse arquivo.

Só estou dizendo isso depois de usar a solução de "cofre" do próprio anisible. O que é relativamente indolor / simples. O cofre de Hashicorp é mais seguro, mas também é mais difícil de configurar e geralmente mais complexo. Embora eu não saiba de nenhuma razão técnica pela qual você ainda não poderia usar isso por baixo como back-end (ocultar / simplificar atrás de uma ferramenta de linha de comando orientada para docker).

Eu sugeriria armazenamento de arquivos local porque evita a necessidade de configurar algum servidor de armazenamento de chave HTTP complexo e potencialmente não confiável. O armazenamento de segredos é uma questão de segurança, portanto, deve estar disponível para todos os usuários, não apenas para empresas. Apenas minha opinião de 2 centavos.

+1 para um back-end de armazenamento de arquivo local, para casos de uso mais avançados, no entanto, eu preferiria o poder total de uma solução semelhante à do Hashicorp Vault. Quando falamos de implantação, em uma organização, o argumento é que as pessoas que fornecem e controlam os segredos são outras pessoas que não aquelas que os usam. Esta é uma medida de segurança comum para manter o círculo de pessoas com poder de controle limitado a engenheiros de segurança muito confiáveis ​​...

Não sei se isso serve ou funcionaria, mas aqui está uma sugestão de leftfield para resolver o caso em que desejo injetar um segredo em um contêiner em tempo de execução (por exemplo, uma senha postgres)

Se eu pudesse substituir em docker run time o ponto de entrada e configurá-lo para um script de minha escolha, por exemplo, / sbin / get_secrets, que após obter segredos de um mecanismo de minha escolha (por exemplo, KMS), executaria o ponto de entrada original (tornando-se um mero invólucro cujo único propósito era configurar variáveis ​​de ambiente com segredos DENTRO do contêiner. Esse script poderia ser fornecido em tempo de execução por meio de uma montagem de volume. Tal mecanismo não envolveria segredos jamais sendo gravados no disco ( um dos meus odeia o animal de estimação), ou vazamento pelo docker (não faz parte do docker inspect), mas garantiria que eles existissem apenas dentro do ambiente do processo 1 dentro do contêiner, que mantém o 12-factorness.

Você já pode fazer isso (eu acredito) se o entrypoint não for usado nos metadados da imagem, mas apenas o cmd é, como o entrypoint então envolve o comando. Conforme mencionado, o wrapper pode ser montado em tempo de execução por meio de um volmount. Se o entrypoint já for usado nos metadados da imagem, então acho que você não pode fazer isso no momento, a menos que seja possível ver o que o entrypoint original era de dentro do contêiner (não a substituição do cmdline) - não tenho certeza se você pode fazer isso ou não .

Finalmente, acho que seria possível fornecer uma chave única criptografada via injeção env var tradicional com a qual o / sbin / get_secrets externo poderia usar para solicitar os segredos reais (por exemplo, a senha do postgres), adicionando assim uma proteção extra no docker vazando a chave única.

Eu não consigo descobrir se isso é apenas camadas sobre camadas, ou se isso potencialmente resolve o problema ... desculpas se apenas o primeiro.

@thaJeztah - Posso confirmar que a solução que

@gtmtech Interessante. Gostaria de saber como você descobriu qual era o ponto de entrada original no binário get secrets.

Talvez uma pasta de código de exemplo tornasse a abordagem um pouco mais fácil de demonstrar / entender.

Exemplo de código e cenários de trabalho aqui @ dreamcat4 @kaos >

https://github.com/gtmtechltd/secret-squirrel

Posso estar errado, mas por que esses métodos complicados? Eu confio nas permissões de arquivo unix padrão. Passe todos os segredos para o docker com -v /etc/secrets/docker1:/etc/secrets legível apenas pelo root e então há um script em execução na inicialização do contêiner como root, que passa os segredos para locais apropriados para programas relevantes (por exemplo, configuração do apache). Esses programas eliminam as permissões de root na inicialização para que, se hackeados, não possam ler o segredo de propriedade do root posteriormente. Este método que uso é de alguma forma falho?

Obrigado @gtmtech :)
Infelizmente, não temos um ponto de entrada padrão, nem sou capaz de executar o docker inspect antes de executá-lo de maneira controlada. Mas gosto da sua abordagem.

Posso estar errado, mas por que esses métodos complicados? Eu confio nas permissões de arquivo unix padrão. Passe todos os segredos para o docker com -v / etc / secrets / docker1: / etc / secrets legíveis apenas pelo root e então há um script em execução na inicialização do contêiner como root, que passa os segredos para locais apropriados para programas relevantes (por exemplo apache config). Esses programas eliminam as permissões de root na inicialização para que, se hackeados, não possam ler o segredo de propriedade do root posteriormente. Este método que uso é de alguma forma falho?

Oi,
Eu concordo e acho que essa abordagem ^^ deve ser geralmente recomendada como a melhor maneira para segredos do RUNTIME. A menos que alguém aqui tenha uma forte objeção contra isso. Depois do que pode então, subsequentemente, também listar quaisquer casos de canto restantes (em RUNTIME) que não são cobertos por esse ^^.

Infelizmente, não consigo ver o esquilo secreto decolando porque é simplesmente muito complicado para a maioria das pessoas comuns não técnicas aprender e adotar uma estratégia popular.

Então isso deixa (você provavelmente já adivinhou) ...
Segredos de tempo de construção!

Mas acho que isso é um progresso! Já que depois de muito tempo sem chegar a lugar nenhum, talvez corte as coisas pela metade e resolva aproximadamente 45-50% do problema total.

E se ainda houver problemas remanescentes em torno dos segredos, pelo menos eles serão mais específicos / focados e podem continuar progredindo / resolvendo depois.

Sim, não irei entrar em muitos detalhes, mas essas abordagens nunca funcionariam para uma situação na qual estou trabalhando atualmente, porque preciso de um nível de segurança mais alto do que eles fornecem. Por exemplo, nenhum segredo não criptografado no disco, nenhuma chave de descriptografia válida depois de descriptografada no processo de destino, rotação de criptografia regular e repositório único para segredos criptografados (e não espalhados pelos servidores). Portanto, é mais para pessoas que precisam ter esse nível de segurança que sugeri uma abordagem possível.

secret_squirrel é, de qualquer maneira, um hack em um espaço onde ainda não consigo ver nenhuma solução viável, em torno do docker ainda não fornecendo uma API de segredos ou um driver de secrets plugável, o que espero que em algum momento, mas talvez sirva para ilustrar essa configuração ENV vars dentro do contêiner antes da execução do processo, mas não como parte do processo de criação do docker (ou metadados) é uma maneira segura de ser compatível com 12 fatores com segredos, e talvez a comunidade de desenvolvimento do docker possa usar essa ideia quando começar a construir um secrets-api / driver se eles acham que é um bom!

Feliz encaixe!

Temos usado o tipo de abordagem que @gtmtech descreve, com grande sucesso. Injetamos segredos criptografados por KMS por meio de variáveis ​​de ambiente e, em seguida, deixamos o código dentro do contêiner ser descriptografado conforme necessário.

Normalmente, isso envolve um ponto de entrada de shim simples, na frente do aplicativo. Atualmente, estamos implementando esse shim com uma combinação de shell e um pequeno binário Golang (https://github.com/realestate-com-au/shush), mas gosto do som da abordagem pure-Go.

@gtmtech @mdub Eu definitivamente ficaria feliz em ver mais disso.
@ dreamcat4 Acho que a definição de "complicado" pode ser dependente do caminho, o que obviamente está bem. No entanto, provavelmente não pode ser um julgamento abstraível. Portanto, no entanto, um invólucro de segurança dentro do contêiner do docker não parece algo muito complicado para mim no nível de design. Outro aspecto são as práticas recomendadas: elas precisam ser analisadas não da perspectiva apenas do desenvolvedor, mas da perspectiva da operação.
meus 2 centavos

Vault +1

Vault -1. O Vault tem algumas características operacionais (não lacrado) que o tornam realmente indesejável para muitas pessoas.

Ter uma API conectável faria mais sentido.

Há também o cofre do ansible. Essa é uma besta bem diferente.

@gtmtech obrigado pela sugestão, inspirou-me a escrever este ponto de entrada:

#!/bin/bash

if [ -d "/var/secrets" ]; then
  tmpfile="$(mktemp)"
  for file in /var/secrets/*
  do
    if [ -f $file ]; then
      file_contents=$(cat $file)
      filename=$(basename "$file")
      underscored_filename="${filename//-/_}"
      capitalized_filename=${underscored_filename^^}
      echo "export $capitalized_filename=$file_contents" >> $tmpfile
    fi
  done

  source $tmpfile
  rm -f $tmpfile
fi

exec "$@"

Acabei de adicioná-lo ao Dockerfile assim (não se esqueça de chmod + x nele):

ENTRYPOINT ["/app/docker-entrypoint.sh"]

E voila. ENV vars disponíveis em tempo de execução. Bom o bastante :)

Se bem entendi, o dir /var/secrets deve ser montado por meio de volumes certo ??
Além disso, quando há comentários sobre os segredos não sendo gravados no disco, quão ruim é gravá-los no disco e excluí-los ??

Agradável! Você deve usar shred para excluir o arquivo com segurança.

Na quinta-feira, 3 de março de 2016, Juan Ignacio Donoso [email protected]
escreveu:

Se bem entendi, o diretório / var / secrets deve ser montado por meio de
volumes certo ??
Além disso, quando há comentários sobre segredos não sendo gravados no disco, como
ruim é gravá-los no disco e excluí-los ??

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/docker/issues/13490#issuecomment -191887424.

Rui Marinho

Inspirado pelo "esquilo secreto" de @gtmtech , estendi minha ferramenta de gerenciamento secreto "shush" para torná-la utilizável como um ponto de entrada de imagem:

ADD shush_linux_amd64 /usr/local/bin/shush
ENTRYPOINT ["/usr/local/bin/shush", "exec", "--"]

Isso descriptografa quaisquer KMS_ENCRYPTED_xxx envariables e injeta os resultados de volta no ambiente.

https://github.com/realestate-com-au/shush#use -as-a-command-shim

Portanto, o tópico começa com NÃO FAÇA NENHUMA DESSAS COISAS .....

... mas não vejo nenhuma POR FAVOR FAÇA ESTAS COISAS EM VEZ ... apenas várias propostas / hacks que foram rejeitados / fechados em sua maioria.

Qual é a melhor prática oficial no momento? Como um usuário docker, é um tanto frustrante ver uma longa lista de coisas que não devemos fazer, mas não temos alternativas oficiais oferecidas. Estou esquecendo de algo? Não existe um? Tenho certeza de que as coisas estão acontecendo nos bastidores e que isso é algo em que a equipe do docker está trabalhando, mas, a partir de agora, como faremos melhor para lidar com o gerenciamento de segredos até que uma solução canônica seja apresentada?

@alexkolson
Pelo que eu entendi, se você precisa de segredos em tempo de execução, você deve usar volumes (segredos do sistema de arquivos) ou alguns serviços como o HashiCorp Vault (segredos de rede).

Para segredos de tempo de construção, é mais complicado.
Volumes não são suportados em tempo de construção, então você deve usar contêineres para executar comandos que modificam o sistema de arquivos e usar docker commit.

Portanto, o que está faltando é a capacidade de gerenciar segredos no tempo de compilação usando nada, exceto um Dockerfile, sem a necessidade de usar docker commit .

Algumas pessoas até dizem que usar o sistema de arquivos para segredos não é seguro e que o docker daemon deve fornecer alguma API para fornecer segredos com segurança (usando rede / firewall / volume montado automaticamente?). Mas ninguém tem uma ideia de como essa API seria e como alguém a usaria.

Quando penso nas deficiências de env vars, penso em questões específicas não relacionadas ao docker, como:

  1. Agregar logs que capturam todos os env vars ou um phpinfo esquecido deixado em um servidor web de produção - portanto, tome cuidado com os segredos e configure corretamente.
  2. Talvez um trojan que expõe env vars - portanto, não execute software não confiável.
  3. Ataques que exploram fraquezas, como injeção de sql - valide a entrada e use um firewall de aplicativo da web.

Os pontos fracos apresentados no topo deste tópico:

Acessível por qualquer processo no contêiner, portanto, facilmente "vazado"

Aplicar cruzado 1 e 2 a partir de cima. Legit, mas tratado com ser cuidadoso, certo? Além disso, seu contêiner docker executa muito menos processos do que um servidor web full stack.

E quanto à configuração em env var, mas env vars secretos têm valores criptografados e o aplicativo tem a chave no código? Isso é apenas ofuscação, porque a chave está no código, mas exigiria exploits para obter acesso aos vars key e env. Talvez use o gerenciamento de configuração para gerenciar a chave no host docker em vez do código do aplicativo. Pode ajudar em processos de rouge e vazamentos acidentais, mas obviamente não em ataques de injeção de alguém que tenha a chave.

Preservado nas camadas intermediárias de uma imagem e visível no docker inspect

As pessoas estão preparando env vars para imagens do docker em vez de definir em tempo de execução ou estou interpretando mal este. Nunca transformar segredos em artefatos, certo? Sim sudo docker inspect container_name dá o env var, mas se você estiver no meu servidor de produção, então o iv já foi perdido. sudo docker inspect image_name não tem acesso ao meu env vars definido em tempo de execução.

Compartilhado com qualquer contêiner vinculado ao contêiner

Que tal não usar links e a nova rede em vez disso?

O único problema que parece ser um problema do docker e não universal são os links ...

Coloque-me no campo das pessoas que precisam de uma boa maneira de lidar com segredos durante docker build . Usamos o composer para alguns projetos php e referenciamos alguns repositórios privados do github para dependências. Isso significa que se quisermos construir tudo dentro de contêineres, serão necessárias chaves ssh para acessar esses repositórios privados.

Não encontrei uma maneira boa e sensata de lidar com essa situação sem derrotar algumas das outras coisas que considero benéficas sobre o docker (ver: docker squash ).

Agora tive que regredir na construção de partes do aplicativo fora do contêiner e usando COPY para trazer o produto final para o contêiner. Meh.

Acho que docker build precisa de alguma funcionalidade para lidar com dados efêmeros, como segredos, para que eles não encontrem o caminho para o contêiner de envio final.

Acho que o docker build precisa de alguma funcionalidade para lidar com dados efêmeros como segredos

Este é um problema filosófico e não técnico. Esses dados efêmeros anulariam o benefício essencial de docker: reprodutibilidade.

A filosofia do Docker é que seu Dockerfile junto com um contexto é suficiente para construir uma imagem.
Se você precisa que um contexto esteja fora da imagem resultante, você deve buscá-lo na rede e pular a gravação no sistema de arquivos. Porque cada linha do Dockerfile resulta em um instantâneo do sistema de arquivos.

Se os segredos não deveriam fazer parte de uma imagem, você poderia executar um contêiner efêmero, que espelharia / representaria como proxy todos os seus recursos protegidos por segredo e forneceria acesso sem segredo. Espelhando, btw tem outro fundamento lógico: https://developers.slashdot.org/story/16/03/23/0652204/how-one-dev-broke-node-and-thousands-of-projects-in-11-lines -of-javascript

Você também pode compartilhar a própria chave ssh, mas não seria capaz de controlar seu uso.

@ bhamilton-idexx se você se certificar de que a autenticação para seus repositórios privados funciona com um token de curta duração, você não precisa se preocupar com a persistência do segredo na imagem do docker.
Você faz com que o sistema de compilação gere um token com ttl de 1 hora, torne-o disponível como uma variável de ambiente para a compilação do docker.
Você pode obter os detalhes de compilação necessários, mas o segredo expira logo após a conclusão de suas compilações, fechando esse vetor de ataque.

Tenho lido muitos desses tópicos agora e um recurso que resolveria alguns casos de uso aqui e teria casos de uso fora dos segredos é um sinalizador --add para docker run que copia um arquivo para o contêiner, assim como a instrução ADD em Dockerfiles

Esse é realmente um ótimo artigo. Muito boa leitura. E exatamente o tipo de coisa que esperávamos ver.

POR FALAR NISSO:

Também encontrei algumas outras ferramentas secretas que parecem não constar do artigo. Desculpe por quaisquer repetições / duplicação. Ainda não os notei mencionados aqui:

Segredos de tempo de construção:

https://github.com/defunctzombie/docket

Segredos de tempo de execução:

https://github.com/ehazlett/docker-volume-libsecret

O que as pessoas pensam? Muito Obrigado.

Para mim:

Essas ferramentas mais novas ^^ parecem muito boas agora. E eles certamente não existiam quando começamos este tíquete. MAS o que mais sinto falta agora é:

Ter uma capacidade melhor para segredos de tempo de construção no DockerHub. O que é ruim lá e obriga a uma escolha ou ou. Devemos renunciar aos benefícios de uma solução pelos benefícios da outra. Dependendo de qual conjunto geral de recursos são mais importantes. Como a construção local é definitivamente melhor para manter os segredos seguros, mas compreensivelmente pior do que o Dockerhub de outras maneiras.

Escrevemos outra ferramenta, semelhante ao docket, que usa o novo formato de imagem:

https://github.com/AngryBytes/docker-surgery

Nossa implementação primeiro cria uma camada contendo segredos comentados SECRETS , então cria uma cópia do Dockerfile com um FROM modificado, constrói e finalmente remove todas as SECRETS camadas da imagem resultante.

Sempre há advertências para hackear isso, e seria ótimo se o docker tivesse uma funcionalidade de rebase ou emenda de camada embutida. Remover camadas intermediárias agora é lento, porque todas as soluções têm que fazer uma dança docker save / docker load nos bastidores.

Além disso, o cache de construção está quebrado. No momento, usamos docker commit para criar a camada de segredos comentada, mas manter um cache adequado dessas camadas ainda dá muito trabalho, o que provavelmente não faremos. Usar um Dockerfile para criar a camada de segredos pode resolver isso, mas não há como comentar a camada, tornando difícil apontar o que remover depois.

@Vanuan [Dockerfile] não pode ter reprodutibilidade. O comando RUN garante que você e eu não podemos esperar obter a mesma imagem exata em duas execuções. Porque? Porque na maioria das vezes as pessoas usam RUN para acessar recursos de rede. Se você quer a mesma imagem que eu, você precisa criar sua própria imagem 'DE' minha. Nenhum outro arranjo nos dará as mesmas imagens. Nenhum outro arranjo pode nos dar as mesmas imagens. Toda reprodutibilidade durável vem do Docker Hub, não do Dockerfile.

Se a única defesa de por que não podemos ter dados efêmeros é porque o Docker acha que pode remover todos os dados efêmeros, você deve descontinuar a instrução RUN.

@stephank Eu implementei uma ferramenta de compilação docker no trabalho que tem uma abordagem um pouco diferente. Minha principal preocupação não era com os segredos do tempo de construção, mas ela cuida disso também (manter os segredos fora da imagem construída, ou seja, como você obtém os segredos em primeiro lugar, ainda depende de você).

E isso rodando um "gerenciador de compilação" com o código do projeto em um VOLUME. O gerente então executa qualquer número de ferramentas de construção em contêineres separados que montam o código do projeto usando volumes do gerente. Portanto, quaisquer artefatos construídos e outros arquivos produzidos são mantidos no volume do gerenciador e seguem ao longo do pipeline de construção para cada etapa de construção. No final, o gerente pode construir uma imagem de produção final usando o resultado de construção produzido. Todos os segredos necessários ao longo do caminho estão disponíveis no gerenciador e / ou nos contêineres de construção, mas não na imagem final. Nenhum assistente de imagem do docker é usado e os caches de construção funcionam conforme o esperado.

A aparência do pipeline de construção depende inteiramente do projeto, usando um arquivo de especificação que configura os requisitos de construção.

Na verdade, estou bastante entusiasmado com esta ferramenta, estou apenas esperando que possamos lançá-la como código aberto (as diretrizes da política da empresa estão pendentes para serem adotadas).

@kaos Por um lado, eu não queria me desviar do estoque de ferramentas Docker. Por outro lado, acho que realmente deveria haver mais competição entre as ferramentas de construção de imagens. Isso parece interessante! 😀

@thaJeztah para

@alexkolson Acho que a chave para este tópico é "NÃO FAÇA ISSO", a menos que você tenha atenuado X, Y, Z. É claramente uma questão de engenharia - sempre haverá "soluções" para problemas comuns. Dito isso, a educação sobre o que não fazer e por que é importante para que as verdadeiras soluções alternativas possam começar. O diabo está sempre nos padrões - por isso, precisamos garantir que os novos usuários entendam o que está em risco.

Talvez alguns de vocês possam me ajudar porque eu não tenho muita experiência com docker ainda.
Eu usei um Hashicorps Vault para buscar meus segredos.

O que eu basicamente fiz foi passar um token como um argumento de construção e o token pode ser usado para buscar informações confidenciais do Vault. Isso acontece no momento da construção e só pode ser bem-sucedido se o estado do Vault estiver "sem lacre" (aberto para buscar dados). Após a construção, o token usado é revogado.

Mas acho que ainda estou enfrentando alguns problemas comuns.

  • Tenho que criar novas imagens se dados confidenciais mudarem
  • Se minha imagem foi roubada / hackeada, então os dados confidenciais estão dentro da imagem.

É possível encontrar o token usado com docker inspect, mas não pode mais ser usado.
Eu fiz a escolha de selar e desbloquear o cofre do hashicorps apenas no momento da construção para limitar o acesso ao armazenamento de segredos tanto quanto possível. Eu também não vi uma opção para manter os segredos salvos ao buscar dados em tempo de execução.

Então, o quão ruim eu fiz (não há problema em dizer se eu errei muito;)) alguém tem dicas e truques para eu tornar as coisas mais seguras?

@weemen AFAIK armazenar segredos em sua imagem também não é uma boa ideia. Sua imagem não deve ter credenciais incorporadas (incluindo tokens do Vault). Em vez disso, use o back-end de autenticação de app-id do Vault para seus contêineres para obter segredos no tempo de carregamento. Armazene-os na memória do contêiner de alguma forma, dependendo da pilha de aplicativos que você está usando.

Além disso, o Vault está trabalhando em um back-end de autenticação do aws que será útil no futuro se você estiver usando a AWS como um provedor de nuvem.

@ jaredm4 Pode esclarecer esta afirmação ?:

"Em vez disso, use o back-end de autenticação de id de aplicativo do Vault para seus contêineres para obter segredos no tempo de carregamento. Armazene-os na memória do contêiner de alguma forma, dependendo da pilha de aplicativos que você está usando."

Ainda não tenho certeza de quando / onde recuperar os segredos do Vault (ou Keywhiz, etc). Isso é feito antes da execução do docker e passado para o comando run? Isso está acontecendo em algum ponto durante a inicialização do contêiner (em caso afirmativo, algum exemplo)? Meu aplicativo deve recuperá-los quando necessário? Por exemplo, meu aplicativo rails precisa de chaves de API do Google, escrevo algo dentro do rails para chamar o vault quando as chaves são necessárias?

Acho que estou claro sobre a necessidade de usar algo como o Vault e como configurá-lo, mas não sei como consumir o serviço e obter meus arquivos yml atualizados e prontos quando o Rails for inicializado.

Qualquer orientação aqui seria apreciada. Obrigado

Claro, @mcmatthew , embora deva começar dizendo que ainda estou tentando dominar o Vault, então minha experiência é bem leve.

A maneira como tenho tentado codificar é que a única informação que você passa para o contêiner é algo necessário para que seu código possa ser autenticado com o Vault. Se você estiver usando um back-end de id de aplicativo, seria o próprio app-id e o endereço do seu Vault.

Na inicialização do contêiner, seu aplicativo Rails notará que ainda não tem segredos e deve buscá-los no Vault. Ele tem o app-id e precisará gerá-lo de alguma forma user-id . Essa geração de ID de usuário precisará ser determinada por você, mas sua documentação sugere que "geralmente é um valor exclusivo para uma máquina, como um endereço MAC ou ID de instância, ou um valor hash desses valores exclusivos."

Uma vez que seu aplicativo Rails tem o app-id e o user-id prontos, ele pode usar a API do Vault para / login. A partir daí, você pode fazer chamadas de API para obter os segredos necessários.

Agora, para esclarecer o que eu quis dizer sobre armazená-los na memória - isso varia dependendo do tipo de aplicativo que você está usando, mas com Rails deve haver uma maneira de armazenar seus segredos em um cache de variável de usuário que permitirá que Rails acesse o segredos da memória a cada solicitação, em vez de obtê-los do Vault repetidamente (o que, como você pode imaginar, seria lento). Dê uma olhada neste guia sobre armazenamento em cache no Rails. Ou seja, a seção 2.0, mas garantindo que está usando memory_cache e não disco.

Por último, certifique-se de que, independentemente do código, faça no Rails e não com um script de ponto de entrada especial do Docker ou similar. O Rails deve detectar segredos na memória e, se não existirem, buscá-los.

Espero que ajude. Eu sei, um nível um pouco alto, mas é assim que planejamos lidar com isso.

O que não está claro é o que deve ser mantido em segredo, id do aplicativo, id do usuário ou ambos.

Ok, a resposta é https://www.vaultproject.io/docs/auth/app-id.html
Mas ainda não está claro por que ele é mais seguro do que apenas o acesso por firewall.
Talvez seja porque cada segredo de host deve ser vinculado ao segredo do aplicativo (política)?
Ou seja, se você tiver acesso ao segredo do host, poderá acessar certos aplicativos se souber seus nomes secretos?

Agora precisamos armazenar 2 tokens em algum lugar?

@Vanuan Ambos devem ser mantidos o mais secretos possível, sim.

O objetivo principal do app-id é restringir o acesso a certos segredos dentro do Vault por meio de políticas. Qualquer pessoa com acesso ao app-id ganha acesso aos segredos das políticas desse app-id. O app-id deve ser fornecido por sua estratégia de implantação. Por exemplo, se estiver usando Chef, você pode defini-lo nos pacotes de parâmetros (ou CustomJSON para OpsWorks). No entanto, por si só, ele não permitirá que ninguém acesse o Vault. Assim, alguém que obtivesse acesso ao Chef não seria capaz de acessar o Vault.

O ID do usuário NÃO é fornecido pelo Chef e deve ser vinculado a máquinas específicas. Se o seu aplicativo for dimensionado de forma redundante entre as instâncias, cada instância deve ter seu próprio ID de usuário. Realmente não importa de onde esse id de usuário se origina (embora eles dêem sugestões), mas não deve vir do mesmo lugar que implantou o id de aplicativo (ou seja, Chef). Como eles disseram, pode ser programado, apenas por outros meios. Qualquer software usado para dimensionar instâncias pode fornecer IDs de usuário para os containers instances / docker e autorizar o ID do usuário para o app-id. Isso também pode ser feito manualmente, se você não dimensionar suas instâncias dinamicamente. Cada vez que um humano adiciona uma nova instância, eles criam um novo id de usuário, autorizam-no para o id-app e o fornecem para a instância através dos meios que melhor os combinam.

Isso é melhor do que instâncias de firewall? Acho que depende. O firewall não restringe o acesso aos segredos no Vault (afaik) e, se alguém obtiver acesso às suas instâncias, poderá facilmente entrar no Vault.

Dessa forma, é difícil para eles pegar todas as peças do quebra-cabeça. Para dar um passo adiante, app-id também permite blocos CIDR que você deve usar. Se alguém, de alguma forma, obtiver a id do aplicativo e a id do usuário, ainda não conseguirá acessar o Vault sem estar nessa rede.

(Novamente, esta é minha interpretação depois de grocar a documentação o melhor que pude)

@Vanuan @mcmatthew ótimas perguntas! @ jaredm4 muito obrigado por esse esclarecimento, isso certamente vai me ajudar. Isto é muito útil para todos os que procuram uma implementação mais prática !! Se eu tiver tempo em algum lugar nas próximas duas semanas, então tentarei novamente!

@thaJeztah :

Acessível por qualquer processo no contêiner, portanto, facilmente "vazado"

Você pode apoiar esta afirmação? Os processos não privilegiados não podem acessar as variáveis ​​de ambiente dos processos não pais. Veja https://help.ubuntu.com/community/EnvironmentVariables#Process_locality.

Variáveis ​​de ambiente definidas para o contêiner (via --env ou --env-file ) _são_ acessíveis por qualquer processo no contêiner.

Claro, já que são filhos do processo de ponto de entrada. É o trabalho desse processo, ou você no caso de ser, por exemplo, um shell, remover as variáveis ​​de ambiente secretas o mais rápido possível.

O que é mais relevante é se os processos com um ID de usuário diferente de 0 podem acessar essas variáveis ​​de ambiente dentro e / ou fora do contêiner. Este também não deve ser o caso, quando o software que você usa dentro do contêiner perde privilégios de maneira adequada.

Sei que está fora do assunto, mas alguém mais notou que esta edição já está ativa há quase um ano! Amanhã é seu aniversário. 👏

Seria possível para um processo de contêiner ler as variáveis ​​env na memória do processo e, em seguida, desmarcá-las (no ambiente)? Isso corrige a maioria das questões de segurança em tempo de execução?

@davibe, o problema com isso é que se o contêiner ou seu (s) processo (s) reiniciar (m), esses env vars desaparecem, não há como recuperá-los.

Eu tentei, mas parece que env vars ainda estão lá após o relançamento.

dade<strong i="6">@choo</strong>:~/work/grocerest(master)$ cat test.js
console.log("FOO value: " + process.env.FOO);
delete(process.env.FOO);
console.log("FOO value after delete: " + process.env.FOO);

dade<strong i="7">@choo</strong>:~/work/grocerest(master)$ docker run --name test -it -e FOO=BAR -v $(pwd):/data/ node node /data/test.js
FOO value: BAR
FOO value after delete: undefined

dade<strong i="8">@choo</strong>:~/work/grocerest(master)$ docker restart test
test

dade<strong i="9">@choo</strong>:~/work/grocerest(master)$ docker logs test
FOO value: BAR
FOO value after delete: undefined
FOO value: BAR
FOO value after delete: undefined

talvez docker-run esteja executando meu trabalho como um filho de bash? Eu acho que não deveria ..

@davibe :

unset 'SECRET_ENV_VAR'

Acho que o principal problema / característica em tudo isso é que você efetua login no Docker como root , portanto, qualquer coisa que você colocar dentro de um contêiner pode ser inspecionada, seja um token, um volume, uma variável, uma chave de criptografia. .. nada.

Portanto, uma ideia seria remover sudo e su de seu contêiner e adicionar um comando USER antes de qualquer ENTRYPOINT ou CMD . Qualquer um que esteja executando o seu contêiner não deve ter a chance de executar como root (se não estou errado) e, portanto, agora você pode realmente esconder algo dele.

Outra ideia (melhor IMHO) seria adicionar a noção de usuários e grupos ao soquete Docker e aos contêineres, de modo que você pudesse dizer ao GRUPO-A tem acesso aos contêineres com TAG-B e USUÁRIO-C pertence ao GRUPO- A para ter acesso a esses contêineres. Pode até ser uma permissão por operação (GROUP-A tem acesso para iniciar / parar para TAG-B, GROUP-B tem acesso para exec, GROUP-C tem acesso para rm / inspect e assim por diante).

Depois de pesquisar isso por algumas horas, não posso acreditar que parece não haver nenhuma solução oficialmente recomendada ou solução alternativa para segredos de tempo de compilação, e algo como https://github.com/dockito/vault parece ser a única opção viável para segredos de tempo de construção (exceto para esmagar toda a imagem resultante ou construí-la manualmente em primeiro lugar). Infelizmente https://github.com/dockito/vault é bastante específico para as chaves ssh, então vou tentar adaptá-lo para hospedar arquivos de armazenamento de credenciais https git também ...

Depois do que pareceu uma eternidade (originalmente eu ouvi que estava programado para o lançamento do quarto trimestre de 2015), o AWS ECS parece ter finalmente cumprido sua promessa de trazer funções IAM para aplicativos docker . Aqui está a postagem do

Parece que isso, combinado com algumas vantagens do KMS, é uma solução viável a curto prazo. Em teoria, você só precisa vincular os segredos a certas funções principais / IAM para evitar que as funções de não autenticação solicitem algo que não deveriam e deixar o armazenamento seguro para o KMS.

Ainda não experimentei, mas está na minha pequena lista ...

O Kubernetes também parece ter uma manipulação de segredos que me lembra muito os bancos de dados criptografados do Chef.

Eu entendo que este não é o modo OSS independente da plataforma que é o ponto principal deste tópico,
mas queria lançar essas duas opções para as pessoas jogando nesses espaços de infraestrutura que precisam de algo _NOW_

Acabei de encontrar algo que pode ajudar nesse sentido: https://github.com/docker/docker/pull/13587

Parece que está disponível a partir do docker v1.10.0, mas eu não tinha notado até agora. Acho que a solução que estou buscando neste ponto é usar https://www.vaultproject.io/ para armazenar e recuperar os segredos, armazenando-os dentro do contêiner em um sistema de arquivos tmpfs montado em / secrets ou algo dessa natureza . Com o novo recurso ECS habilitando funções IAM em contêineres, acredito que devo poder usar a autenticação AWS EC2 do vault para proteger a autorização para os próprios segredos. (Para plataforma independente, posso estar inclinado a ir com a autenticação do ID do aplicativo.)

Em qualquer caso, a peça que faltava para mim era onde guardar os segredos com segurança assim que fossem recuperados. A opção tmpfs parece boa para mim. A única coisa que falta é que o ECS não parece suportar esse parâmetro ainda, por isso enviei isso hoje: https://github.com/aws/amazon-ecs-agent/issues/469

Todos juntos, isso parece uma solução bastante abrangente IMHO.

@CameronGo , obrigado pelo ponteiro. Se bem entendi, isso não pode ser usado bem na construção, ou pode?

@NikolausDemmel desculpe sim, você está correto. Esta é apenas uma solução para segredos de tempo de execução, não para o tempo de construção. Em nosso ambiente, os segredos de tempo de construção são usados ​​apenas para recuperar código do Git. Jenkins lida com isso para nós e armazena as credenciais para acesso Git. Não tenho certeza se a mesma solução atende às necessidades de todos aqui, mas não estou certo sobre outros casos de uso para segredos de tempo de construção.

Jenkins lida com isso para nós e armazena as credenciais para acesso Git.

Como isso funciona com o docker? Ou você não git clone dentro do próprio contêiner?

Depois de ler este problema na íntegra, acredito que seria muito benéfico ser dividido em problemas separados para segredos de "tempo de construção" e "tempo de execução", que têm requisitos muito diferentes

Se você é como eu e veio aqui tentando decidir o que fazer agora, então FWIW descreverei a solução que estabeleci, até que algo melhor apareça.

Para segredos de tempo de execução, decidi usar http://kubernetes.io/docs/user-guide/secrets/. Isso só funciona se você usar kubernetes. Caso contrário, o vault parece ok. Qualquer coisa secreta na imagem gerada ou na camada temporária é uma má ideia.

Com relação aos segredos de tempo de construção - não consigo pensar em outro caso de uso de segredos de tempo de construção além da distribuição de código privado. Neste ponto, não vejo melhor solução do que confiar em realizar qualquer coisa "secreta" no lado do host e ADICIONAR o pacote / jar / wheel / repo / etc gerado. para a imagem. Salvar um LOC que gera o pacote no lado do host não vale o risco de expor as chaves ssh ou a complexidade do servidor proxy em execução, conforme sugerido em alguns comentários.

Talvez adicionar um sinalizador "-v" ao docker build, semelhante ao sinalizador docker run, funcione bem? Ele compartilharia temporariamente um diretório entre o host e a imagem, mas também asseguraria que ele apareceria vazio no cache ou na imagem gerada.

Atualmente, estou trabalhando em uma solução usando o Vault :

  1. A máquina Builder tem o Vault instalado e um token salvo localmente
  2. Quando a compilação é iniciada, a máquina do construtor solicita um novo token temporário válido apenas por minutos (com base na compilação, 1h seria até aceitável)
  3. Injeta o token como argumento de compilação
  4. A imagem do Docker também tem o Vault instalado (ou o instala e remove durante a compilação) e usando esse token, ele pode buscar os segredos reais

É importante que os segredos sejam removidos dentro do mesmo comando, para que quando o docker armazena em cache a camada fornecida, não haja sobras. (Isso, claro, só se aplica a segredos de tempo de construção)

Eu não construí isso ainda, mas estou trabalhando nisso.

Algo relacionado ao comentário de @kozikow : "Com relação aos segredos de tempo de construção - não consigo pensar em outro caso de uso de segredos de tempo de construção que não seja a distribuição de código privado."

Talvez não seja um segredo de tempo de compilação especificamente, mas tenho uma necessidade de caso de uso para (proteger) uma senha durante o tempo de compilação em um Dockerfile para permitir que um artefato já compilado seja baixado por meio de um comando RUN curl. O download em tempo de compilação requer credenciais do usuário para autenticar a fim de obter o artefato - então, passamos a senha como uma variável de ambiente no Dockerfile agora (ainda estamos no Dev). As compilações acontecem nos bastidores automaticamente, conforme usamos o OpenShift, e as variáveis ​​de ambiente no Dockerfile são geradas nos logs durante a compilação, como qualquer comando de compilação do docker. Isso torna a senha visível para qualquer pessoa que tenha acesso aos logs, incluindo nossos desenvolvedores. Tenho tentado desesperadamente descobrir uma maneira de enviar a senha para que ela possa ser usada durante a compilação do docker, mas não ter a saída da senha para os logs ou acabar em qualquer camada.

Também concordo com o que

Acho que pode valer a pena definir alguns testes para qualquer mecanismo secreto (em tempo de execução) que seja criado por qualquer pessoa. Porque há muitas pessoas neste tópico que defendem uma segurança muito fraca.

Para começar, sugiro:

  • O segredo não aparece no docker inspect
  • Após o início do processo 1, o segredo não fica disponível em nenhum arquivo acessível a partir do contêiner (incluindo arquivos montados em volume)
  • O segredo não está disponível em / proc / 1 / cmdline
  • O segredo é transmitido ao contêiner de forma criptografada

Qualquer solução sugerida acima que viole um desses é problemática.

Se pudermos chegar a um acordo sobre uma definição de qual comportamento um segredo deve seguir, então pelo menos isso eliminará infinitas soluções que não são adequadas ao propósito.

@gtmtech ótimas sugestões :)

Após o início do processo 1, o segredo não fica disponível em nenhum arquivo acessível a partir do contêiner (incluindo arquivos montados em volume)

Não tenho certeza se concordo com isso. Embora eu concorde que ele só deve ser acessível a partir do contêiner (de preferência na memória), há vários casos em que um aplicativo precisa de tempo para "iniciar" e não tem os arquivos removidos de dentro dele. Acho que algo na memória durante a execução do contêiner (removido na parada) é uma abordagem um pouco melhor.

Eu adicionaria à lista de requisitos de tempo de execução:

  • Autenticação / autorização do contêiner ao inicializar o primeiro segredo.

Por exemplo, o Vault fornece autorização com o AppRole Backend, mas é

Nick Sullivan apresentou o projeto PAL de Clouflare algumas semanas atrás, prometendo abrir o código em breve, o que deve fornecer uma resposta potencial para a questão de autenticação usando o docker notary.

Do ponto de vista de um aplicativo, existem três maneiras de lidar com isso:

  1. Obtenha um segredo de uma variável de ambiente.
  2. Obtenha um segredo de um arquivo.
  3. Obtenha um segredo de outro sistema.

1 e 2 acima são geralmente os mais comuns porque a maioria dos aplicativos oferece suporte a esse mecanismo. # 3 é provavelmente mais ideal, pois deixa menos "migalhas", mas o aplicativo deve ser desenvolvido especificamente para isso e, muitas vezes, ainda precisa de uma credencial para obter o segredo.

Docker tem tudo a ver com versatilidade e suporte a uma ampla variedade de casos de uso. Com base nisso, 1. e 2. são mais atraentes do ponto de vista de um aplicativo, apesar do fato de ambos deixarem "migalhas" no sistema.

Uma abordagem comum que certamente uso é injetar segredos por meio de um script de ponto de entrada (por exemplo, usar uma ferramenta como credstash ou KMS simples na AWS e combinar com funções IAM). Com relação a isso, você realmente faz o # 3 acima no script do entrypoint e faz o # 1 (definir uma variável de ambiente) ou o # 2 (gravar em um arquivo). Esta abordagem é dinâmica e para o nº 1 (variáveis ​​de ambiente), não expõe credenciais em logs do docker ou inspeção do docker.

O bom da abordagem do ponto de entrada é que você separa as preocupações do gerenciamento de segredos do aplicativo.

Esta é uma área onde o Docker pode adicionar funcionalidade para evitar ter que usar seus próprios scripts de entrada. O Docker adora plug-ins e pode fornecer um gancho para o ciclo de vida do contêiner, onde pode suportar plug-ins de provedor de "segredos", que essencialmente executam a função de um script de ponto de entrada manual e injetam segredos no contêiner (por meio de uma variável de ambiente interna ou arquivo). Portanto, você poderia ter um provedor de segredos Hashicorp Vault, um provedor de segredos AWS KMS etc. O Docker talvez pudesse ter seu próprio provedor baseado em criptografia RSA (via certificados digitais). Todo esse conceito é vagamente semelhante ao conceito de segredos do Kubernetes, que apresenta segredos no sistema de arquivos do contêiner.

Claro, há a complexidade de como você autoriza o acesso ao provedor de segredos, que é um problema que você enfrenta hoje. Com o Hashicorp, você pode emitir e passar um token único / limitado no tempo para autenticação, com a AWS suas funções IAM, com a abordagem de criptografia Docker RSA que mencionei, pode ser apenas passar segredos criptografados usando o certificado público do Docker Engine.

Este tópico é ótimo. Espero que vejamos mais tópicos como este, onde pessoas da comunidade e de todas as profissões possam compartilhar suas experiências, pensamentos e soluções.

O problema do "segredo zero" é complicado. Tempo de construção ou tempo de execução? Ambos têm seus prós e contras, e óbvias medidas de segurança e falhas (e hacks e contornos!).

Dito isso, tenho pensado muito sobre como o gerenciamento de uma senha / chave se resume ao aplicativo e / ou serviço.

Algo em que trabalharemos nos próximos meses é construir um serviço de suporte de configuração global compartilhado por meio de pares de chave / valor, distribuído pelo Consul e disponibilizado como uma variável de ambiente (ou injetado se o uso de variáveis ​​de ambiente não for suportado). Isso apóia apenas seus valores inseguros. Por segurança, vamos mudar para o Vault e tratá-lo como um serviço de apoio - bem como um banco de dados ou qualquer outra dependência.

Código, configuração e segredos serão fornecidos por meio de serviço (s) de apoio. Neste caso, usamos Stash, Consul e Vault. Enquanto a dependência estiver ativa, também estará a capacidade de extrair configurações e segredos conforme necessário.

Eu não vi isso como uma solução sólida em qualquer lugar, por isso estou postando sobre isso aqui. Mas, para trazer de volta ao propósito deste tópico, é uma abordagem que vamos experimentar para contornar o problema do Docker / segredo. Construiremos aplicativos que suportam isso nativamente, em vez de depender dos frameworks e plataformas em que são executados.

Com relação aos segredos de tempo de construção, a diretiva MOUNT Rocker provou ser útil para criar diretórios e arquivos temporários que _apenas_ existem em tempo de construção. Alguns de seus recursos de modelagem também podem ajudar nessa situação, mas ainda não os usei completamente.

Eu adoraria ver essa funcionalidade implementada como um plug-in do Builder no núcleo do Docker (bem como alguns dos outros recursos úteis que o Rockerfiles tem)!

Vejo que todas as 4 propostas atualmente em OP são sobre armazenamento de segredo 🙁

Eu diria que os dockers devem facilitar a passagem de um segredo / senha para uma _instância do docker_, mas armazenar / gerenciar esses segredos está (e deve estar) fora do escopo do docker.

Ao _passar um segredo_, eu diria que um parâmetro de execução é quase perfeito, exceto pelo fato de que geralmente é registrado. Então, eu restringiria isso a um recurso de parâmetro de texto não simples . Uma abordagem seria usar criptografia com chaves geradas por instância do docker.

Quanto a _como gerenciar segredos_, eu diria tudo o que o usuário quiser, desde um script bash caseiro à integração por software como o Kubernetes .

O que há de errado em apenas implementar MOUNT como montagens de rocker, como @ agilgur5 comentou anteriormente? Não posso acreditar que este debate tenha durado tanto que uma equipe teve de efetivamente fazer um fork do comando docker build para satisfazer esse caso de uso realmente fácil. Precisamos de outro servidor HTTP na mistura? BEIJO.

Passei tantas horas em torno desse assunto ...

Por enquanto, a melhor maneira que encontrei de gerenciar segredos durante a fase de compilação é compilar em duas etapas, ou seja, dois arquivos docker. Aqui está um bom exemplo .

[Habitus] (http://www.habitus.io/) parece ser outra opção, mas no meu caso, não quero adicionar outras ferramentas principalmente porque gostaria que o processo de construção no servidor de CI E no computador do usuário mantivesse simples / mesmo.

E quanto ao modo docker-in-docker (dind)?

Aqui está um exemplo de duas etapas construídas com dind como acabei de falar acima: https://github.com/BenoitNorrin/docker-build-with-secrets

Sinta-se à vontade para comentar ...

Interessante. Meio que me lembra de como o OpenShift faz compilações.

Parece que você está passando a senha na linha de comando. Existe alguma maneira de contornar isso?

Observe que há um PR de trabalho em andamento para segredos de tempo de construção aqui; https://github.com/docker/docker/pull/28079 (os segredos de tempo de execução para serviços estarão no docker 1.13, consulte https://github.com/docker/docker/pull/27794)

@thaJeztah :
Sobre o # 28079, estou um pouco pessimista quando vi tantas RP em torno desse assunto fracassando nos últimos dois anos ...
Não quero ter enxame como dependência. Parte dos meus clientes usa outro orquestrador de cluster.

@cassiussa :
Eu não entendo o que você quer dizer?
1 / As senhas foram passadas para o "construtor de contêineres" que não é a imagem final. Este construtor faz uma construção docker e produz uma imagem baseada em Dockerfile.realease. Não há segredos armazenados na história desta imagem final.
2 / Sinta-se à vontade para usar docker-compose ( exemplo ) se não quiser passar a senha para a linha de comando

@BenoitNorrin acho que pode ser expandido para não enxame no futuro, mas @diogomonica pode saber mais sobre isso

Parece que sim:

Isso é atualmente para o modo Swarm apenas porque o armazenamento de apoio é Swarm e, como tal, é apenas para Linux. Esta é a base para o futuro suporte secreto no Docker com melhorias potenciais, como suporte do Windows, diferentes armazenamentos de apoio, etc.

Seria ótimo se fosse implementado da mesma forma que o rocker, pode ser
simples, não precisa ser 'empresa'.

Na terça-feira, 29 de novembro de 2016, 15:53 ​​Michael Warkentin, [email protected]
escreveu:

Parece que sim:

Este é atualmente para o modo Swarm apenas como o armazenamento de apoio é Swarm e como
tal é apenas para Linux. Esta é a base para o futuro apoio secreto em
Docker com melhorias potenciais, como suporte ao Windows, diferentes
lojas de apoio, etc.

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/13490#issuecomment-263608915 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAZk5vlLwsBHHTTbUS_vvx-qTuwnkp6Oks5rDEpjgaJpZM4Eq021
.

Uma solução seria criptografar algumas partes das informações passadas de um arquivo docker-compose .

Por exemplo, execute docker inspect e as informações criptografadas devem ser exibidas / marcadas como _encriptografadas_. Então docker inspect --encryption-key some_key_file mostraria todas as informações criptografadas, não criptografadas.

Por outro lado, dentro dos contêineres, os aplicativos devem ser capazes de implementar diferentes mecanismos para acessar e descriptografar essas informações criptografadas para seu uso.

Acho que a criptografia _é a chave_ :)

O objetivo é que meu caso de uso (muito, muito comum) seja construir um
projeto de software de um servidor git que requer autenticação, tanto para
o projeto e suas dependências. Rocker acertou em cheio ao permitir a montagem
um arquivo ou diretório durante a construção (neste caso, um soquete de agente SSH)

Na terça-feira, 3 de janeiro de 2017, 04:14 Hisa, [email protected] escreveu:

Acho que uma solução seria criptografar algumas partes das informações passadas
de um arquivo docker-compose.

Por exemplo, execute docker inspect e as informações criptografadas devem ser
exibido / marcado como criptografado . Em seguida, docker inspect --encryption-key
some_key_file mostraria todas as informações criptografadas, não criptografadas.

Por outro lado, dentro dos contêineres, os aplicativos devem ser capazes de implementar
mecanismo diferente para acessar e descriptografar essas informações criptografadas para seu uso.

Acho que a criptografia é a chave :)

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/13490#issuecomment-270049742 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAZk5qEphZo5SR9vOWVL5dck50EPadpVks5rOcsUgaJpZM4Eq021
.

Como não vi isso ser mencionado, aqui está outro bom artigo sobre como lidar com segredos no AWS ECS: https://aws.amazon.com/blogs/security/how-to-manage-secrets-for-amazon-ec2-container- aplicativos baseados em serviço usando amazon-s3-e-docker /

Há um novo comando "docker secret" no Docker 1.13. Esse problema pode ser resolvido quando a documentação desse recurso for adequada aos casos de uso mencionados aqui.

O comando docker secret parece se aplicar atualmente apenas ao Docker Swarm (ou seja, serviços docker), portanto, não é viável atualmente para contêineres Docker genéricos.

Além disso, docker secret gerencia apenas segredos de tempo de execução, não segredos de tempo de compilação.

Uau. É como se ninguém na equipe de gerenciamento de produto tivesse considerado
o caso de uso em que qualquer coisa, exceto software de código aberto não autenticado, obtém
construído em um contêiner docker ou qualquer idioma além do golang, onde todos
dependências são copiadas e coladas, desculpe, 'versionadas' no repositório Git.

Eu simplesmente não consigo entender como as pessoas seriam tão incrivelmente obtusas. Somente
explicação que consigo pensar é que a equipe de gerenciamento de produto não é
praticantes e nunca usaram o produto. Costumo ver isso
característica se manifesta quando a organização contrata com base
habilidades Jira / Agile.

Vou continuar usando o rocker até 2019 ou quando alguém achar melhor.

Em Dom, 22 de janeiro de 2017, 23:47 Shane StClair, [email protected] escreveu:

Além disso, os segredos do docker gerenciam apenas os segredos do tempo de execução, não os segredos do tempo de compilação.

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/13490#issuecomment-274370450 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAZk5vJVJe4OeypWd1Cwqmh8Gzyn8P-mks5rU-qqgaJpZM4Eq021
.

Retiro o último comentário, desculpe, estou desabafando. Apenas frustrado isso
casos extremos simples frequentemente parecem uma oportunidade de impingir algo
como cônsul ou criar algo realmente elaborado em vez de apenas
implementar algo tão simples como a montagem do tempo de construção.

Na segunda-feira, 23 de janeiro de 2017, 09:31, Bryan Hunt, [email protected] escreveu:

Uau. É como se ninguém na equipe de gerenciamento de produto tivesse considerado
o caso de uso em que qualquer coisa, exceto software de código aberto não autenticado, obtém
construído em um contêiner docker ou qualquer idioma além do golang, onde todos
dependências são copiadas e coladas, desculpe, 'versionadas' no repositório Git.

Eu simplesmente não consigo entender como as pessoas seriam tão incrivelmente obtusas. Somente
explicação que consigo pensar é que a equipe de gerenciamento de produto não é
praticantes e nunca usaram o produto. Costumo ver isso
característica se manifesta quando a organização contrata com base
habilidades Jira / Agile.

Vou continuar usando o rocker até 2019 ou quando alguém achar que faz sentido
então.

Em Dom, 22 de janeiro de 2017, 23:47 Shane StClair, [email protected]
escreveu:

Além disso, os segredos do docker gerenciam apenas os segredos do tempo de execução, não os segredos do tempo de compilação.

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/13490#issuecomment-274370450 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAZk5vJVJe4OeypWd1Cwqmh8Gzyn8P-mks5rU-qqgaJpZM4Eq021
.

@binarytemple Todo mundo quer todos os recursos agora. Se o material não estiver pronto, ele simplesmente não está pronto. Limitar o escopo de um novo recurso definitivamente não é uma coisa ruim, pois mesmo com um escopo limitado, sempre há espaço para melhorias.

Se alguém está realmente entusiasmado com a introdução de um recurso, ele deve conversar com o (s) mantenedor (es) sobre como eles podem contribuir com o trabalho para isso.

Pensei a mesma coisa que @mixja no sentido de que o comando secret apenas ajuda a enxame de usuários não é uma solução mais geral (como fizeram com a anexação de volumes persistentes). A maneira como você gerencia seus segredos (o que são e quem tem acesso a eles) depende muito do sistema e depende de quais bits de OSS pagos e / ou OSS você junta para fazer sua "plataforma". Com o Docker, a empresa se movendo para fornecer uma plataforma, não estou surpreso que sua primeira implementação seja baseada em enxame, assim como a Hashicorp está integrando o Vault ao Atlas - faz sentido.

Na verdade, a forma como os segredos são passados ​​está fora do espaço de docker run . A AWS faz esse tipo de coisa com funções e políticas para conceder / negar permissões mais um SDK. Chef faz isso usando databags criptografados e criptografia "bootstrapping" para auth. K8S tem sua própria versão do que acabou de ser lançado em 1.13. Tenho certeza que o mesos adicionará uma implementação semelhante com o tempo.

Essas implementações parecem cair em 2 campos.
1) passar o segredo via montagem de volume que a "plataforma" fornece ou (chef / docker secret / k8s
2) passar credenciais para falar com um serviço externo para fazer as coisas na inicialização (iam / credstash / etc)

Acho que esperava ver algo mais próximo da segunda opção. Na primeira opção, não acho que haja separação suficiente de interesses (a coisa que faz o lançamento também tem acesso a todas as chaves), mas isso é preferência, e como tudo na construção de sistema, todo mundo gosta de fazer diferente .

Estou encorajado que este primeiro passo foi dado pelo docker e espero que um mecanismo mais geral para docker run saia disso (para apoiar o acampamento # 2) - o que infelizmente significa que não acho que este tópico seja missão inicial foi cumprida e não deve ser encerrada ainda.

gostar!
design realmente simples, mas muito eficaz

@bacoboy , @mixja - enxame de nó único e serviço de contêiner único não é tão ruim
docker swarm init, docker service create replica = 1

para mim, é lógico que docker swarm seja o padrão para a execução de contêineres / serviços de agora em diante.

Estou correto em pensar que essa nova proposta baseada em enxame afeta apenas os segredos de tempo de execução? Eu realmente não vejo nenhuma necessidade de tratamento especial de segredos de tempo de execução, pois já existem muitas maneiras de colocar segredos em um contêiner em execução.

segredos de tempo de construção são importantes e, até onde eu sei, esta proposta não os aborda.

Para injetar segredos de tempo de compilação, agora podemos usar docker build --squash para fazer o seguinte com segurança:

COPY ssh_private_key_rsa /root/.ssh/id_rsa
RUN git pull ...
RUN rm -rf /root/.ssh/id_rsa

O sinalizador --squash produzirá uma única camada para todo o Dockerfile: não haverá nenhum vestígio do segredo.

--squash está disponível no docker-1.13 como um sinalizador experimental.

@hmalphettes Isso significa que você perderá os benefícios das camadas inferiores compartilhadas entre as compilações.

Definitivamente, essa não é a intenção do squash. Eu ainda teria muito cuidado ao adicionar segredos como este.

@zoidbergwill camadas inferiores ainda são compartilhadas.

Eu concordo 100% com @ cpuguy83. Depender de um indicador de tempo de construção para manter os segredos fora seria muito arriscado. Houve uma proposta de RP para o tempo de construção (https://github.com/docker/docker/pull/30637). Vou trabalhar em um rebase para obter mais feedback.

@wpalmer Se você automatizou construções de imagens, seu conjunto de ferramentas deve saber como obter segredos em tempo de construção.

Por exemplo, você pode querer manter seus segredos de tempo de construção em um cofre criptografado Ansible embutido em uma imagem e conceder aos contêineres executados a partir dessa imagem o acesso ao segredo de tempo de execução que mantém sua senha de cofre.

WDYT?

Por que continuamos confundindo segredos de tempo de construção com segredos de tempo de execução? Já existem muitas maneiras boas para o docker (ou ferramentas relacionadas, como kubernetes) fornecer os segredos do tempo de execução. A única coisa que realmente falta são os segredos de tempo de construção. Esses segredos não são usados ​​durante o tempo de execução, eles são usados ​​durante o tempo de instalação, podem ser repositórios internos, por exemplo. A única maneira de trabalhar que vi neste e nos tópicos relacionados (mas também desaconselhável) é expor um servidor http ao contêiner durante o tempo de construção. A abordagem do servidor http torna as coisas bastante complicadas para realmente chegar a esses segredos.

+1 segredo de tempo de construção! = Segredo de tempo de execução

Como Paul aponta. Não é desejável assar repositório interno
credenciais na imagem.

Por que isso é tão difícil de compreender?

Na quinta-feira, 16 de fevereiro de 2017, 14h42, Paul van der Linden, [email protected]
escreveu:

Por que continuamos confundindo segredos de tempo de construção com segredos de tempo de execução? Lá
há muitas boas maneiras de o docker (ou ferramentas relacionadas, como kubernetes)
fornecer os segredos do tempo de execução. A única coisa que realmente falta é o tempo de construção
segredos. Esses segredos não são usados ​​durante o tempo de execução, eles são usados ​​durante
tempo de instalação, podem ser repositórios internos, por exemplo. O único
forma de trabalho que vi neste e em tópicos relacionados (mas também aconselhei
contra ele), está expondo um servidor http ao contêiner durante o tempo de construção.
A abordagem do servidor http torna as coisas mais complicadas para realmente chegar
esses segredos.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/13490#issuecomment-280348116 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAZk5h0Z2OGwApVnLNEFWKRdOfGxLOmRks5rdGBagaJpZM4Eq021
.

@pvanderlinden Você também pode fazer isso com duas etapas de construção.
Aqui está um exemplo: https://github.com/BenoitNorrin/docker-build-with-secrets

@timka, como mencionado, não é desejável inserir credenciais na imagem, pois isso representa um risco de segurança. Aqui está uma proposta para segredos de tempo de compilação: https://github.com/docker/docker/pull/30637

@BenoitNorrin Não tenho certeza como seria no meu caso de uso (e em outros).
Os pacotes que precisam ser instalados já estão compilados quando eu inicio o processo de compilação do docker. Mas a compilação do docker precisará instalar esses pacotes, precisará acessar um repositório anaconda interno e / ou servidor pypi (python). Os locais e as senhas são particulares, claro.
Parece que # 30637 é outra tentativa, espero que isso vá parar no docker!

@timka a primeira metade de sua mensagem parece mencionar segredos de tempo de construção, mas a segunda metade fala explicitamente sobre segredos de tempo de execução. Os segredos de tempo de execução são simples. Minha "solução" atual para segredos de tempo de construção é pré-executar, como uma etapa completamente separada, um contêiner que busca dados privados usando um segredo de tempo de execução. Outra etapa então mescla isso na árvore, antes de executar um comando docker build normal.

A alternativa, se os segredos de tempo de compilação fossem um recurso padrão, seria executar essas etapas no Dockerfile.

Meu ferramental sabe como executar essas etapas automaticamente, mas eu mesmo precisava assar isso, o que é um tanto absurdo para um desejo tão comum.

Para sua informação, escrevi https://github.com/abourget/secrets-bridge para resolver o problema dos segredos em tempo de construção.

Ele cria uma configuração descartável que você pode passar como argumentos, durante o processo de construção, ele se conectará ao host e buscará os segredos, os usará e então você poderá eliminar a ponte do host. Mesmo que os argumentos de construção sejam salvos em algum lugar, eles se tornam inúteis no momento em que o servidor é encerrado.

O servidor oferece suporte a SSH Agent Forwarding, tunelado por meio de uma comunicação de websocket TLS. Também funciona no Windows!

Alexandre, o que você fez é extremamente criativo e habilidoso. É só
me deixa triste que seja necessário pular todas essas etapas apenas para
conseguir o mesmo que poderia ser feito se 'docker build' suportasse o 'mount'
comando em vez da insistência cega de que tudo seja copiado para o
recipiente.

Eu sou o meu caso, vou abandonar o 'docker build' e, em vez disso, usar o rocker ou
algo se minha própria criação.

Em qui, 13 de julho de 2017, 16:23 Alexandre Bourget, notificaçõ[email protected]
escreveu:

Para sua informação, escrevi https://github.com/abourget/secrets-bridge para abordar o
problema de segredos em tempo de construção.

Ele cria uma configuração descartável que você pode passar como argumentos,
durante o processo de construção, ele se conectará ao host e buscará o
segredos, use-os e então você pode matar a ponte de host. Mesmo se o
build-args são salvos em algum lugar, eles se tornam inúteis no momento em que o servidor
é morto.

O servidor oferece suporte a SSH Agent Forwarding, tunelado por meio de um TLS
comunicação de websocket. Também funciona no Windows!

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/13490#issuecomment-315111388 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAZk5hZqTAgPBjS9cFP_IsYNa9wv-yoAks5sNjaBgaJpZM4Eq021
.

Aqui está a mais recente proposta de segredos: https://github.com/moby/moby/issues/33343

Acho que a nova funcionalidade de "compilação de vários estágios" incluída na última versão do Docker CE resolve grande parte dos nossos problemas.

https://docs.docker.com/engine/userguide/eng-image/multistage-build/

Os contêineres gerados para executar comandos de Dockerfile vêm com /dev cozidos e nenhuma alteração feita deve ser registrada em uma camada. O docker pode fornecer segredos do usuário por meio desse ponto de montagem? De maneira semelhante, ele fornece /dev/init ?

Isso ainda é muito importante porque compilações de vários estágios com argumentos não vazam na imagem, mas ainda expõem seus segredos como parte das listas de processos no sistema em execução, portanto, não é realmente resolvido.

É agosto de 2017. Enquanto isso, "propostas mais antigas para lidar com segredos" no link da edição original para edições de 2014.

Ainda não há boas soluções para segredos de tempo de construção. O PR que oferecia a bandeira --build-time-secret foi encerrado sem nenhuma explicação. Nada apresentado em "Então, o que é necessário?" seção é implementada.

Enquanto isso

O CEO recém-instalado Steve Singh, com foco em clientes empresariais
Última rodada de US $ 75 milhões para ajudar a formar a equipe de vendas e marketing


UPD .: como @ cpuguy83 corretamente e com razão apontado abaixo, o resumo completo das propostas está em # 33343

Eu sei que não está embutido, mas secrets-bridge funciona muito bem por enquanto.

@dmitriid Eu entendo sua frustração com a ausência desse recurso. No entanto, não é assim que se dirige a uma comunidade de código aberto (ou qualquer comunidade).

Publiquei um link para uma proposta acima e vi exatamente 0 comentários sobre ela, exceto o meu próprio.

Aqui está a mais recente proposta de segredos: # 33343

@ cpuguy83 Incrível! Eu meio que pulei o último terço desta discussão (e alguns outros) porque é um monte de coisas para ler (enquanto ao mesmo tempo procuro por uma solução), então realmente senti falta do seu comentário, desculpe :(

Este tópico começou em 2015.

É 2017.

Por que não há solução para segredos de tempo de construção que ainda não seja hackeado e terrível? É obviamente um grande problema para muitas pessoas, mas ainda não há uma solução realmente boa!

@mshappe

Por que não há solução para segredos de tempo de construção que ainda não seja hackeado e terrível?

Porque é um problema difícil de resolver corretamente e é algo que será utilizado por literalmente milhões de pessoas.

Por favor, veja meu comentário logo acima do seu:

Publiquei um link para uma proposta acima e vi exatamente 0 comentários sobre ela, exceto o meu próprio.
Aqui está a mais recente proposta de segredos: # 33343

Se quiser ver algo implementado, você precisará fazer mais do que reclamar que algo não foi implementado. Por favor, comente a proposta!

É tão fácil de resolver. Requer apenas algo, qualquer coisa que não seja
incorporado nas imagens. E na verdade é muito fácil de resolver, pare de usar
'docker build' e usa a API python, rocker ou qualquer outra coisa.

Na quarta-feira, 23 de agosto de 2017 às 21h42, Brian Goff [email protected]
escreveu:

@mshappe https://github.com/mshappe

Por que não há solução para segredos de tempo de construção que não sejam hackeados e
terrível, ainda?

Porque é um problema difícil de resolver corretamente e é algo que
será usado por literalmente milhões de pessoas.

Por favor, veja meu comentário logo acima do seu:

Publiquei um link para uma proposta acima e vi exatamente 0 comentários sobre
exceto o meu.
Aqui está a mais recente proposta de segredos: # 33343
https://github.com/moby/moby/issues/33343

Se você quiser ver algo implementado, você precisará fazer mais do que
reclamar que algo não foi implementado. Por favor, comente a proposta!

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/13490#issuecomment-324441280 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAZk5oEpcipmfCji1mXz6MOVt0p6-OA6ks5sbIC0gaJpZM4Eq021
.

@binarytemple Comecei a olhar para o Rocker como uma alternativa, na verdade ... mas apenas por causa desse estranho bloqueio mental que o docker parece ter sobre segredos de tempo de construção.

É estranho. Eu converso com as pessoas e elas estão fazendo todos os tipos de hacks estúpidos
como usar um serviço HTTP - jogando fora tudo (monitoramento / granular
permissões / simplicidade) que o combo POSIX / SELinux fornece. Eu simplesmente não
Compreendo. A recusa parece ilógica para mim.

Na quarta-feira, 23 de agosto de 2017, 23:03 Michael Scott Shappe [email protected]
escreveu:

@binarytemple https://github.com/binarytemple comecei a olhar para
Rocker como uma alternativa, na verdade ... mas apenas por causa deste estranho
O docker do bloco mental parece ter sobre segredos de tempo de construção.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/13490#issuecomment-324461257 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAZk5ppZYsOhdfvgotCUk5l41Truo_EEks5sbJOLgaJpZM4Eq021
.

As compilações do docker de vários estágios resolvem muitos desses problemas.

Em sua forma mais simples, você pode injetar segredos como argumentos de construção, e eles farão apenas parte do histórico das imagens que diz explicitamente que precisam do argumento. Como neclimdul aponta , os segredos estarão disponíveis na listagem de processos durante a compilação. IMO não é um grande problema, mas adotamos outra abordagem.

Nosso servidor de compilação é executado com alguns segredos montados como volumes, portanto, nossa cópia CI em f.ex. /mnt/secrets/.npmrc no diretório de trabalho atual. Em seguida, usamos um Dockerfile semelhante ao abaixo.

FROM node:latest
WORKDIR /usr/src/app
COPY .npmrc .
RUN echo '{ "dependencies": [ "lodash" ] }' > package.json
RUN npm install
RUN ls -lah

FROM alpine:latest
WORKDIR /usr/src/app
COPY --from=0 /usr/src/app/node_modules ./node_modules
RUN ls -lah
CMD ["ls", "./node_modules"]

A imagem resultante terá as dependências instaladas, mas não o .npmrc ou qualquer vestígio de seu conteúdo.

O uso de compilações de vários estágios oferece controle total sobre como expor os segredos de tempo de compilação para o processo de compilação. Você pode obter segredos de armazenamentos externos, como Vault, por meio de volumes (que montamos no armazenamento de segredos no Kubernetes), criptografando-os com gpg no repositório, secrets Travis etc.

Ao usar compilações de vários estágios para este caso de uso, certifique-se de perceber que os dados secretos permanecerão dentro de uma imagem não marcada no daemon local até que a imagem seja excluída para que esses dados possam ser usados ​​para o cache de compilação em compilações subsequentes. Mas não é enviado para o registro ao enviar a imagem final marcada.

@androa Gosto dessa solução, mas não tenho certeza de como me sinto sobre os segredos sendo copiados para o diretório de trabalho. Provavelmente, isso não é um problema em um servidor CI privado, mas não é tão bom para um prédio local onde você estaria copiando arquivos que não deveria estar fora de locais protegidos (sem mencionar que a cópia em si é irritante e perigosa, pois pode terminar acidentalmente no controle de origem). A outra opção seria usar um contexto de compilação mais amplo do Docker, mas, para muitos segredos comuns, isso poderia significar todo o volume raiz. Alguma sugestão sobre como tornar isso bom para locais e CI?

Isso é terrível. A autoproclamada "plataforma de contêiner de software líder mundial" não pode se dar ao trabalho de passar com segurança segredos de tempo de construção para contêineres nos últimos 3 anos.

Com a abordagem "nós sabemos melhor" e "não cometemos erros de software" e o que pode ser descrito como uma omissão infeliz na fase de design, não há suporte e nenhum progresso visível em relação a um dos recursos necessários do software DevOps. Todas as comunidades sugeridas e às vezes até desenvolvidas a ponto de estarem prontas para a fusão são fechadas com medo de que alguém as abuse. Como resultado desta falha de cluster ... todas as maneiras de passar chaves privadas necessárias apenas para a fase de construção do contêiner docker requer salvar esses segredos no histórico de construção ou estar visível na lista de processos com esperança de que, respectivamente, o histórico de construção nunca saia do máquina confiável ou ninguém que não deva ver a lista de processos. Ambos falharão mesmo nas auditorias de segurança mais permissivas.

Esta edição está aberta há mais de 2 anos para resumir o que se sabia sobre o problema na época e o que fazer a respeito. Ainda não há solução. Com isso, não quero dizer uma solução abrangente que oferecerá suporte aos esquemas de gerenciamento de segredos mais complexos e prontos para uso. Não existe uma solução AT ALL, nenhuma variável de ambiente de host, nenhum segredo de carregamento do caminho do arquivo fora do contexto de construção. Nada que possa ser considerado seguro, mesmo em termos menos rigorosos.

@OJezu Como já afirmei várias vezes sobre esse assunto, há uma proposta aberta com basicamente 0 comentários sobre ela.
Se você deseja que os segredos sejam divulgados, reserve um tempo para comentar a proposta.

Em vez de vir armas em chamas e atacar as pessoas que trabalham nisso todos os dias, da próxima vez tente fazer perguntas e ler pelo menos os comentários mais recentes sobre o assunto que você está comentando.

Muitas vezes as coisas podem parecer paralisadas quando, na verdade, há apenas pessoas trabalhando arduamente.
Para construção, consulte github.com/moby/buildkit onde a maior parte desse trabalho está acontecendo hoje.

Obrigado.

Estou um pouco embriagado, porque hoje passei 9 horas tentando encontrar uma solução para algo que não deveria ser problema, principalmente em um projeto que está sendo trabalhado em tempo integral e se posicionando como padrão de fato e go-to soultion . Eu estava tentando muito não xingar e parar de me machucar enquanto escrevia esses comentários.

Olhei para aquele problema e vi referências a duas soluções, uma paralisada desde abril, outra já fechada. Não posso deixar de notar que a proposta de 0 comentários tem 4 participantes, o mesmo número de comentários e menciona alguma discussão interna aparente, acho que por pessoas mais familiarizadas com as complexidades de. Mas se você quiser feedback adicional de alguém que nem mesmo programa em go, posso fornecer mais ideias sobre os problemas que mencionei no comentário anterior.

@OJezu

Há pelo menos uma solução fácil: usar um serviço dedicado (por exemplo, rodar no Jenkins) para construir artefatos.
Esse serviço receberá com segurança todas as chaves necessárias para acessar os artefatos dos quais sua imagem depende.
Ao terminar, os artefatos serão colocados em um local seguro (por exemplo, Jenkins). Esses artefatos não conteriam nenhum segredo, apenas um diretório com binários / fontes / etc.
Em seguida, outro serviço (por exemplo, outro trabalho do Jenkins) acessará esses artefatos pré-construídos e os transformará em uma imagem que pode ser enviada com segurança para um registro de imagem, que por sua vez é protegido com segurança usando rbac / keys para acessá-los das máquinas do desenvolvedor / produção.

Ou seja, o processo de compilação da imagem docker não é diferente de qualquer outro sistema de compilação por aí: você precisa ter um pipeline de compilação no lugar.

Build pipeline

@Vanuan nem todos os idiomas são tão simples com empacotamento e instalação, para simplesmente instalar com um artefato.

Exemplos?

Os projetos Python obtêm seus requisitos no momento da instalação, não no momento da construção. Em nosso caso, de um repositório pypi / conda privado (protegido por senha)

Então? Faça da instalação uma parte do seu processo de construção e, a seguir, copie os pacotes instalados em uma imagem nova.

Você só precisa ter certeza de que sua imagem de construção e sua imagem de produção são baseadas na mesma imagem base do Python.

Na verdade, você pode simplesmente copiar tudo em uma nova imagem. No entanto, isso remove todo o ponto de um Dockerfile. Por que ter um Dockerfile se a única coisa que você pode usar é apenas para copiar um conjunto de diretórios?

Portanto, não posso ter um fluxo simples no qual apenas executo docker build . qualquer lugar - seja na máquina de desenvolvimento ou no CI, mas preciso depender do CI para construir pacotes. Por que se preocupar com o docker então? Posso escrever um arquivo travis ou configurar o fluxo em bamboo.

Você não pode simplesmente pip install requirements.txt em seu primeiro estágio de construção com segredos disponíveis para puxar de seus repositórios privados. Então, o próximo estágio de construção apenas copia os pacotes de sites do primeiro estágio.

Por que ter um Dockerfile se a única coisa que você pode usar é apenas para copiar um conjunto de diretórios?

Por que não? Usar um Dockerfile para construir é consistente.

A especificação da imagem é mais do que um monte de arquivos compactados. Existem variáveis ​​de ambiente, argumentos de linha de comando, volumes, etc.

Leia a referência do Dockerfile:
https://docs.docker.com/engine/reference/builder/

Parece que você tem se concentrado principalmente na instrução RUN , pensando que o Dockerfile é um substituto para o Makefile. Não é. O Dockerfile serve apenas para uma coisa: construir uma imagem a partir de algum material de origem. Qual seria o material de origem - um binário baixado por http ou um repositório git - não importa. O Docker não precisa ser seu sistema CI, embora você possa usá-lo como um sob certas condições.

Posso escrever um arquivo travis ou configurar o fluxo em bamboo.

Se você pode obter o resultado do seu processo de construção e depois executá-lo em outro ambiente, sem imagens e contêineres, com certeza não precisa se preocupar com o docker. Por que você?

Ambiente separado e estritamente controlado que obtém redefinições garantidas entre compilações, mas somente se as etapas de compilação forem alteradas. Capacidade de executá-lo em qualquer lugar, não apenas em servidores CI (como com Travis), vinculando instruções de construção com código, o que eu acho que é bom se a construção muda para diferentes ramos de código (por exemplo, alterar a versão do ambiente de execução apenas em um ramo). Possibilidade de executar o build container nas máquinas do desenvolvedor, permitindo enviar todo o ambiente para desenvolvedores que, de outra forma, não têm ideia de como atualizar seu próprio sistema, mas serão capazes de construir o aplicativo com suas alterações localmente com o mesmo ambiente de todos os outros.

Se eu não quisesse tudo isso, preferiria lxc + ansible, sem necessidade de docker.

Você não precisa de docker build para isso.

Você não precisa de docker build para isso.

Claro, você também pode fornecer um script Makefile ou build_image.sh para cada projeto, em vez de um único Dockerfile auto-suficiente, mas isso tem várias desvantagens:

  • Compatibilidade de plataforma cruzada: com o fornecimento de um Dockerfile, sei que qualquer sistema que execute docker build será capaz de construir a imagem. Com o fornecimento de Makefile ou build_image.sh , tenho que garantir manualmente que funcionem em todas as plataformas que desejo oferecer suporte.
  • Interface conhecida para usuários: Se você conhece o docker, conhece um pouco do comportamento de docker build para qualquer projeto, mesmo sem olhar para o Dockerfile (por exemplo, com relação ao cache, etc ...). Se eu tiver um Makefile ou build_image.sh , para cada projeto, preciso primeiro descobrir quais são os comandos para construir, limpar, onde e de que forma está o resultado, se houver é algum cache e de que forma, ...

Oh, o Dockerfile está longe de ser autossuficiente. Especialmente para ambiente de desenvolvimento.
Considere isto:

  • a maioria dos desenvolvedores não conhece todas as diferentes opções de docker build , mas quase todo mundo sabe como executar scripts bash
  • docker build depende do diretório de contexto . Portanto, a menos que você esteja disposto a esperar por gigabytes de dados (seu código-fonte com dependências) para viajar de um local para outro para cada mudança de linha de origem, você não vai usá-lo para desenvolvimento.
  • a menos que você crie TUDO do zero, você depende do registro do docker
  • é provável que você dependa de repositórios de SO (se você usa imagens baseadas em Debian ou Alpine), a menos que inicialize um contêiner direto para o binário estaticamente construído
  • a menos que você comprometa tudo com git, você terá algumas dependências em nível de projeto, seja npm, índice de pacote python, rubygems ou qualquer outra coisa. Então você dependerá de algum registro de pacote externo ou de seu espelho
  • como a maioria das pessoas notou aqui, você dependerá de algum local de pacote secreto para suas dependências privadas que você não pode publicar no repositório público, então você dependerá disso
  • o provisionamento de segredos é necessário para acessar esse local seguro, então você dependerá de algum sistema que distribuirá segredos aos desenvolvedores
  • além do Dockefile, você precisará do docker-compose.yml, e ele não é multiplataforma: você ainda depende das diferenças de avanço / barra invertida .

Compatibilidade de plataforma cruzada: com o fornecimento de um Dockerfile, sei que qualquer sistema que possa executar o docker build será capaz de construir a imagem.

O Dockerfile não garante compatibilidade entre plataformas. Você ainda precisa fornecer vários Dockerfiles para várias plataformas. "Pode executar docker build" não significa mais "Usa Linux". O Docker também oferece suporte a imagens nativas do Windows. Você ainda precisa usar o Cygwin + Linux VM se quiser executar algo voltado especificamente para máquinas Linux em um host Windows.

Ah, e eu nem mencionei x86 vs ARM ...

Interface conhecida para usuários: se você conhece o docker, conhece um pouco do comportamento do docker build para qualquer projeto, mesmo sem olhar para o Dockerfile

A menos que você não faça. Todos sabem como executar um script bash sem parâmetros ou um único comando make . Poucas pessoas sabem como especificar corretamente todas as diferentes opções de linha de comando para docker build , docker run ou docker-compose . É inevitável que você tenha algum script bash ou cmd de invólucro.


Com todo o respeito pelo que o pessoal do Docker fez, acho que você está pedindo demais. Temo que o Mobyproject não tenha um escopo tão amplo a ponto de dar suporte a todos os fluxos de trabalho de desenvolvimento imagináveis.

Não vou refutar todos os seus pontos individualmente. Em primeiro lugar, é claro que você sempre pode encontrar situações em que a abordagem de "Dockerfile único" não funciona. No entanto, eu diria que para quase todos os seus pontos que você levantou (que são válidos e relevantes), a abordagem de "script personalizado ou makefile" é tão ruim quanto ou pior. Apenas como exemplo, um ponto:

a maioria dos desenvolvedores não conhece todas as diferentes opções de compilação docker, mas quase todo mundo sabe como executar scripts bash

Se estou envolvido em 10 projetos e todos usam um Dockerfile, preciso aprender sobre o docker apenas uma vez, mas com sua sugestão, preciso aprender 10 scripts de compilação totalmente diferentes. Como faço para limpar o cache e começar do zero para build_image.sh projeto Foo novamente? Não está claro. Se a construção da imagem for feita com docker build , está claro (ofc, preciso saber como o docker funciona, mas também preciso fazer isso para usar a imagem que sai de build_image.sh ).

No geral, acho que o que eu e outros estamos tentando fazer é que para / muitos / cenários a abordagem de "Dockerfile único" parece funcionar muito bem para as pessoas (o que é uma razão para o docker ser tão popular), em particular no mundo de código aberto onde normalmente todos os recursos são acessíveis sem segredos. Mas se você tentar aplicar o mesmo padrão que passou a amar em um contexto em que parte de seus recursos precisa de credenciais para acessar, a abordagem falha. Tem havido uma série de sugestões (e implementações) de maneiras tecnologicamente não muito complexas de fazê-lo funcionar, mas nada aconteceu ao longo do tempo (isso foi colocado muitas vezes acima). Daí a frustração.

Agradeço que as pessoas estejam se empenhando nisso, por exemplo, com a proposta vinculada em # 33343. Meu post é sobre como motivar o que algumas pessoas fazem e por que continuam voltando pedindo isso aqui.

Com todo o respeito pelo que o pessoal do Docker fez, acho que você está pedindo demais. Temo que o Mobyproject não tenha um escopo tão amplo a ponto de dar suporte a todos os fluxos de trabalho de desenvolvimento imagináveis.

Parece-me que o que a maioria das pessoas está pedindo aqui não é nada disso, mas apenas uma maneira simples de usar segredos em docker build de uma forma não menos segura do que usá-los em seu build_image.sh personalizado

Sinto muito, mas cada pessoa neste tíquete tem um caso de uso ligeiramente diferente. Esses são casos esquivos e exigem soluções diferentes.

  1. Quero executar imagens de produção em máquinas de desenvolvimento. Usar registro docker
  2. Quero um sistema de CI distribuído, para que cada desenvolvedor tenha uma construção reproduzível. Use docker run para construir seu projeto, use docker prune para limpar
  3. Quero construir imagens docker para poder distribuí-las. Use um servidor de CI dedicado onde você pode executar compilações de vários estágios.

@Vanuan , então acho que sua abordagem é basicamente: não use docker build, para nada além do ambiente básico. Este é um problema criado para mudar isso. "Você tem que fazer diferente" É o problema, não a solução.

As pessoas que defendem o problema desejam abordagens mais simples e diretas com as imagens do docker, sem ter que contornar as limitações do docker.

Para qualquer pessoa interessada: Eu tentei explorar argumentos de construção "mascarados por padrão" como FTP_PROXY para construir contextos. É seguro em relação ao fato de que o docker-build não expõe esses argumentos mascarados aos metadados da imagem nem às camadas da imagem.

36443 foi uma tentativa de expandi-lo para um argumento de construção denominado como SECRET para que possamos encorajar os usuários a usá-lo como uma solução alternativa simples para o problema de gerenciamento de segredo.

No entanto, o trabalho foi rejeitado razoavelmente, já que a natureza mascarada desses argumentos de construção não são garantidos no futuro.

Minha melhor aposta depois disso é seguir o conselho de @AkihiroSuda , usar docker build --network ou uma ferramenta como o habitus para armazenar / passar segredos por meio de um servidor tcp temporário, apenas contextos de construção visíveis dentro de um único docker daemon, no máximo.

Comentando parcialmente, então recebo uma notificação daqui a 5 anos, quando Docker finalmente decidir nos dar um pequeno passo na direção do gerenciamento adequado de credenciais .... e também, dar um esboço do hack que estou usando no momento , para ajudar os outros, ou para fazer furos que eu não conheço.

No seguinte problema de @mumoshu , finalmente peguei a dica de usar args predefinidos para segredos de construção.

Então, basicamente, posso usar docker-compose, com um mapeamento como este:

  myProject:
    build:
      context: ../myProject/
      args: 
        - HTTPS_PROXY=${NEXUS_USERNAME}
        - NO_PROXY=${NEXUS_PASSWORD}

E então, na pasta com o arquivo docker-compose.yml, crie um arquivo chamado ".env" com pares de valores-chave de NEXUS_USERNAME e NEXUS_PASSWORD - e os valores apropriados lá.

Finalmente, no próprio Dockerfile, especificamos nosso comando run assim:
EXECUTAR wget --user $ HTTPS_PROXY --password $ NO_PROXY

E NÃO os declare como ARGs no DockerFile.

Eu não encontrei minhas credenciais flutuando na compilação resultante em nenhum lugar ainda ... mas não sei se estou procurando em todos os lugares ... E para o resto dos desenvolvedores em meu projeto, apenas cada um tem que crie o arquivo .env com os valores apropriados para eles.

@darmbrust Tentei sua solução, mas não consegui fazer funcionar.
Aqui está o meu yml de composição:
versão: "3.3"
Serviços:

  buildToolsImage:
    image: vsbuildtools2017:web-v6

    build:
      context: .
      dockerfile: ./vsbuild-web-v6-optimized.dockerfile
      args:
        - CONTAINER_USER_PWD=${CONTAINER_USER_CREDS}

Aqui está o arquivo .env próximo ao arquivo yml:

CONTAINER_USER_CREDS=secretpassword

E aqui está meu dockerfile:

# escape=`
FROM microsoft/dotnet-framework:4.7.2-sdk
# Add non-root user
CMD ["sh", "-c", "echo ${CONTAINER_USER_PWD}"] 
RUN net user userone ${CONTAINER_USER_PWD} /add /Y

E, finalmente, o comando para dar o pontapé inicial é assim:

docker-compose -f docker-compose.buildImage.yml build

Ele constrói a imagem, mas sem usar a senha armazenada no arquivo .env.

[Warning] Um ou mais build-args [CONTAINER_USER_PWD] não foram consumidos

O que estou perdendo aqui?
Obrigado!

Você deve usar um dos https://docs.docker.com/engine/reference/builder/#predefined -args no arquivo docker. Você não pode usar seus próprios nomes de argumento como CONTAINER_USER_PWD.

É assim que o truque funciona, porque docker tem um comportamento especial para os args predefinidos, em que você pode usá-los sem declará-los. E, ao usá-los sem declará-los, eles não parecem estar registrados em nenhum lugar.

Com o arquivo docker-compose, você pode mapear esses argumentos predefinidos para algo com um nome mais razoável.

@darmbrust Sim, funcionou.
No entanto, você não acha que é fedorento? Alguma recomendação melhor?
Obrigado!

Provavelmente não é tão fedorento quanto expor suas credenciais de agente ssh pelo tcp
via socat para qualquer processo local roubar, mas, na verdade, como com qualquer coisa
relacionado aos segredos, o 'docker build' é bastante fedorento.

Na verdade, eu tinha esquecido que o Docker para Mac não pode expor o domínio Unix
soquetes no host osx para os contêineres, de modo que abre ainda mais de um
lata de minhocas.

Minha solução atual, executar uma conta de usuário de máquina Centos VM, GitHub
as credenciais vão para ele, construídas usando a ferramenta "Rocker" (obsoleta).

Em quinta-feira, 26 de julho de 2018, 21:49 Sameer Kumar, [email protected] escreveu:

@darmbrust https://github.com/darmbrust Sim, funcionou.
No entanto, você não acha que é fedorento? Alguma recomendação melhor?
Obrigado!

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/13490#issuecomment-408230125 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAZk5iz1kvCpZ0s65ng4TwL7LmHa9zZvks5uKitDgaJpZM4Eq021
.

Todo esse bug é fedorento. Não encontrei uma maneira melhor ... existem várias outras abordagens acima, mas acho que todas as outras seguras requerem a criação de um pequeno servidor http para alimentar as informações na imagem. talvez menos fedorento, mas mais complexidade, mais ferramentas, mais peças móveis.

Não tenho certeza de que alguém encontrou uma "boa" solução ... estamos todos presos esperando que o pessoal do docker faça algo a respeito ... não prenda a respiração, pois esse bug foi escrito em 2015, e eles não o fizeram. Eu ainda propus um roteiro, muito menos uma solução.

É tão simples e óbvio, permite a montagem de volumes, (arquivos ou
diretórios) no contêiner durante a construção.

Esta não é uma limitação técnica, é uma decisão de não permitir segredos em
a fim de preservar o comportamento de - verificar, executar construção, mesmas entradas,
saída, altere um argumento de construção se quiser invalidar o cache ...

O problema é que a abstração está se tornando cada vez mais imprecisa
com pessoas usando todos os tipos de hacks desajeitados e inseguros para obter um "segredo"
em um recipiente.

Newsflash, expondo seu chaveiro SSH via TCP, mesmo em localhost não é
seguro, nem passar credenciais por meio de variáveis ​​de ambiente (dica, execute
ps ou peek no sistema de arquivos / proc), argumentos de comando e variáveis ​​de ambiente estão todos lá, nus, para o mundo ver.

Para desenvolvedores de código golang, isso tradicionalmente não tem sido um problema, pois eles copiam e colam
suas dependências em seus projetos, em vez de usar uma ferramenta de gerenciamento de dependências, os desenvolvedores de golang chamam essa prática de 'venda'.

Para quem trabalha em outros ecossistemas onde o sistema de compilação
obtém dependências do Git, ou repositórios que requerem autenticação, é um grande problema.

Tenho certeza de que existe alguma regra de inicialização em algum lugar ao longo das linhas de,
"não presuma que você sabe, como ou por que seus usuários usam o produto".

Em quinta-feira, 26 de julho de 2018, 22h, Dan Armbrust, notificaçõ[email protected] escreveu:

Todo esse bug é fedorento. Eu não encontrei uma maneira melhor ... há
várias outras abordagens acima, mas acho que todas as outras seguras
requer a criação de um pequeno servidor http para alimentar as informações no
imagem. talvez menos fedorento, mas mais complexidade, mais ferramentas, mais comovente
partes.

Não tenho certeza se alguém encontrou uma "boa" solução ... estamos todos presos
esperando o pessoal do docker fazer algo a respeito ... não espere
respiração, já que esse bug foi escrito em 2015, e eles nem mesmo propuseram
um roteiro ainda, muito menos uma solução.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/13490#issuecomment-408233258 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAZk5nvbBTj4BAv5TtELNIHhJN8mU0Ctks5uKi38gaJpZM4Eq021
.

@binarytemple Todos que já trabalharam no Docker / moby (como os engenheiros por trás dele) sabem exatamente qual é o problema e até mesmo se depararam com ele.

Volumes é uma solução que em si é incrivelmente furada.
Há uma proposta, mencionada um pouco no fluxo de comentários, que tenta resolver isso de uma maneira razoável (https://github.com/moby/moby/issues/33343)

O principal aqui é fornecer a abstração "certa" ao invés de "qualquer abstração que funcione" ... é claro que sabemos que isso é doloroso para muitos mais do que apenas neste caso.

Recentemente, muito trabalho foi feito no construtor que ainda não é necessariamente visível, mas os frutos desse esforço começarão a aparecer nos próximos meses.
Para começar, o Docker 18.06 vem com uma implementação de construtor alternativa apoiada por https://github.com/moby/buildkit.
Você pode pensar "como isso me ajuda?". O Buildkit fornece muitos primitivos de baixo nível que nos permitem ser muito mais flexíveis no construtor Docker. Tanto quanto ser capaz de fornecer seu próprio analisador de compilação (que pode ser qualquer coisa, desde um analisador Dockerfile aprimorado até algo completamente diferente). Os analisadores são especificados na parte superior do "Dockerfile" e são qualquer imagem que você deseja usar para analisar o arquivo.

Se você realmente deseja ver algo agora, você pode pegar o próprio buildkit e executá-lo hoje, ele fica sobre o containerd, você pode construir uma integração customizada muito rapidamente.

O suporte para montagens secretas foi adicionado ao buildkit em https://github.com/moby/buildkit/pull/522 . Eles aparecem estritamente no tmpfs, são excluídos do cache de construção e podem usar uma fonte de dados configurável. Nenhum PR ainda que o expõe em uma sintaxe dockerfile, mas deve ser uma adição simples.

Existem 2 soluções para construir imagens com segredos.

Compilação de vários estágios:

FROM ubuntu as intermediate
ARG USERNAME
ARG PASSWORD
RUN git clone https://${USERNAME}:${PASSWORD}@github.com/username/repository.git

FROM ubuntu
# copy the repository form the previous image
COPY --from=intermediate /your-repo /srv/your-repo

Então: docker build --build-arg USERNAME=username --build-arg PASSWORD=password my-image .

Usando um construtor de imagem: docker-build-with-secrets

@BenoitNorrin , desculpe, mas você expôs essa senha a todos os processos no sistema host. Segurança 101 do Unix - não coloque segredos como argumentos de comando.

Sim, mas existem alguns usos em que a segurança é um pouco menos importante:

  • você quer construir em seu próprio computador
  • você constrói em seu servidor de CI empresarial (como Jenkins). Na maioria das vezes, trata-se de ter acesso a um repositório privado (nexus, git, npm, etc), então seu CI pode ter suas próprias credenciais para isso.
  • você pode usar uma VM criada a partir da docker-machine e removê-la depois.

Se esse for o único problema, @binarytemple , simplesmente adicionar o sinalizador docker image build --args-file ./my-secret-file deve ser uma solução bem fácil para todo o problema, não é? :pensamento:

@yajo pode ser, sim, é pelo menos uma solução alternativa até que o buildkit seja enviado com a montagem dos segredos. Boa sugestão. Obrigado. B

Infelizmente, a maioria das soluções alternativas mencionadas nesses e em muitos outros tíquetes ainda expõe os segredos da imagem resultante ou só funciona com linguagens específicas em que você só precisa de dependências durante o tempo de compilação e não durante a instalação.

@binarytemple que nunca vai acontecer, os mantenedores do docker já mataram pelo menos um PR totalmente documentado e totalmente implementado de um recurso de segredo seguro. Dado o resto da história (este tíquete de 3 anos não é o mais antigo e definitivamente não é o único tíquete / PR sobre esse assunto), acho que é seguro dizer que os mantenedores do docker não entendem a necessidade de segurança, que é uma grande problema.

O maior problema são as rotações secretas para mim

você tem que manter um gráfico de segredo para dependências de serviços e atualizar duas vezes cada serviço (para voltar ao nome secreto original)

listar segredos de serviços não parece ser fácil (desisti após algumas tentativas em torno de docker service inspect --format='{{.Spec.TaskTemplate.ContainerSpec.Secrets}}' <some_service> ), listar dependências de serviços de docker secret inspect <secret_name> também seria útil. Então, eu apenas mantenho esse gráfico (aproximado) manualmente por enquanto.

Você também deve especificar o destino secreto, quando não é o /run/secrets/<secret_name> padrão no comando de atualização do serviço docker

Só espero uma maneira mais simples de alternar segredos

@caub aqui está uma ajuda de CLI:

Os documentos do Docker para formatação ajudam a encontrar o resto do formato de inspeção:

docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Secrets}}{{println .SecretName}}{{end}}'

Isso listará todos os nomes secretos em um serviço. Se você quisesse o nome e a identidade, poderia:

docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Secrets}}{{println .SecretName .SecretID}}{{end}}' nginx

Sempre tenho meu CI / CD (comandos de atualização de serviço) ou arquivos de pilha codificados no caminho para que você não tenha esse problema de rotação.

Com os rótulos, você pode fazer com que a automação de CI / CD identifique o segredo certo se não estiver usando arquivos de pilha (sem a necessidade do nome do segredo, que seria diferente a cada vez).

docker build --secret finalmente está disponível no Docker 18.09 https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

@thaJeztah Estamos prontos para encerrar este problema?

Para versões mais antigas do docker, usar a compilação de vários estágios com a cópia de segredos antes do comando de compilação é uma opção viável, certo?

`` `
FROM debian as build
COPY ./secret.conf / path / on / image /
RUN build.sh
...

DE debian
COPY --from = build ...

@andriy-f sim, isso funciona, contanto que você;

  • (obviamente) não copie o segredo para o estágio final 😉, ou:
  • use o estágio / estágio build no qual um segredo está presente como um "pai" para a imagem final
  • nunca _push_ o estágio de construção para um registro
  • confie no host no qual seu daemon é executado; ou seja, levando em consideração que seu estágio de "construção" é preservado como uma imagem; alguém com acesso a essa imagem seria capaz de obter acesso ao seu segredo.

segredos de tempo de construção agora são possíveis ao usar o buildkit como construtor; veja a postagem do blog aqui https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

e a documentação; https://docs.docker.com/develop/develop-images/build_enhancements/

a opção RUN --mount usada para segredos mudará para a sintaxe Dockerfile padrão (estável) em breve

Obrigado @thaJeztah .

Legal. Isso encerra a questão dos segredos do tempo de construção. Qualquer coisa para runtime / devtime (ssh no OS X)?

Esta página foi útil?
0 / 5 - 0 avaliações