Saltar para o conteúdo principal Saltar para a navegação Saltar para o rodapé
Por tempo limitado: Programa de Parceiro de Design. Plano BUSINESS grátis para sempre.

Gerir Segredos

Coloque credenciais de implementação num lugar a que os forks não conseguem aceder. Apenas escrita por design.

Gerir Segredos

Isto é importante sobre os forks: são cópias byte-a-byte da imagem encriptada, credenciais e tudo. Uma chave Stripe de produção, uma palavra-passe de base de dados, um token de API no repositório? O fork herda-os. O seu sandbox acaba por cobrar cartões de clientes reais.

O lugar certo é rdc repo secret. Dois modos de entrega, apenas escrita por design, e o fork começa sem nada. Neste tutorial definimos os dois tipos, implementamos uma aplicação que os consome, provamos que os valores chegam mesmo ao contentor, e depois vemos um fork falhar ao arrancar porque os segredos recusaram segui-lo.

Ver o tutorial

A armadilha: .env no repositório

A .env file inside the repo image gets cloned by every fork

A maioria das equipas coloca .env no repositório. É o movimento óbvio.

Depois fazem um fork.

O fork é uma cópia byte-a-byte da imagem do pai. O que quer que esteja em .env está no .env do fork. Os contentores do fork arrancam. Leem a mesma chave Stripe. Chamam a mesma API Stripe com credenciais de produção. Do ponto de vista do Stripe, essa chamada é você.

É um mau dia. Pergunte-me como sei.

Passo 1: Definir um segredo em modo env

rdc repo secret set --name my-app --key DB_HOST --value postgres.internal --mode env

Primeiro, defina um segredo no modo env. O valor chega como uma variável de ambiente dentro do container. Primeiras gravações não exigem cerimônia, é a substituição de um segredo existente que requer comprovação.

--mode env faz com que o valor chegue como variável de ambiente dentro do contentor. Primeiras escritas não precisam de cerimónia; é a substituição de um segredo existente que exige prova do valor atual.

Passo 2: Definir um segredo em modo file

rdc repo secret set --name my-app --key STRIPE_KEY --value sk_test_xxx --mode file

Agora defina um segredo no modo file. O modo file nunca expõe o valor pelo ambiente do container; ele grava o valor em um arquivo em /run/secrets usando o mecanismo padrão de segredos do Docker. Prefira o modo file para qualquer coisa sensível.

O modo file nunca coloca o valor no ambiente do contentor. Escreve-o em /run/secrets/stripe_key usando o mecanismo padrão do Docker. Prefira este para qualquer coisa sensível.

Passo 3: Listar o que tem

rdc repo secret list --name my-app

Vamos listar o que temos. Apenas nomes e modos. A listagem nunca mostra os valores, independente de quem está pedindo.

Vê nomes e modos. Sem valores. A lista nunca mostra valores, independentemente de quem pergunta.

Integrar no compose

Abra docker-compose.yml. Referencie ambos os modos:

services:
  api:
    image: myapp:latest
    environment:
      DATABASE_HOST: ${REDIACC_SECRET_DB_HOST}
    secrets:
      - stripe_key

secrets:
  stripe_key:
    file: /var/run/rediacc/secrets/${REDIACC_NETWORK_ID}/STRIPE_KEY

${REDIACC_SECRET_DB_HOST} é o modo env: o wrapper compose do renet expande-o a partir do seu armazenamento de segredos no momento da implementação.

O bloco secrets: é o modo file, usando o mecanismo padrão do Docker. O caminho do anfitrião usa ${REDIACC_NETWORK_ID} para que o mesmo compose funcione para pais e forks. Cada fork tem o seu próprio ID de rede.

Nunca o pode ler de volta

Write-only model: get returns a digest, never the value

Aqui está a parte que surpreende as pessoas pela primeira vez, até a mim.

Passo 4: Get devolve um digest

rdc repo secret get --name my-app --key STRIPE_KEY

O comando secret get retorna um digest, não o valor, e não há nenhuma flag para recuperar o texto original. Isso segue o modelo do GitHub Actions: segredos são somente gravação por design.

Obtém um digest. Não o valor. Não existe nenhum sinalizador que faça devolver o valor. Não há nenhum comando em lado algum que lhe dê o texto simples de volta.

É o modelo do GitHub Actions: apenas escrita. Pode provar que sabe qual é um segredo passando --current <value> e vendo a pré-condição passar. Não pode pedir ao Rediacc para lhe dizer o que é.

