14. Docker Secrets

Ninguém tem dúvida de que a arquitetura de microsserviços já se provou eficiente. Porém, implementar segurança, principalmente em um contexto de infraestrutura imutável, tem sido um belo desafio.

Com questões que envolvem desde como separar a senha do template em uma imagem até como trocar a senha de acesso a um serviço sem interrompê-lo, workarounds não faltam. Mas como sempre dá para melhorar, na versão 1.13 nossos queridos amigos do Docker lançaram o que foi chamado de Docker Secrets.

O Docker Secrets é a solução do Docker para trabalhar com toda a parte de secrets em um ambiente multi-node e multi-container. Em outras palavras, um "swarm mode" cluster. A secret pode conter qualquer coisa, porém deve ter um tamanho máximo de 500 KB. Por enquanto essa belezinha não está disponível fora do contexto do Docker Swarm -- na verdade, não é claro se vai algum dia ser diferente. Por enquanto somos encorajados a usar um service para fazer deploy de containers individuais.

14.1. O comando docker secret

O comando "docker secret" vem com alguns subcomandos. São eles:

docker secret --help

Usage: docker secret COMMAND

Manage Docker secrets

Options:
     --help Print usage

Commands:
    create   Create a secret from a file or STDIN as content
    inspect  Display detailed information on one or more secrets
    ls       List secrets
    rm       Remove one or more secrets

Run 'docker secret COMMAND --help' for more information on a command.
  • create -- Cria uma secret a partir do conteúdo de um arquivo ou STDIN.

  • inspect -- Mostra informações detalhadas de uma ou mais secrets.

  • ls -- Lista as secrets existentes.

  • rm -- Remove uma ou mais secrets.

Create

Como dito, o "create" aceita conteúdo tanto do STDIN...

root@linuxtips:~# echo 'minha secret' | docker secret create minha_secret -
jxr0pilzhtqsiqi1f1fjmmg4t

root@linuxtips:~#

...quanto de um arquivo:

root@linuxtips:~# docker secret create minha_secret minha_secret.txt
ci7mse43i5ak378sg3qc4xt04

root@linuxtips:~#

Inspect

Fique tranquilo, o "inspect" não mostra o conteúdo da sua secret! :P

Em vez disso, ele mostra uma série de informações sobre a secret, incluindo sua criação e modificação (apesar de não ter, na verdade, como modificar uma secret; uma vez criada, ela não pode ser atualizada via CLI, porém já há um endpoint na API do Docker Swarm para update de secret -- "/secrets/{id}/update", vamos aguardar!)

root@linuxtips:~# docker secret inspect minha_secret
[
    {
        "ID": "ci7mse43i5ak378sg3qc4xt04",
        "Version": {
            "Index": 808
        },
        "CreatedAt": "2017-07-02T17:17:18.143116694Z",
        "UpdatedAt": "2017-07-02T17:17:18.143116694Z",
        "Spec": {
            "Name": "minha_secret",
            "Labels": {}
        }
    }
]

root@linuxtips:~#

O "inspect" aceita mais de uma secret por vez e mostrará o resultado na mesma sequência.

ls && rm

Servem respectivamente para listar suas secrets e removê-las.

root@linuxtips:~# docker secret ls
ID                         NAME           CREATED             UPDATED
ci7mse43i5ak378sg3qc4xt04  minha_secret   About a minute ago  About a minute ago

root@linuxtips:~#
root@linuxtips:~# docker secret rm minha_secret
minha_secret

root@linuxtips:~#

14.2. Tudo bem, mas como uso isso?

As secrets são consumidas por serviços, como já citamos, e isso acontece através de associação explícita, usando a flag "--secret" na hora de criar um serviço. Vamos para um exemplo.

Primeiro vamos criar uma secret com a senha do banco de dados da nossa aplicação fake.

root@linuxtips:~# echo 'senha_do_banco' | docker secret create db_pass -
kxzgmhlu3ytv64hbqzg30nc8u

root@linuxtips:~#

Agora, vamos associá-la à nossa app, criando um serviço.

root@linuxtips:~# docker service create --name app --detach=false --secret db_pass minha_app:1.0
npfmry3vcol61cmcql3jiljk2
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Waiting 1 seconds to verify that tasks are stable...

root@linuxtips:~# docker service ls
ID            NAME      MODE        REPLICAS   IMAGE           PORTS
npfmry3vcol6  app       replicated  1/1        minha_app:1.0

root@linuxtips:~# docker container ls
CONTAINER ID     IMAGE          COMMAND                   CREATED           STATUS           PORTS     NAMES
65d1533f5b50     minha_app:1.0  "/bin/sh -c ./scri..."   40 seconds ago     Up 39 seconds              app.1.molbmj0649c7xkzfermkuwrx2

root@linuxtips:~#

Também é possível dar acesso a keys para serviços já criados, através da flag "--secret-add" do comando "docker service update", assim como revogá-las, usando a flag "--secret-rm" no mesmo comando. Ver o tópico "Atualizando a secret de um serviço".

14.3. Acessando a secret

Com o serviço criado, a secret ficará disponível para todos os containers daquele service e estará em arquivos dentro do diretório "/run/secrets", montado em tmpfs. Se a sua secret chamar "db_pass", como no exemplo, o conteúdo dela estará em "/run/secrets/db_pass".

É possível incluir alguns parâmetros na hora de adicionar uma secret a um serviço, como, por exemplo, o target, que altera o nome do arquivo no destino e até itens de segurança, como uid, gid e mode:

docker service create --detach=false --name app --secret source=db_pass,target=password,uid=2000,gid=3000,mode=0400 minha_app:1.0

Dentro do container ficaria assim:

root@4dd6b9cbff1a:/app# ls -lhart /run/secrets/
total 12K
-r-------- 1 2000 3000   15 Jul 2 17:44 password
drwxr-xr-x 7 root root 4.0K Jul 2 17:44 ..
drwxr-xr-x 2 root root 4.0K Jul 2 17:44 .

root@4dd6b9cbff1a:/app#

E aí basta que a sua aplicação leia o conteúdo do arquivo.

root@8b16b5335334:/app# python
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> secret = open('/run/secrets/password').read()
>>>
>>> print "minha secret e: %s" % (secret)
minha secret e: nova_senha
>>>

14.4. Atualizando a secret de um serviço

Secrets foram criadas para serem imutáveis, ou seja, caso você queira trocar a secret de um serviço, você precisará criar outra secret. A troca da secret é bem fácil. Por exemplo, para trocar a secret "db_pass" do exemplo anterior, teríamos que fazer o seguinte:

Criar uma nova secret:

root@linuxtips:~# echo 'nova_senha' | docker secret create db_pass_1 -
221uzilbsl1ybna7g7014hoqr

root@linuxtips:~#

Adicionar à secret a app criada anteriormente:

root@linuxtips:~# docker service update --secret-rm db_pass --detach=false --secret-add source=db_pass_1,target=password app
app
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Waiting 1 seconds to verify that tasks are stable...

root@linuxtips:~#

Após a atualização, basta remover a secret antiga:

root@linuxtips:~# docker secret rm db_pass
db_pass

root@linuxtips:~#

results matching ""

    No results matching ""