Come posso salvare le mie chiavi segrete e la password in modo sicuro nel mio sistema di controllo della versione?


134

Conservo impostazioni importanti come i nomi host e le porte dei server di sviluppo e produzione nel mio sistema di controllo della versione. Ma so che è una cattiva pratica mantenere segreti (come chiavi private e password del database) in un repository VCS.

Ma le password - come qualsiasi altra impostazione - sembrano avere una versione. Quindi qual è il modo corretto di mantenere la versione controllata delle password?

Immagino che ciò implicherebbe mantenere i segreti nel loro file "impostazioni segreti" e avere quel file crittografato e controllato dalla versione. Ma quali tecnologie? E come farlo correttamente? C'è un modo completamente migliore per farlo?


Faccio la domanda in generale, ma nel mio caso specifico vorrei archiviare chiavi e password segrete per un sito Django / Python usando git e github .

Inoltre, una soluzione ideale farebbe qualcosa di magico quando spingo / estraggo con git - ad esempio, se il file delle password crittografate cambia viene eseguito uno script che richiede una password e la decodifica in posizione.


EDIT: Per chiarezza, sto chiedendo dove conservare i segreti di produzione .


1
Effettivamente versare un po 'di soldi per mantenere privato l'intero repo.
John Mee,

29
@JohnMee In realtà già pago per un repository privato, ma il punto rimane: non dovresti conservare le informazioni sensibili nel tuo repository.
Chris W.

1
Penso che gran parte del motivo per cui sarà difficile ottenere risposte soddisfacenti sia che la vecchia password in chiaro per collegarsi a un database è una reliquia di un'era meno ostile. La risposta corretta è qualcosa come "il tuo codice non dovrebbe aver bisogno di un segreto", ma i sistemi a cui stai accedendo non ti danno molta scelta.
msw,

4
Perché? C'è un valore zilch nella versione che controlla le password per i servizi esterni. Il valore principale del controllo della versione è che è possibile ispezionare revisioni storiche dell'applicazione note per funzionare ed eseguirle . Tuttavia, le vecchie password sono inutili per te. Se sono stati revocati, non funzioneranno mai più.
Colonnello Panic,

Risposte:


100

Hai esattamente ragione a voler crittografare il file delle impostazioni sensibili mantenendo comunque il file nel controllo della versione. Come accennato, la soluzione migliore sarebbe quella in cui Git crittograferà in modo trasparente determinati file sensibili quando li si spinge in modo che localmente (cioè su qualsiasi macchina che abbia il proprio certificato) sia possibile utilizzare il file delle impostazioni, ma Git o Dropbox o chiunque sia la memorizzazione dei file in VC non ha la possibilità di leggere le informazioni in testo normale.

Tutorial sulla crittografia / decrittografia trasparente durante Push / Pull

Questa sintesi https://gist.github.com/873637 mostra un tutorial su come utilizzare il driver di filtro sfumatura / pulizia di Git con openssl per crittografare in modo trasparente i file push. Hai solo bisogno di fare un po 'di configurazione iniziale.

Riepilogo di come funziona

Fondamentalmente creerai una .gitencryptcartella contenente 3 script bash,

clean_filter_openssl 
smudge_filter_openssl 
diff_filter_openssl 

che vengono utilizzati da Git per la decrittografia, la crittografia e il supporto di Git diff. Una passphrase master e salt (risolta!) Sono definiti all'interno di questi script e DEVI assicurarti che .gitencrypt non venga mai effettivamente spinto. clean_filter_opensslScript di esempio :

#!/bin/bash

SALT_FIXED=<your-salt> # 24 or less hex characters
PASS_FIXED=<your-passphrase>

openssl enc -base64 -aes-256-ecb -S $SALT_FIXED -k $PASS_FIXED

Simile per smudge_filter_open_ssle diff_filter_oepnssl. Vedi Gist.

Il tuo repository con informazioni riservate dovrebbe avere un file .gitattribute (non crittografato e incluso nel repository) che fa riferimento alla directory .gitencrypt (che contiene tutto ciò di cui Git ha bisogno per crittografare / decrittografare il progetto in modo trasparente) e che è presente sul tuo computer locale.