Passo 5: Faça rotação quando esquecer

Perdeu o valor? Não espie. Faça rotação.

rdc repo secret set --name my-app --key STRIPE_KEY --value sk_test_new --mode file --rotate-secret

Se você perder o controle do valor de um segredo, rotacione-o em vez de tentar recuperá-lo. A flag rotate-secret ignora a verificação de pré-condição e o log de auditoria registra a mudança como uma rotação deliberada.

--rotate-secret ignora a pré-condição. O registo de auditoria marca-o como uma rotação: explícito, deliberado.

Se ainda se lembrar do valor antigo, prove-o em vez disso com --current <old-value>. É o caminho mais seguro. Apanha-me mais de uma vez quando estou no terminal errado ou na máquina errada.

Implementar e provar a entrega

Segredos que nunca chegam à aplicação são apenas uma base de dados elaborada. Implemente e verifique os dois caminhos de entrega.

Passo 6: Implementar com os dois segredos

rdc repo up --name my-app --machine <machine-name>

Faça o deploy do repo. O compose file consome ambos os segredos: o valor env via interpolação, o valor file via um mount de segredos do Docker.

Passo 7: O segredo env chega

rdc term connect --machine <machine-name> --repository my-app --command 'docker exec app printenv DB_HOST'

Imprima a variável dentro do container: postgres.internal. O segredo no modo env chegou ao app no momento do deploy.

O contentor imprime postgres.internal. A aplicação recebeu mesmo o valor, expandido no seu ambiente no momento da implementação.

Passo 8: O segredo file chega

rdc term connect --machine <machine-name> --repository my-app --command 'docker exec app cat /run/secrets/stripe_key'

Leia /run/secrets/stripe_key dentro do container: o valor rotacionado está montado lá. O app recebe o texto original; apenas a CLI se recusa a exibi-lo.

E está lá o valor após rotação, lido de /run/secrets/stripe_key dentro do contentor. Apenas escrita aplica-se a humanos e ao CLI; a sua aplicação recebe o texto simples real onde o Docker promete que estará.

A conclusão do fork

After fork, the secrets list is empty

Lembra-se da armadilha? Faça um fork do repositório e veja.

Passo 9: Fork do repositório

rdc repo fork --parent my-app --tag test --machine <machine-name>

Faça um fork do repo. O fork é uma cópia byte a byte da imagem criptografada do pai.

Passo 10: O fork lista vazio

rdc repo secret list --name my-app:test

Listar os segredos do fork retorna um conjunto vazio: nenhuma chave Stripe, nenhuma senha de banco de dados, nenhum token de API. O fork não pode se passar pelo pai, e é isso que torna seguro clonar a produção.

Vazio.

O fork não tem chave Stripe. Nem palavra-passe de base de dados. Nem token de API. Os contentores no fork não conseguem interpolar ${REDIACC_SECRET_STRIPE_KEY}. O ficheiro em /var/run/rediacc/secrets/<fork-id>/STRIPE_KEY não existe.

O fork não consegue fazer-se passar por si.

Passo 11: O fork nem consegue arrancar

rdc repo up --name my-app:test --machine <machine-name>

Iniciar o fork com o compose do pai falha: o arquivo de segredo não existe sob o ID de rede do fork, então o Docker recusa o bind mount. Credenciais de produção nunca acompanham um fork.

A implementação falha propositadamente: bind source path does not exist: /var/run/rediacc/secrets/<fork-id>/STRIPE_KEY. O ficheiro de segredo existe sob o ID de rede do pai, não do fork, por isso o Docker recusa a montagem. A falha é a demonstração: as credenciais de produção nunca seguem um fork, nem por acidente.

Se quiser segredos no fork para testes, defina-os explicitamente no fork com valores de sandbox, por exemplo rdc repo secret set --name my-app:test --key STRIPE_KEY --value sk_sandbox_yyy --mode file. Agora o fork fala com o sandbox do Stripe e arranca sem problemas. As credenciais de produção nunca saíram da produção.

Resumo

  • rdc repo secret coloca as suas credenciais fora da imagem do repositório.
  • Os dois modos chegam mesmo ao contentor: interpolação env e /run/secrets.
  • get devolve um digest, nunca o valor. Faça rotação quando esquecer; não espie.
  • O fork lista vazio e nem consegue arrancar o compose do pai.

Segredos que o fork não consegue seguir.


Próximo: Backup e Restauro.