Existem algumas opções para armazenar senhas e outros segredos que um programa Python precisa usar, particularmente um programa que precisa ser executado em segundo plano, onde não pode simplesmente pedir ao usuário para digitar a senha.
Problemas a evitar:
- Verificar a senha no controle de origem, onde outros desenvolvedores ou até mesmo o público podem vê-la.
- Outros usuários no mesmo servidor lendo a senha de um arquivo de configuração ou código-fonte.
- Ter a senha em um arquivo de origem onde outras pessoas possam vê-la por cima do ombro enquanto você a edita.
Opção 1: SSH
Nem sempre isso é uma opção, mas provavelmente é a melhor. Sua chave privada nunca é transmitida pela rede, o SSH apenas executa cálculos matemáticos para provar que você tem a chave certa.
Para fazer funcionar, você precisa do seguinte:
- O banco de dados ou o que você está acessando precisa estar acessível por SSH. Tente pesquisar por "SSH" e qualquer serviço que você está acessando. Por exemplo, "ssh postgresql" . Se este não for um recurso em seu banco de dados, vá para a próxima opção.
- Crie uma conta para executar o serviço que fará chamadas ao banco de dados e gere uma chave SSH .
- Adicione a chave pública ao serviço que você vai chamar ou crie uma conta local nesse servidor e instale a chave pública lá.
Opção 2: Variáveis de Ambiente
Este é o mais simples, então pode ser um bom lugar para começar. É bem descrito no aplicativo Twelve Factor . A ideia básica é que seu código-fonte apenas extraia a senha ou outros segredos das variáveis de ambiente e, em seguida, configure essas variáveis de ambiente em cada sistema em que executa o programa. Também pode ser um toque agradável se você usar valores padrão que funcionarão para a maioria dos desenvolvedores. Você deve equilibrar isso contra tornar seu software "seguro por padrão".
Aqui está um exemplo que extrai o servidor, o nome de usuário e a senha das variáveis de ambiente.
import os
server = os.getenv('MY_APP_DB_SERVER', 'localhost')
user = os.getenv('MY_APP_DB_USER', 'myapp')
password = os.getenv('MY_APP_DB_PASSWORD', '')
db_connect(server, user, password)
Veja como definir variáveis de ambiente em seu sistema operacional e considere a possibilidade de executar o serviço em sua própria conta. Dessa forma, você não tem dados confidenciais em variáveis de ambiente ao executar programas em sua própria conta. Ao configurar essas variáveis de ambiente, tome cuidado extra para que outros usuários não possam lê-las. Verifique as permissões do arquivo, por exemplo. Claro que qualquer usuário com permissão de root será capaz de lê-los, mas isso não pode ser ajudado.
Opção 3: arquivos de configuração
Isso é muito semelhante às variáveis de ambiente, mas você lê os segredos de um arquivo de texto. Ainda acho as variáveis de ambiente mais flexíveis para coisas como ferramentas de implantação e servidores de integração contínua. Se você decidir usar um arquivo de configuração, Python suporta vários formatos na biblioteca padrão, como JSON , INI , netrc e XML . Você também pode encontrar pacotes externos como PyYAML e TOML . Pessoalmente, acho JSON e YAML os mais simples de usar, e YAML permite comentários.
Três coisas a serem consideradas com arquivos de configuração:
- Onde está o arquivo? Talvez um local padrão como
~/.my_app
, e uma opção de linha de comando para usar um local diferente.
- Certifique-se de que outros usuários não possam ler o arquivo.
- Obviamente, não envie o arquivo de configuração para o código-fonte. Você pode querer enviar um modelo que os usuários possam copiar para seu diretório pessoal.
Opção 4: módulo Python
Alguns projetos simplesmente colocam seus segredos diretamente em um módulo Python.
# settings.py
db_server = 'dbhost1'
db_user = 'my_app'
db_password = 'correcthorsebatterystaple'
Em seguida, importe esse módulo para obter os valores.
# my_app.py
from settings import db_server, db_user, db_password
db_connect(db_server, db_user, db_password)
Um projeto que usa essa técnica é o Django . Obviamente, você não deve se comprometer settings.py
com o controle de origem, embora possa querer enviar um arquivo chamado settings_template.py
que os usuários possam copiar e modificar.
Vejo alguns problemas com essa técnica:
- Os desenvolvedores podem enviar acidentalmente o arquivo para o controle de origem. Adicioná-lo
.gitignore
reduz esse risco.
- Parte do seu código não está sob controle de origem. Se você for disciplinado e apenas colocar strings e números aqui, isso não será um problema. Se você começar a escrever classes de filtro de registro aqui, pare!
Se seu projeto já usa essa técnica, é fácil fazer a transição para variáveis de ambiente. Basta mover todos os valores de configuração para variáveis de ambiente e alterar o módulo Python para ler essas variáveis de ambiente.