Como trabalhar com Secrets no Docker 1.13.x
No dia 18 de janeiro de 2017, há menos de um mês foi lançada a versão 1.13 do Docker com uma porrada de novas e matadoras funcionalidades. Uma das que eu mais gostei foi a possibilidade de gerenciar secrets no Swarm Mode e é sobre ela que vou discorrer nesse artigo.
O que é o secret?
Quando estamos trabalhando em um projeto e precisamos passar informações sensíveis para o ambiente, tais como senhas, chaves privadas, tokens, chaves de APIs e afins sempre passamos pelo problema de não podermos deixar no controle de versão e devemos sempre utilizar uma maneira segura de trafegar esses segredos.
Muitas vezes acabamos trabalhando com variáveis de ambiente para guardar essas informações, o que não é recomendado por alguns motivos.
Diogo Monica que é um dos engenheiros de software da Docker mencionou em um comentário que variáveis de ambiente quebram o princípio de “least surprise” e podem levar a eventuais vazamentos de segredos já que estão acessíveis de várias maneiras, tais como linked containers, através do docker inspect, de processos filhos e até de arquivos de logs já que em caso de exceptions da aplicação muitos frameworks fazem o dump do contexto, inclusive o valor das variáveis de ambiente no arquivo de log.
Um pouco da história
Em Janeiro de 2015 houve uma proposta de adicionar o comando docker vault
numa alusão ao Vault Project da Hashicorp para fazer a gerencia de segredos dentro do próprio Docker. Segue o link para a issue 10310 no GitHub.
A discussão evoluiu e virou a issue 13490 onde trataram do roadmap para o atual Docker Secrets.
Como funciona?
O Docker Secrets funciona como um cofre onde você pode colocar coisas sensíveis lá e só que tem a chave do cofre consegue utilizar, no caso essa chave é designada aos nós dos serviços que a chave for atribuída.
Dicas
Só funciona no Swarm Mode onde toda a comunicação entre os nós é por padrão encriptada.
Se utiliza do algoritmo de RAFT para persistir o segredo de forma encriptada por todos os nós managers e distribuir aos contêineres que fizerem parte do serviço ao qual a chave for atribuida.
Segue diagrama da própria Docker:
Criando um secret
Podemos criar um secret de duas maneiras, usando o STDIN:
$ echo "ConteudoDoSecret" | docker secret create um-secret -
Ou lendo um arquivo:
$ docker secret create novo-secret $HOME/senhas.txt
Listando, removendo e demais opções
Para listar as secrets disponíveis:
$ docker secrets ls
ID NAME CREATED UPDATED
8ulrzh4i1kdlxeypgh8hx5imt um-secret 3 minutes ago 3 minutes ago
n95fprwd2trpqnjooojmpsh6z novo-secret About an hour ago About an hour ago
Demais opções do que fazer com os secrets como remover, inspecionar, etc podem ser listadas com o help:
$ docker secret --help
Usando o secret criado
Podemos criar um serviço usando um secret criado com o comando:
$ docker service create --name demo --secret um-secret mysql:5.7
Podemos remover um secret de algum serviço existente
$ docker service update --secret-rm um-secret demo
Ou podemos adicionar um secret a algum service que esteja de pé:
$ docker service update --secret-add novo-secret demo
Quando atrelamos um secret a um service podemos então acessar qualquer um dos contêineres que estejam rodando nesse service no path /run/secrets. Dentro do contêiner nesse path vai existir um arquivo plain text com o nome igual ao definido no nome do secret e com o conteúdo desejado, o secret em plain text. No nosso caso seria no path /run/secrets/novo-secret.
Exemplo
Segue exemplo onde criamos e utilizando um secret como senha para um banco de dados MySQL, ao final nós conectamos ao MYSQL usando a mesma senha passada como secret para a criação do serviço.
Até a próxima.