Onde este app guarda os segredos
Toda aplicação tem um punhado de valores que não são código e não podem ser públicos. Uma senha de banco, uma chave de API, o token que assina os cookies. Este curso é sobre onde eles moram, e este repositório é incomumente interessante porque usa dois mecanismos ao mesmo tempo.
O que tem aqui
config/credentials.yml.enc # criptografado, versionado
config/master.key # a chave, ignorada pelo git
E o conteúdo:
Rails.application.credentials.config.keys
# => [:secret_key_base]
Um valor. Enquanto isso, a aplicação lê os outros segredos do ambiente (sete nomes na lista secret do config/deploy.yml, além da chave mestra):
# config/initializers/omniauth.rb
provider :github, ENV["GITHUB_KEY"], ENV["GITHUB_SECRET"], scope: "user:email"
# config/environments/production.rb
user_name: ENV["SMTP_USERNAME"],
password: ENV["SMTP_PASSWORD"],
Então a divisão, na prática, é: secret_key_base nas credenciais criptografadas, todo o resto em variáveis de ambiente.
Isso não é acidente e não está obviamente errado. É um desenho a que a maioria das aplicações Rails converge sem decidir. E este curso é sobre se ele é o certo, o que exige entender o que cada mecanismo oferece.
A única coisa que está definitivamente certa
git check-ignore -v config/master.key
# .gitignore:34:/config/master.key config/master.key
git log --all -- config/master.key
# (sem saída)
A chave é ignorada, e nunca foi versionada: em nenhum branch, em nenhum commit alcançável de qualquer lugar deste repositório. Essa segunda checagem é a que as pessoas pulam, e é a que importa. Uma chave ignorada hoje e versionada um ano atrás continua no histórico, e continua comprometida.
Rode aquele comando nos seus próprios repositórios. O --all é essencial: uma chave versionada num branch depois apagado continua alcançável, e continua lá.
flowchart TB
S["Um segredo"] --> Q{"onde ele mora?"}
Q -->|"credenciais criptografadas"| C["credentials.yml.enc, versionado"]
C --> K["master.key, nunca versionada"]
Q -->|"ambiente"| E["ENV, definido pela plataforma"]
E --> P["env.secret do Kamal, ou o cofre da plataforma"]
K -.->|"se isto vazar"| B["tudo no arquivo é público"]
Os dois mecanismos
| Credenciais criptografadas | Variáveis de ambiente | |
|---|---|---|
| Onde o valor mora | No repositório, criptografado | Na plataforma, fora do código |
| Onde a confiança mora | Uma chave, distribuída à parte | O cofre de segredos da plataforma |
| Mudar um valor | Editar, commitar, publicar | Mudar e reiniciar |
| Quem consegue ler | Quem tem a chave mestra | Quem consegue ler o processo |
| Rotação | Um commit | Uma mudança de configuração |
| Trilha de auditoria | Histórico do git, do texto cifrado | O que a sua plataforma registrar |
| Diferente por ambiente | Sim, com arquivos de chave separados | Naturalmente |
Duas linhas merecem ser lidas juntas. Mudar um valor é um commit com credenciais, o que é uma trilha de auditoria útil ou uma exigência de deploy inconveniente, dependendo do segredo. E diferente por ambiente é onde os dois mecanismos mais diferem na prática. O destino de staging dos cursos de deploy precisa de valores diferentes, e as duas abordagens resolvem isso de formas bem distintas.
O que não é segredo
Vale dizer cedo porque é onde o esforço se perde.
Uma chave de API pública que aparece no seu JavaScript não é segredo, por mais que o painel do fornecedor a chame assim. Uma chave de site de analytics, uma chave publicável do Stripe, uma chave de tiles de mapa. Elas são entregues a todo navegador, e criptografá-las no credentials.yml.enc não protege nada.
Elas pertencem à configuração, não aos segredos. Colocá-las nas credenciais não é danoso, e dilui o arquivo, o que dificulta para a próxima pessoa ver quais valores importam.
O teste: quem tiver este valor conseguiria fazer algo que já não conseguia? Se o valor já está em todo navegador, a resposta é não.
O que este curso cobre
- Onde este app guarda os segredos (esta aula).
- Credenciais criptografadas, com precisão.
- Variáveis de ambiente, com precisão.
- Escolhendo entre elas.
- Rotação, e o que fazer depois de um vazamento.
- Segredos na pipeline.
- Juntando tudo: um plano de credenciais.
Pontos-chave
- Este repositório guarda só o
secret_key_basenas credenciais criptografadas e lê todo outro segredo do ambiente. - O
config/master.keyé ignorado e, verificado comgit log --all, nunca foi versionado. - Confira o histórico com
--all, porque uma chave num branch apagado continua alcançável e continua comprometida. - Os mecanismos mais diferem em onde mora a confiança, como um valor é mudado, e como os ambientes divergem.
- Uma chave que vai para todo navegador é configuração, não segredo; criptografá-la não protege nada e dilui o arquivo.
Continue com a aula 2
Credenciais criptografadas, com precisão
Explica as credenciais criptografadas: arquivos por ambiente, distribuição da chave, diffs ilegíveis e o que se perde sem a chave.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.