Ci sono alcune opzioni per memorizzare le password e altri segreti che un programma Python deve usare, in particolare un programma che deve essere eseguito in background dove non può semplicemente chiedere all'utente di digitare la password.
Problemi da evitare:
- Controllo della password per il controllo del codice sorgente dove altri sviluppatori o anche il pubblico possono vederlo.
- Altri utenti sullo stesso server leggono la password da un file di configurazione o da un codice sorgente.
- Avere la password in un file sorgente in cui gli altri possono vederla sopra le tue spalle mentre la modifichi.
Opzione 1: SSH
Questa non è sempre un'opzione, ma probabilmente è la migliore. La tua chiave privata non viene mai trasmessa sulla rete, SSH esegue solo calcoli matematici per dimostrare che hai la chiave giusta.
Per farlo funzionare, hai bisogno di quanto segue:
- Il database o qualsiasi cosa a cui stai accedendo deve essere accessibile da SSH. Prova a cercare "SSH" più qualsiasi servizio a cui stai accedendo. Ad esempio, "ssh postgresql" . Se questa non è una funzionalità del tuo database, passa all'opzione successiva.
- Creare un account per eseguire il servizio che effettuerà chiamate al database e generare una chiave SSH .
- Aggiungi la chiave pubblica al servizio che stai per chiamare o crea un account locale su quel server e installa lì la chiave pubblica.
Opzione 2: variabili d'ambiente
Questo è il più semplice, quindi potrebbe essere un buon punto di partenza. È descritto bene nell'app Twelve Factor . L'idea di base è che il codice sorgente estrae semplicemente la password o altri segreti dalle variabili di ambiente e quindi si configurano tali variabili di ambiente su ciascun sistema in cui si esegue il programma. Potrebbe anche essere un bel tocco se usi valori predefiniti che funzioneranno per la maggior parte degli sviluppatori. Devi bilanciarlo con il rendere il tuo software "sicuro per impostazione predefinita".
Ecco un esempio che estrae il server, il nome utente e la password dalle variabili di 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)
Cerca come impostare le variabili di ambiente nel tuo sistema operativo e considera di eseguire il servizio con il proprio account. In questo modo non hai dati sensibili nelle variabili di ambiente quando esegui programmi nel tuo account. Quando si impostano queste variabili di ambiente, fare particolare attenzione che gli altri utenti non possano leggerle. Controlla i permessi dei file, ad esempio. Ovviamente tutti gli utenti con i permessi di root saranno in grado di leggerli, ma questo non può essere aiutato. Se stai usando systemd, guarda l' unità di servizio e fai attenzione a usarla al EnvironmentFile
posto di Environment
eventuali segreti. Environment
i valori possono essere visualizzati da qualsiasi utente con systemctl show
.
Opzione 3: file di configurazione
Questo è molto simile alle variabili d'ambiente, ma leggi i segreti da un file di testo. Trovo ancora le variabili di ambiente più flessibili per cose come strumenti di distribuzione e server di integrazione continua. Se decidi di utilizzare un file di configurazione, Python supporta diversi formati nella libreria standard, come JSON , INI , netrc e XML . Puoi anche trovare pacchetti esterni come PyYAML e TOML . Personalmente, trovo JSON e YAML i più semplici da usare e YAML consente i commenti.
Tre cose da considerare con i file di configurazione:
- Dov'è il file? Forse una posizione predefinita come
~/.my_app
e un'opzione della riga di comando per utilizzare una posizione diversa.
- Assicurati che gli altri utenti non possano leggere il file.
- Ovviamente, non eseguire il commit del file di configurazione nel codice sorgente. Potresti voler eseguire il commit di un modello che gli utenti possono copiare nella loro directory home.
Opzione 4: modulo Python
Alcuni progetti mettono semplicemente i loro segreti in un modulo Python.
db_server = 'dbhost1'
db_user = 'my_app'
db_password = 'correcthorsebatterystaple'
Quindi importa quel modulo per ottenere i valori.
from settings import db_server, db_user, db_password
db_connect(db_server, db_user, db_password)
Un progetto che utilizza questa tecnica è Django . Ovviamente, non dovresti impegnarti settings.py
nel controllo del codice sorgente, anche se potresti voler eseguire il commit di un file chiamato settings_template.py
che gli utenti possono copiare e modificare.
Vedo alcuni problemi con questa tecnica:
- Gli sviluppatori potrebbero salvare accidentalmente il file nel controllo del codice sorgente. Aggiungerlo a
.gitignore
riduce tale rischio.
- Parte del codice non è sotto il controllo del codice sorgente. Se sei disciplinato e metti solo stringhe e numeri qui, non sarà un problema. Se inizi a scrivere classi di filtri di registrazione qui, fermati!
Se il tuo progetto utilizza già questa tecnica, è facile passare alle variabili di ambiente. Basta spostare tutti i valori di impostazione nelle variabili di ambiente e modificare il modulo Python per leggere da quelle variabili di ambiente.