.gitattribute Contenuti:

* filter=openssl diff=openssl
[merge]
    renormalize = true

Infine, dovrai anche aggiungere il seguente contenuto al tuo .git/configfile

[filter "openssl"]
    smudge = ~/.gitencrypt/smudge_filter_openssl
    clean = ~/.gitencrypt/clean_filter_openssl
[diff "openssl"]
    textconv = ~/.gitencrypt/diff_filter_openssl

Ora, quando si sposta il repository contenente le informazioni sensibili in un repository remoto, i file verranno crittografati in modo trasparente. Quando si estrae da un computer locale che ha la directory .gitencrypt (contenente la passphrase), i file verranno decodificati in modo trasparente.

Appunti

Dovrei notare che questo tutorial non descrive un modo per crittografare solo il tuo file di impostazioni sensibili. Ciò crittograferà in modo trasparente l'intero repository che viene inviato all'host VC remoto e decrittograferà l'intero repository in modo che venga completamente decrittografato localmente. Per ottenere il comportamento desiderato, è possibile posizionare i file sensibili per uno o più progetti in uno sensitive_settings_repo. È possibile esaminare il modo in cui questa tecnica di crittografia trasparente funziona con i sottomoduli Git http://git-scm.com/book/en/Git-Tools-Submodules se è davvero necessario che i file sensibili si trovino nello stesso repository.

L'uso di una passphrase fissa potrebbe teoricamente portare a vulnerabilità a forza bruta se gli aggressori avessero accesso a molti repository / file crittografati. IMO, la probabilità di ciò è molto bassa. Come indicato nella parte inferiore di questo tutorial, il mancato utilizzo di una passphrase fissa comporterà versioni locali di un repository su macchine diverse, dimostrando sempre che si sono verificate modifiche con "stato git".


1
Oh molto interessante. Questo suona quasi esattamente come quello che voglio (tranne la sua crittografia dell'intero repository).
Chris W.

È possibile conservare tutti i file delle impostazioni sensibili per più applicazioni in un unico repository crittografato o aggiungere il repository crittografato con le impostazioni sensibili al progetto come sottomodulo Git come descritto qui git-scm.com/book/en/Git-Tools-Submodules .
dgh

La memorizzazione di password / impostazioni di produzione in un sottomodulo (crittografato) non è rara. stackoverflow.com/questions/11207284/… . Semplificherebbe persino la gestione delle impostazioni tra i progetti.
dgh

Potrebbe valere la pena controllare github.com/AGWA/git-crypt per una soluzione aggiornata. Ha il vantaggio di consentire la codifica di singoli file e afferma di essere "dimostrabile semanticamente sicuro". Lo stesso autore del suggerimento ha suggerito che questo strumento è migliore, su github.com/shadowhand/git-encrypt .
Geekley,

52

Heroku spinge l'uso di variabili d'ambiente per impostazioni e chiavi segrete:

L'approccio tradizionale per la gestione di tali configurazioni di configurazione è quello di metterle nel sorgente - in un file delle proprietà di qualche tipo. Questo è un processo soggetto a errori ed è particolarmente complicato per le app open source che spesso devono mantenere rami separati (e privati) con configurazioni specifiche dell'app.

Una soluzione migliore è utilizzare le variabili di ambiente e tenere le chiavi fuori dal codice. Su un host tradizionale o che lavora localmente, puoi impostare vari parametri ambientali nel tuo bashrc. Su Heroku, usi config vars.

Con Foreman e .envfile Heroku fornisce una toolchain invidiabile per esportare, importare e sincronizzare le variabili di ambiente.


Personalmente, credo che sia sbagliato salvare le chiavi segrete insieme al codice. È fondamentalmente incompatibile con il controllo del codice sorgente, poiché le chiavi sono per servizi estrinseci al codice . L'unico vantaggio sarebbe che uno sviluppatore può clonare HEAD ed eseguire l'applicazione senza alcuna configurazione. Tuttavia, supponiamo che uno sviluppatore verifichi una revisione storica del codice. La loro copia includerà la password del database dell'anno scorso, quindi l'applicazione avrà esito negativo rispetto al database di oggi.

Con il metodo Heroku sopra, uno sviluppatore può effettuare il checkout dell'app dell'anno scorso, configurarlo con le chiavi di oggi ed eseguirlo correttamente sul database di oggi.


1
Questa risposta non ha abbastanza attenzione, ma coincide soprattutto con il modo di Linux.
Nikolay Fominyh,

11
Quindi, se le variabili d'ambiente sono impostate nel tuo bashrc e stai distribuendo un nuovo server, allora cosa crea il bashrc? Questo non sposta semplicemente le password dal repository del codice sorgente e nella configurazione di distribuzione? (che è presumibilmente anche nel repository del codice sorgente o in un repository a parte?)
Jonathan Hartley,

@JonathanHartley il tuo .bashrc non dovrebbe essere nel repository di codice per la tua app Django.
Steve,

4
Scusa, il mio commento è ambiguo, ma è perché sono sinceramente confuso. Adoro il suono del punto di vista di questa risposta, ma non l'ho mai capito del tutto. Se sto eseguendo la distribuzione in diversi ambienti, ognuno dei quali contiene diversi host e forse diversi tipi di host, allora ovviamente devo automatizzare la creazione dei file .bashrc che esisteranno su ciascun host per impostare le sue variabili di ambiente. Quindi la risposta dice che dovrei avere un secondo repository, separato dalla mia fonte, che contiene tutte le impostazioni che diventeranno variabili di ambiente in .bashrc al momento della distribuzione?
Jonathan Hartley,

1
Devono essere configurati una sola volta per PER macchina su cui si distribuisce. Se il tuo processo di distribuzione è "gira su una nuova macchina e prova che è OK prima di reindirizzare il traffico su di essa e poi sparare a quello vecchio in testa", che IMHO è la migliore pratica, allora devi davvero automatizzare la creazione di qualsiasi set env vars.
Jonathan Hartley,

16

Il modo più pulito secondo me è usare le variabili d'ambiente. Ad esempio, non dovrai occuparti dei file .dist e lo stato del progetto nell'ambiente di produzione sarebbe lo stesso del tuo computer locale.

Consiglio di leggere il capitolo di configurazione dell'app The Dodici Fattori , anche gli altri, se sei interessato.


6
Sembra che le variabili di ambiente siano un buon modo per eseguire l'applicazione con le impostazioni segrete ... ma non risponde ancora alla domanda su dove conservare tali impostazioni.
Chris W.

2
Di solito dovresti avere un file README per ciascuna delle tue app. Lì, specifica quali variabili di ambiente devono essere impostate e ogni volta che distribuisci un progetto, segui semplicemente i passaggi e imposta ognuna di esse. È inoltre possibile creare uno script di shell con molti export MY_ENV_VAR=e, quando lo si distribuisce, basta riempirlo con i valori giusti e sourceesso. Se per mantenere intendi la versione delle impostazioni, non dovresti farlo in primo luogo.
Samy Dindane,

Inoltre, vota per The Twelve-Factor App - roba davvero fantastica.
Chris W.

4
@Samy: E se hai implementato automaticamente?
Jonathan Hartley,

3
@Samy Non capisco ancora come impostare le variabili di ambiente. La pagina dell'app a 12 fattori non chiarisce neanche questo (a meno che tu non sia su Heroku, che non è il mio progetto attuale). Stiamo dicendo che uno script di generazione deve chiedere a un negozio di configurazione centrale "Sono la macchina X, per favore dammi i miei dati di configurazione ", e questo risponde con i valori delle variabili di ambiente che dovrebbero essere impostati. In tal caso, non credo più che tu abbia bisogno di uno script generato. Sto speculando selvaggiamente qui, sto abbaiando sull'albero giusto?
Jonathan Hartley,

10

Un'opzione sarebbe quella di mettere le credenziali associate al progetto in un contenitore crittografato (TrueCrypt o Keepass) e inviarlo.

Aggiorna come risposta dal mio commento qui sotto:

Interessante domanda tra. Ho appena trovato questo: github.com/shadowhand/git-encrypt che sembra molto promettente per la crittografia automatica


Sarebbe bello avere qualcosa che potrei automatizzare. In modo tale che se il mio file di password crittografato cambia, decodifica automaticamente il nuovo file.
Chris W.

7
Interessante domanda tra. Ho appena trovato questo: github.com/shadowhand/git-encrypt che sembra molto promettente per la crittografia automatica.
schneck,

1
Wow grande. La descrizione di git-encryptsuoni esattamente come quello che sto cercando "Quando si lavora con un repository git remoto ospitato su un server di archiviazione di terze parti, la riservatezza dei dati a volte diventa una preoccupazione. Questo articolo illustra le procedure di configurazione dei repository git per cui le directory di lavoro locali sono normali (non crittografate) ma i contenuti impegnati sono crittografati. " (Certo, voglio solo un sottoinsieme dei miei contenuti crittografati ...)
Chris W.

@schneck pubblica il tuo commento come una risposta in modo che Chris possa accettarlo - sembra che sia quello che sta cercando.
Tony Abou-Assaleh,

9

Suggerisco di usare i file di configurazione per quello e di non versioni.

È comunque possibile esempi di versione dei file.

Non vedo alcun problema di condivisione delle impostazioni di sviluppo. Per definizione non dovrebbe contenere dati preziosi.


1
Ma allora dove archiviare i record della password canonica? Mi innervosirebbe che quei dati si trovassero solo in un file di configurazione su una macchina che potrebbe esplodere un giorno.
Chris W.

@ChrisW. Se la macchina esplode, non hai più necessariamente bisogno della password ... Tuttavia, se hai solo una copia dei dati sulla tua macchina di produzione, dovrebbe apparire una bandiera rossa. Ma ciò non significa che dovrebbe essere in VCS. Dovrebbe esserci RAID, backup completi integrati da backup incrementali su supporti magnetici e ottici. Molte aziende hanno una procedura di controllo delle modifiche che può dettare come e dove archiviare su carta password e altri materiali sensibili.
Steve Buzonas,

@ChrisW Non voglio essere volgare ma sembra che tu non ci dica la verità e le password che vuoi conservare non sono utilizzate nello sviluppo ma nella produzione. Non è vero? Altrimenti, perché ti interessa una macchina di sviluppo o di prova e password di sviluppo? Nessuno lo farebbe.
tiktak,

A proposito, presso la nostra azienda, tutte le password di sviluppo sono disponibili su carta e sull'intranet. Perché non hanno valore. Sono lì perché il software che sviluppiamo necessita di autenticazione.
tiktak

@tiktak, hai ragione: la mia domanda riguarda cosa fare riguardo alle password di produzione. Non mi interessa particolarmente archiviare le password di sviluppo in A VCS in chiaro. Scusa se non l'ho chiarito abbastanza.
Chris W.

7

BlackBox è stato recentemente rilasciato da StackExchange e mentre devo ancora usarlo, sembra affrontare esattamente i problemi e supportare le funzionalità richieste in questa domanda.

Dalla descrizione su https://github.com/StackExchange/blackbox :

Conserva in modo sicuro i segreti in un repository VCS (ad es. Git o Mercurial). Questi comandi ti facilitano la crittografia GPG di file specifici in un repository in modo che siano "crittografati a riposo" nel tuo repository. Tuttavia, gli script semplificano la decrittografia quando è necessario visualizzarli o modificarli e decrittografarli per l'utilizzo in produzione.


7

Da quando ho posto questa domanda, ho optato per una soluzione, che utilizzo quando sviluppo piccole applicazioni con un piccolo team di persone.

git-crypt

git-crypt usa GPG per crittografare in modo trasparente i file quando i loro nomi corrispondono a determinati schemi. Per intenderci, se aggiungi al tuo .gitattributesfile ...

*.secret.* filter=git-crypt diff=git-crypt

... quindi un file come config.secret.jsonverrà sempre inviato ai repository remoti con crittografia, ma rimarrà non crittografato sul file system locale.

Se voglio aggiungere una nuova chiave GPG (una persona) al tuo repository che può decrittografare i file protetti, quindi esegui git-crypt add-gpg-user <gpg_user_key>. Questo crea un nuovo commit. Il nuovo utente sarà in grado di decrittografare i commit successivi.


5

Faccio la domanda in generale, ma nel mio caso specifico vorrei archiviare chiavi e password segrete per un sito Django / Python usando git e github.

No, non farlo, anche se si tratta del tuo repository privato e non hai mai intenzione di condividerlo, non farlo.

Dovresti creare un local_settings.py metterlo su VCS ignora e nelle tue impostazioni.py fai qualcosa di simile

from local_settings import DATABASES, SECRET_KEY
DATABASES = DATABASES

SECRET_KEY = SECRET_KEY

Se le tue impostazioni di segreti sono così versatili, sono ansioso di dire che stai facendo qualcosa di sbagliato


9
Ma dovrò ancora tenere traccia di quei segreti da qualche parte . Ad esempio, il keypass o qualcosa del genere, giusto?
Chris W.,

La regolamentazione e l'implementazione dell'archiviazione di dati privati ​​dipende dalla politica della società per cui il progetto. Dubito fortemente che il codice sorgente del progetto sia il posto giusto in quanto qualsiasi tester o programmatore di terze parti potrebbe vederli
Hedde van der Heide,

4

EDIT: presumo che tu voglia tenere traccia delle tue precedenti versioni di password - diciamo, per uno script che impedirebbe il riutilizzo della password ecc.

Penso che GnuPG sia il modo migliore di procedere: è già utilizzato in un progetto relativo a git (git-annex) per crittografare i contenuti del repository archiviati sui servizi cloud. GnuPG (gnu pgp) fornisce una crittografia basata su chiave molto potente.

  1. Tieni una chiave sul tuo computer locale.
  2. Aggiungi 'mypassword' ai file ignorati.
  3. All'hook pre-commit si crittografa il file mypassword nel file mypassword.gpg tracciato da git e lo si aggiunge al commit.
  4. Con l'hook post-merge basta decifrare mypassword.gpg in mypassword.

Ora se il tuo file 'mypassword' non è cambiato, la crittografia provocherà lo stesso testo cifrato e non verrà aggiunto all'indice (nessuna ridondanza). La più piccola modifica di mypassword comporta un testo cifrato e mypassword.gpg radicalmente diversi nell'area di gestione temporanea differisce molto da quello nel repository, pertanto verrà aggiunto al commit. Anche se l'attaccante ottiene una chiave gpg deve comunque forzare la password. Se l'attaccante ottiene un accesso al repository remoto con il testo cifrato, può paragonare un mucchio di numeri cifrati, ma il loro numero non sarà sufficiente a dargli un vantaggio non trascurabile.

Successivamente è possibile utilizzare .gitattributes per fornire una decrittazione immediata per uscire da diff della password.

Inoltre puoi avere chiavi separate per diversi tipi di password ecc.


3

Di solito, separo la password come file di configurazione. e farli dist.

/yourapp
    main.py
    default.cfg.dist

E quando corro main.py, inserisco la vera password in default.cfgquella copiata.

ps. quando lavori con git o hg. puoi ignorare i *.cfgfile da creare .gitignoreo.hgignore


I file .dist sono ciò di cui parlavo: esempi di file di configurazione reali. Una buona pratica è che dovrebbe essere possibile eseguire il software solo rinominando rimuovendo l'estensione ".dist" (o meglio: copiando), cioè dovresti essere in grado di provare il software in pochi secondi, senza doverlo configurare durante tutto il giorno.
tiktak,

3

Fornire un modo per sovrascrivere la configurazione

Questo è il modo migliore per gestire una serie di impostazioni predefinite corrette per la configurazione che si sta effettuando il check-in senza che sia necessario completare la configurazione o contenere elementi come nomi host e credenziali. Esistono alcuni modi per sovrascrivere le configurazioni predefinite.

Le variabili d'ambiente (come altri hanno già detto) sono un modo per farlo.

Il modo migliore è cercare un file di configurazione esterno che sostituisca i valori di configurazione predefiniti. Ciò consente di gestire le configurazioni esterne tramite un sistema di gestione della configurazione come Chef, Puppet o Cfengine. La gestione della configurazione è la risposta standard per la gestione delle configurazioni separate dalla base di codice, quindi non è necessario eseguire una versione per aggiornare la configurazione su un singolo host o un gruppo di host.

Cordiali saluti: Crittografare i crediti non è sempre una buona pratica, soprattutto in un luogo con risorse limitate. È possibile che la crittografia dei crediti non ti consenta di ridurre ulteriormente i rischi e di aggiungere semplicemente un livello di complessità non necessario. Assicurati di fare l'analisi corretta prima di prendere una decisione.


2

Crittografa il file delle password, usando ad esempio GPG. Aggiungi le chiavi sul tuo computer locale e sul tuo server. Decifrare il file e inserirlo all'esterno delle cartelle del repository.

Uso un passwords.conf, che si trova nella mia cartella home. Ad ogni distribuzione questo file viene aggiornato.


Quindi il software deve decrittografare il file della password.
tiktak,

Bene, solo quando si distribuisce il sito la password viene decifrata e scritta in un file di password di testo semplice
Willian

2

No, le chiavi e le password private non rientrano nel controllo di revisione. Non vi è alcun motivo per gravare chiunque abbia accesso in lettura al proprio repository con la conoscenza delle credenziali dei servizi sensibili utilizzate nella produzione, quando molto probabilmente non tutti dovrebbero avere accesso a tali servizi.

A partire da Django 1.4, i tuoi progetti Django ora vengono forniti con un project.wsgimodulo che definisce l' applicationoggetto ed è un posto perfetto per iniziare a far valere l'uso di un project.localmodulo di impostazioni che contiene configurazioni specifiche del sito.

Questo modulo di impostazioni viene ignorato dal controllo di revisione, ma è necessaria la presenza durante l'esecuzione dell'istanza del progetto come applicazione WSGI, tipica per ambienti di produzione. Ecco come dovrebbe apparire:

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.local")

# This application object is used by the development server
# as well as any WSGI server configured to use this file.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Ora puoi avere un local.pymodulo il cui proprietario e gruppo possono essere configurati in modo che solo il personale autorizzato ei processi Django possano leggere il contenuto del file.


2

Se hai bisogno di VCS per i tuoi segreti, dovresti almeno tenerli in un secondo repository separato dal tuo vero codice. Quindi puoi consentire ai membri del tuo team di accedere al repository del codice sorgente e non vedranno le tue credenziali. Inoltre, ospita questo repository altrove (ad es. Sul tuo server con un filesystem crittografato, non su github) e per verificarlo nel sistema di produzione potresti usare qualcosa come git-submodule .


1

Un altro approccio potrebbe essere quello di evitare completamente il salvataggio dei segreti nei sistemi di controllo della versione e invece utilizzare uno strumento come vault di hashicorp , una memoria segreta con rotazione delle chiavi e controllo, con un'API e una crittografia incorporata.


1

Questo è ciò che faccio:

  • Conserva tutti i segreti come env vars in $ HOME / .secrets (go-r perms) che $ HOME / .bashrc genera (in questo modo se apri .bashrc davanti a qualcuno, non vedranno i segreti)
  • I file di configurazione sono archiviati in VCS come modelli, ad esempio config.properties archiviati come config.properties.tmpl
  • I file modello contengono un segnaposto per il segreto, ad esempio:

    my.password = ## MY_PASSWORD ##

  • Durante la distribuzione dell'applicazione, viene eseguito uno script che trasforma il file modello nel file di destinazione, sostituendo i segnaposto con i valori delle variabili di ambiente, come la modifica di ## MY_PASSWORD ## al valore di $ MY_PASSWORD.


0

È possibile utilizzare EncFS se il sistema lo fornisce. Pertanto, è possibile conservare i dati crittografati come sottocartella del repository, fornendo al contempo alla propria applicazione una vista decrittografata dei dati montati a parte. Poiché la crittografia è trasparente, non sono necessarie operazioni speciali su pull o push.

Dovrebbe tuttavia montare le cartelle EncFS, cosa che potrebbe essere eseguita dall'applicazione in base a una password memorizzata altrove al di fuori delle cartelle con versione (ad es. Variabili di ambiente).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.