Desenvolvimento

7 mar, 2017

Como trabalhar com Secrets no Docker 1.13.x

Publicidade

Em 18 de janeiro foi lançada a versão 1.13 do Docker com um monte de funcionalidades novas e matadoras. 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 gerência 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 e só quem 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.

Utiliza-se o 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

Veja abaixo um exemplo onde criamos e utilizamos 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: