python django git version-control

python - ¿Cómo puedo guardar mis claves secretas y mi contraseña de forma segura en mi sistema de control de versiones?



django git (17)

En general, hago la pregunta, pero en mi caso específico me gustaría almacenar claves secretas y contraseñas para un sitio de Django / Python usando git y github.

No, simplemente no, incluso si es su repositorio privado y nunca tiene la intención de compartirlo, no lo haga.

Debes crear un local_settings.py ponlo en VCS ignore y en tu settings.py haz algo así como

from local_settings import DATABASES, SECRET_KEY DATABASES = DATABASES SECRET_KEY = SECRET_KEY

Si la configuración de tus secretos es tan versátil, estoy ansioso por decir que estás haciendo algo mal.

Guardo ajustes importantes como los nombres de host y los puertos de los servidores de desarrollo y producción en mi sistema de control de versiones. Pero sé que es una mala práctica guardar secretos (como claves privadas y contraseñas de bases de datos) en un repositorio de VCS.

Pero las contraseñas, como cualquier otra configuración, parecen que deberían tener una versión. Entonces, ¿cuál es la forma correcta de mantener la versión de contraseñas controlada?

Imagino que implicaría mantener los secretos en su propio archivo de "configuración de secretos" y tener ese archivo cifrado y la versión controlada. Pero, ¿qué tecnologías? ¿Y cómo hacer esto correctamente? ¿Hay una mejor manera de hacerlo por completo?

En general, hago la pregunta, pero en mi caso específico me gustaría almacenar claves secretas y contraseñas para un sitio de Django / Python usando git y github .

Además, una solución ideal sería algo mágico cuando presiono / jala con git; por ejemplo, si el archivo de contraseñas encriptadas cambia, se ejecuta una secuencia de comandos que solicita una contraseña y la descifra en su lugar.

EDITAR: Para mayor claridad, estoy preguntando dónde almacenar los secretos de producción .

Cifre el archivo de contraseñas, usando por ejemplo GPG. Agregue las llaves en su máquina local y en su servidor. Descifra el archivo y colócalo fuera de tus carpetas de repositorio.

Utilizo un password.conf, ubicado en mi carpeta de inicio. En cada implementación, este archivo se actualiza.


Desde que hice esta pregunta, me he decidido por una solución que uso al desarrollar aplicaciones pequeñas con un pequeño equipo de personas.

git-crypt

git-crypt usa GPG para encriptar archivos de forma transparente cuando sus nombres coinciden con ciertos patrones. Para intant, si agrega a su archivo .gitattributes ...

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

... entonces un archivo como config.secret.json siempre será enviado a los repos remotos con encriptación, pero permanece sin encriptar en su sistema de archivos local.

Si quiero agregar una nueva clave GPG (una persona) a su repositorio, que puede descifrar los archivos protegidos, ejecute git-crypt add-gpg-user <gpg_user_key> . Esto crea un nuevo compromiso. El nuevo usuario podrá descifrar confirmaciones posteriores.


Está en lo cierto al querer encriptar su archivo de configuración confidencial mientras mantiene el archivo en control de versión. Como mencionas, la mejor solución sería aquella en la que Git encriptara transparentemente ciertos archivos sensibles cuando los presionas para que a nivel local (es decir, en cualquier máquina que tenga tu certificado) puedas usar el archivo de configuración, pero Git o Dropbox o quien sea el almacenamiento de sus archivos en VC no tiene la capacidad de leer la información en texto sin formato.

Tutorial sobre Cifrado / Descifrado Transparente durante Push / Pull

Esta esencia https://gist.github.com/873637 muestra un tutorial sobre cómo usar el controlador de filtro de manchas / limpieza de Git con openssl para encriptar transparentemente archivos empujados. Solo necesitas hacer una configuración inicial.

Resumen de cómo funciona

Básicamente .gitencrypt una carpeta .gitencrypt contenga 3 scripts bash,

clean_filter_openssl smudge_filter_openssl diff_filter_openssl

que son utilizados por Git para descifrado, cifrado y compatibilidad con Git diff. Una frase de contraseña maestra y sal (¡fijo!) Se define dentro de estos scripts y usted DEBE asegurarse de que .gitencrypt en realidad nunca se presione. Ejemplo de script clean_filter_openssl :

#!/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

Similar para smudge_filter_open_ssl y diff_filter_oepnssl . Ver Gist.

Su repositorio con información confidencial debe tener un archivo .gitattribute (sin encriptar e incluido en el repositorio) que haga referencia al directorio .gitencrypt (que contiene todo lo que Git necesita para encriptar / desencriptar el proyecto de forma transparente) y que esté presente en su máquina local.

.gitattribute contenido:

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

Finalmente, también deberá agregar el siguiente contenido a su archivo .git/config

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

Ahora, cuando inserta el repositorio que contiene su información confidencial en un repositorio remoto, los archivos se cifrarán de forma transparente. Cuando extrae de un equipo local que tiene el directorio .gitencrypt (que contiene su frase de contraseña), los archivos se descifrarán de forma transparente.

Notas

Debo señalar que este tutorial no describe una manera de encriptar solo tu archivo de configuración confidencial. Esto encriptará de forma transparente todo el repositorio que se envía al host remoto de VC y descifrará todo el repositorio, por lo que se descifrará completamente de manera local. Para lograr el comportamiento que desea, puede colocar archivos confidenciales para uno o más proyectos en un sensitive_settings_repo. Podría investigar cómo funciona esta técnica de cifrado transparente con los submódulos de Git http://git-scm.com/book/en/Git-Tools-Submodules si realmente necesita que los archivos confidenciales estén en el mismo repositorio.

El uso de una frase de contraseña fija teóricamente podría generar vulnerabilidades de fuerza bruta si los atacantes tuvieran acceso a muchos repos / archivos encriptados. OMI, la probabilidad de esto es muy baja. Como menciona una nota en la parte inferior de este tutorial, si no se utiliza una frase de contraseña fija, las versiones locales de un repositorio en diferentes máquinas siempre mostrarán que se han producido cambios con ''estado de git''.


Esto es lo que hago:

  • Guarde todos los secretos como archivos en $ HOME / .secrets (go-r perms) que fuentes $ HOME / .bashrc (de esta manera si abre .bashrc delante de alguien, no verán los secretos)
  • Los archivos de configuración se almacenan en VCS como plantillas, como config.properties almacenado como config.properties.tmpl
  • Los archivos de plantilla contienen un marcador de posición para el secreto, como:

    my.password = ## MY_PASSWORD ##

  • En la implementación de aplicaciones, se ejecuta un script que transforma el archivo de plantilla en el archivo de destino, reemplazando los marcadores de posición con valores de variables de entorno, como el cambio de ## MY_PASSWORD ## al valor de $ MY_PASSWORD.


Heroku empuja el uso de variables de entorno para configuraciones y claves secretas:

El enfoque tradicional para manejar tales configuraciones es colocarlas bajo la fuente, en un archivo de propiedades de algún tipo. Este es un proceso propenso a errores, y es especialmente complicado para aplicaciones de código abierto que a menudo tienen que mantener ramas separadas (y privadas) con configuraciones específicas de la aplicación.

Una mejor solución es usar variables de entorno y mantener las claves fuera del código. En un host tradicional o que trabaje localmente, puede establecer variables de entorno en su bashrc. En Heroku, usas config vars.

Con los archivos Foreman y .env , Heroku proporciona una herramienta envidiable para exportar, importar y sincronizar variables de entorno.

Personalmente, creo que es incorrecto guardar claves secretas junto con el código. Es fundamentalmente inconsistente con el control de fuente, porque las claves son para servicios extrínsecos al código . La única ventaja sería que un desarrollador puede clonar HEAD y ejecutar la aplicación sin ninguna configuración. Sin embargo, supongamos que un desarrollador verifica una revisión histórica del código. Su copia incluirá la contraseña de la base de datos del año pasado, por lo que la aplicación fallará contra la base de datos de hoy.

Con el método Heroku anterior, un desarrollador puede consultar la aplicación del año pasado, configurarla con las claves de hoy y ejecutarla con éxito en la base de datos de hoy.


La forma más limpia en mi opinión es usar variables de entorno. No tendrá que lidiar con archivos .dist , por ejemplo, y el estado del proyecto en el entorno de producción sería el mismo que el de su máquina local.

Recomiendo leer el capítulo de configuración de la aplicación Twelve-Factor , los demás también si está interesado.


No, las claves privadas y las contraseñas no están bajo control de revisión. No hay ninguna razón para cargar a todos los que tengan acceso de lectura a su repositorio con el conocimiento de las credenciales de servicio sensibles utilizadas en la producción, cuando lo más probable es que no todas ellas tengan acceso a esos servicios.

Comenzando con Django 1.4, sus proyectos Django ahora incluyen un módulo project.wsgi que define el objeto de la application y es un lugar perfecto para comenzar a aplicar el módulo project.local settings que contiene configuraciones específicas del sitio.

Este módulo de configuración se ignora desde el control de revisión, pero se requiere su presencia cuando se ejecuta la instancia de su proyecto como una aplicación WSGI, típica para entornos de producción. Así es como debería verse:

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()

Ahora puede tener un módulo local.py cuyo propietario y grupo se puedan configurar para que solo el personal autorizado y los procesos de Django puedan leer los contenidos del archivo.


Otro enfoque podría ser evitar por completo el almacenamiento de secretos en los sistemas de control de versiones y, en su lugar, usar una herramienta como bóveda de hashicorp , un almacenamiento secreto con transferencia de claves y auditoría, con API y cifrado incorporado.


Por lo general, separa la contraseña como un archivo de configuración. y hazlos dist.

/yourapp main.py default.cfg.dist

Y cuando ejecuto main.py , pongo la contraseña real en default.cfg que se copió.

PD. cuando trabajas con git o hg. puede ignorar archivos *.cfg para hacer .gitignore o .hgignore


Puede usar EncFS si su sistema lo proporciona. De este modo, podría mantener sus datos encriptados como una subcarpeta de su repositorio, mientras le proporciona a su aplicación una vista descifrada de los datos montados a un lado. Como el cifrado es transparente, no se necesitan operaciones especiales para tirar o empujar.

Sin embargo, tendría que montar las carpetas EncFS, lo que podría hacer su aplicación en función de una contraseña almacenada en otro lugar fuera de las carpetas versionadas (por ejemplo, variables de entorno).


Si necesita VCS para sus secretos, al menos debe mantenerlos en un segundo repositorio separado del código actual. Por lo tanto, puede dar acceso a los miembros de su equipo al repositorio de código fuente y no verán sus credenciales. Además, aloje este repositorio en otro lugar (por ejemplo, en su propio servidor con un sistema de archivos encriptado, no en github) y para consultarlo en el sistema de producción podría usar algo como http://git-scm.com/book/en/Git-Tools-Submodules .


Sugiero usar archivos de configuración para eso y no versionarlos.

Sin embargo, puedes versionar ejemplos de los archivos.

No veo ningún problema para compartir configuraciones de desarrollo. Por definición, no debe contener datos valiosos.


Una opción sería colocar las credenciales enlazadas al proyecto en un contenedor cifrado (TrueCrypt o Keepass) y presionarlo.

Actualizar como respuesta de mi comentario a continuación:

Pregunta interesante por cierto. Acabo de encontrar esto: github.com/shadowhand/git-encrypt que parece muy prometedor para el cifrado automático


BlackBox fue lanzado recientemente por StackExchange y, aunque todavía no lo utilizo, parece abordar exactamente los problemas y respaldar las funciones solicitadas en esta pregunta.

De la descripción en BlackBox :

Almacene con seguridad los secretos en un repositorio de VCS (es decir, Git o Mercurial). Estos comandos facilitan que GPG encripte archivos específicos en un repositorio para que estén "encriptados en reposo" en su repositorio. Sin embargo, los scripts hacen que sea fácil descifrarlos cuando necesite verlos o editarlos, y descifrarlos para usarlos en producción.


EDITAR: supongo que desea realizar un seguimiento de las versiones anteriores de sus contraseñas, por ejemplo, para un script que evite la reutilización de contraseñas, etc.

Creo que GnuPG es la mejor manera de hacerlo: ya se usa en un proyecto relacionado con git (git-annex) para cifrar los contenidos del repositorio almacenados en servicios en la nube. GnuPG (gnu pgp) proporciona una encriptación basada en claves muy sólida.

  1. Mantiene una tecla en su máquina local.
  2. Agrega ''mypassword'' a archivos ignorados.
  3. En el enganche previo a la confirmación, encripte el archivo mypassword en el archivo mypassword.gpg seguido por git y agréguelo al commit.
  4. En el enlace posterior a la fusión, acaba de descifrar mypassword.gpg en mypassword.

Ahora bien, si su archivo ''mypassword'' no cambió, el cifrado resultará con el mismo texto cifrado y no se agregará al índice (sin redundancia). La menor modificación de mypassword da como resultado un texto cifrado radicalmente diferente y mypassword.gpg en el área de ensayo difiere mucho del repositorio, por lo que se agregará al compromiso. Incluso si el atacante obtiene su clave de gpg, aún necesita aplicar la contraseña bruta. Si el atacante obtiene acceso a un repositorio remoto con texto cifrado, puede comparar un montón de textos cifrados, pero su número no será suficiente para darle una ventaja no despreciable.

Más adelante, puede usar .gitattributes para proporcionar un descifrado sobre la marcha para dejar de recibir su contraseña.

También puede tener claves separadas para diferentes tipos de contraseñas, etc.


Proporcione una forma de anular la configuración

Esta es la mejor manera de administrar un conjunto de valores predeterminados correctos para la configuración que se registra sin que se requiera que la configuración esté completa, o que contenga cosas como nombres de host y credenciales. Hay algunas maneras de anular las configuraciones predeterminadas.

Las variables de entorno (como otros ya lo han mencionado) son una forma de hacerlo.

La mejor manera es buscar un archivo de configuración externo que anule los valores de configuración predeterminados. Esto le permite administrar las configuraciones externas a través de un sistema de administración de configuración como Chef, Puppet o Cfengine. La administración de la configuración es la respuesta estándar para la administración de las configuraciones separadas de la base de código, por lo que no es necesario realizar una versión para actualizar la configuración en un único host o grupo de hosts.

FYI: Cifrar créditos no siempre es una mejor práctica, especialmente en un lugar con recursos limitados. Puede ser que el cifrado de los creditos no genere una mitigación de riesgos adicional y simplemente agregue una capa innecesaria de complejidad. Asegúrese de hacer el análisis adecuado antes de tomar una decisión.