Muchos proyectos de software usan secretos, por lo general, claves para API externas o credenciales para acceder a un recurso externo, como una base de datos. Su aplicación necesita estas claves en tiempo de ejecución, por lo que debe poder proporcionarlas cuando implemente su aplicación o como un paso en la preparación de su entorno de implementación. En este artículo, le mostraré cómo usar para que pueda mantener de manera segura los secretos de su aplicación en sus repositorios de código fuente, incluso si son públicos.
El problema con los secretos de las aplicaciones
La mayoría de los proyectos tienen algún tipo de claves o credenciales secretas. Por ejemplo, si su aplicación está alojada en , puede proporcionar una clave API para su aplicación Heroku mediante un comando como este:
$ heroku config: set API_KEY =my-sooper-sekrit-api-key
Al ejecutar este comando antes de (re)implementar su aplicación, le asigna una variable de entorno en tiempo de ejecución llamada API_KEY con el valor my-sooper-sekrit-api-key. Sin embargo, hacer un seguimiento de estos valores secretos fuera de Heroku (o donde sea que implemente su aplicación) sigue siendo un desafío.
Siempre trato de configurar mis proyectos para que pueda ejecutar un solo comando para implementarlos desde cero sin ningún paso manual separado. Para nuestro ejemplo, esto significa que necesito almacenar el valor my-sooper-sekrit-api-key en algún lugar para que mi código de implementación pueda usarlo (en este caso, para ejecutar heroku config:set... el comando anterior).
El código fuente de mi proyecto siempre se almacena en git y, por lo general, se aloja en github.com o bitbucket.com o en algún otro servicio de alojamiento de código fuente. Podría almacenar mi valor API_KEY en mi repositorio de código fuente, sin embargo, esto tiene algunas desventajas:
- No puedo compartir mi repositorio con nadie más a menos que me sienta cómodo con ellos accediendo a mis secretos. Esto significa que todos mis repositorios de aplicaciones con secretos deben ser privados.
- Presumiblemente, muchos miembros del personal en Github/bitbucket/donde sea que también tendrían acceso a mis secretos, con lo que podría no estar de acuerdo (dependiendo del secreto).
- Es fácil olvidarse de los secretos de un repositorio privado si luego elijo hacerlo público. Entonces podría revelar accidentalmente secretos importantes.
Podría almacenar mis secretos en algún lugar separado del código fuente de mi aplicación, pero esto tiene sus propios problemas:
- Necesito una manera de obtener mis secretos de donde sea que estén almacenados, en el momento de la implementación o antes, y darle acceso a mi código de implementación.
- Es posible que mis secretos no se almacenen tan sólidamente como mi código fuente. Por ejemplo, podría guardar secretos en un archivo .env en mi computadora portátil y asegurarme de nunca verificarlo en el repositorio de git. Sin embargo, si pierdo ese archivo (por ejemplo, si mi computadora portátil se daña o me la roban), también pierdo ese secreto.
git-cripta
Git-crypt tiene como objetivo resolver este problema cifrando sus secretos cada vez que los envía a su repositorio de git y descifrándolos cada vez que los extrae. Esto sucede de manera transparente, desde su punto de vista. Por lo tanto, los secretos están en texto sin cifrar en lo que respecta a usted y su código de implementación, pero nadie más puede leerlos, incluso si su código fuente está en un repositorio público de Github. Veamos un ejemplo. 1. Instale git-crypt. Hay instrucciones para Linux, Mac y Windows en la Si, como yo, está usando una Mac con instalado, puede ejecutar:
2. Cree un nuevo repositorio de git.
$ mkdir myproject $ cd myproject $ git init $ echo "This is some text" > file.txt $ git add file.txt $ git commit -m "Initial commit"
Ahora tenemos un repositorio git que contiene un solo archivo de texto.
3. Configure el repositorio para usar git-crypt.
Deberías ver la salida:
Antes de hacer cualquier otra cosa, ejecute el siguiente comando:
$ git-crypt export -key ../git-crypt-key
Este comando crea una copia de la clave simétrica de git-crypt que se generó para este repositorio. Lo estamos colocando en el directorio sobre este repositorio para que podamos reutilizar la misma clave en varios repositorios de git.
De forma predeterminada, git-crypt almacena la clave generada en el archivo .git/git-crypt/keys/default para que pueda lograr el mismo resultado ejecutando cp .git/git-crypt/keys/default ../git-crypt- llave
Este archivo git-crypt-key es importante. Es la clave que puede desbloquear todos los archivos cifrados en nuestro repositorio. Más adelante veremos cómo utilizar esta clave.
4. Dile a git-crypt qué archivos cifrar.
Imagine que nuestra aplicación necesita una clave API y queremos almacenarla en un archivo llamado api.key.
Antes de agregar ese archivo a nuestro repositorio, le diremos a git-crypt que queremos que el archivo api.key se cifre cada vez que lo confirmemos.
Hacemos eso usando el archivo .gitattributes. Este es un archivo que podemos usar para agregar metadatos adicionales a nuestro repositorio de git. No es específico de git-crypt, por lo que es posible que ya tenga un archivo .gitattributes en su repositorio. Si es así, solo agregue las líneas relevantes, no reemplace todo el archivo. En nuestro caso, no tenemos un archivo .gitattributes, por lo que debemos crear uno. El archivo .gitattributes contiene líneas de la forma:
[file pattern] attr1 =value1 attr2 =value2
Para git-crypt, el patrón de archivo debe coincidir con todos los archivos que queremos que git-crypt cifre, y los atributos son siempre los mismos: filter y diff, los cuales establecemos en git-crypt. Entonces, nuestro archivo .gitattributes debería contener esto:
api.key filter =git-crypt diff =git-crypt
Cree ese archivo, agréguelo y confírmelo a su repositorio de git:
$ echo "api.key filter=git-crypt diff=git-crypt" > .gitattributes $ git add .gitattributes $ git commit -m "Tell git-crypt to encrypt api.key"
Usé el nombre de archivo literal api.key en mi archivo .gitattributes, pero puede ser cualquier patrón de archivo que incluya los archivos que desea cifrar, por lo que podría haber usado *.key, por ejemplo. Alternativamente, puede simplemente agregar una línea para cada archivo que desee cifrar. Puede ser fácil cometer un error en su archivo .gitattributes si está tratando de proteger varios archivos con una sola entrada de patrón. Por lo tanto, recomiendo encarecidamente leer esta sección del , que destaca algunos de los problemas comunes.
5. Agregue un secreto.
Ahora que le hemos dicho a git-crypt que queremos cifrar el archivo api.key, agreguemos eso a nuestro repositorio.
Siempre es una buena idea probar su configuración agregando primero un valor ficticio y confirmando que está encriptado con éxito, antes de confirmar su secreto real.
$ echo "dummy value" > api.key
Todavía no hemos agregado api.key a git, pero podemos verificar qué hará git-crypt ejecutando:
Debería ver el siguiente resultado:
encrypted : api.key not encrypted : .gitattributes not encrypted : file.txt
Entonces, aunque el archivo api.key aún no se ha enviado a nuestro repositorio de git, esto le indica que git-crypt lo cifrará por usted. Agreguemos y confirmemos el archivo:
$ git add api.key $ git commit -m "Added the API key file"
6. Confirme que nuestro secreto está encriptado.
Le hemos dicho a git-crypt que encripte y hemos agregado api.key a nuestro repositorio. Sin embargo, si nos fijamos, nada parece diferente:
$ cat api. key dummy value
La razón de esto es que git-crypt cifra y descifra de forma transparente los archivos a medida que los empuja y extrae a su repositorio. Por lo tanto, el archivo api.key parece un archivo normal de texto claro.
$ file api .key api .key : ASCII text
Una forma de confirmar que sus archivos realmente se están cifrando es enviar su repositorio a GitHub. Cuando vea el archivo api.key mediante la interfaz web de GitHub, verá que es un archivo binario encriptado en lugar de texto. Una forma más fácil de ver cómo se vería el repositorio para alguien sin la clave de descifrado es ejecutar:
Ahora, si miramos nuestro archivo api.key, las cosas son diferentes:
$ file api .key api .key : data $ cat api .key GITCRYPTROܮ 7 y\R*^
Verá una salida de basura diferente a la que obtengo, pero está claro que el archivo está encriptado. Esto es lo que se almacenaría en GitHub. Para volver a tener un archivo api.key de texto claro, ejecute:
$ git- crypt unlock ../git- crypt -key
El archivo ../git-crypt-key es el que guardamos anteriormente usando git-crypt export-key...
Control
Hagamos un repaso rápido de dónde estamos ahora.
- Inicialice git-crypt en un repositorio de git usando git-crypt init
- Use patrones de archivo en .gitattributes para decirle a git-crypt qué archivos cifrar
- git-crypt lock cifrará todos los archivos especificados en nuestro repositorio
- git-crypt unlock [ruta al archivo de claves] descifrará los archivos cifrados
El archivo git-crypt-key es muy importante. Sin él, no podrá descifrar ninguno de los archivos cifrados en su repositorio. Cualquiera que tenga una copia de ese archivo tiene acceso a todos los secretos encriptados en su repositorio. Por lo tanto, debe mantener ese archivo seguro y protegido.
Reutilización de su archivo de clave git-crypt
Usamos git-crypt init y git-crypt export-key para crear nuestro archivo git-crypt-key. Pero, si tenemos que tener un archivo de claves separado para cada uno de nuestros repositorios, entonces no hemos mejorado mucho nuestra gestión de secretos. Afortunadamente, es muy fácil usar el mismo archivo de claves de git-crypt para varios repositorios de git. Para usar un archivo de clave existente, simplemente use git-crypt unlock en lugar de git-crypt init cuando configure su repositorio git para usar git-crypt, así:
$ mkdir my-other-project # At the same directory level as `myproject` $ cd my-other-project $ git init $ echo "Something" > file.txt $ git add file.txt $ git commit -m "initial commit" $ git-crypt unlock ../git-crypt-key
Si ejecuta el comando de desbloqueo de git-crypt antes de agregar cualquier archivo a su repositorio de git, verá un mensaje como este:
fatal: You are on a branch yet to be born Error: 'git checkout' failed git-crypt has been set up but existing encrypted files have not been decrypted
Esto todavía funciona bien, pero es un poco confuso, así que me aseguré de agregar y confirmar al menos un archivo antes de ejecutar git-crypt unlock...
Reutilizar su archivo de clave de git-crypt es conveniente, pero significa que si alguien más obtiene una copia de su archivo de clave, todos sus secretos cifrados quedan expuestos.
Este es el mismo tipo de compensación de seguridad que usar un administrador de contraseñas como o . En lugar de administrar varios secretos (contraseñas), cada uno con su propio riesgo de exposición, los guarda todos en un almacén seguro y usa una única contraseña maestra para desbloquearlos.
La idea aquí es que es más fácil manejar un secreto importante que muchos secretos menores.
Cuándo NO usar git-crypt
Git-crypt es una excelente manera de mantener los secretos que sus aplicaciones necesitan en el repositorio de git, junto con el código fuente de la aplicación. Sin embargo, como cualquier otra medida de seguridad, no siempre va a ser adecuada o aconsejable.
Aquí hay algunas cosas a considerar para decidir si es la solución adecuada para su proyecto en particular:
- git-crypt está diseñado para situaciones en las que la mayoría de los archivos en su repositorio de git pueden permanecer en texto no cifrado y solo necesita cifrar algunos archivos que contienen secretos. Si necesita encriptar la mayoría o todos los archivos en su repositorio, entonces otras soluciones pueden ser más adecuadas.
- No hay una manera fácil de revocar el acceso a los secretos en un repositorio una vez que alguien tiene el archivo de clave, y no hay una manera fácil de rotar (es decir, reemplazar) un archivo de clave (aunque cambiar el archivo de clave de git-crypt no ayuda mucho a menos que también rote todos los secretos reales en el repositorio).
- git-crypt solo encripta el contenido de los archivos. Por lo tanto, no es adecuado si los metadatos de su repositorio también son confidenciales (es decir, nombres de archivo, fechas de modificación, mensajes de confirmación, etc.).
- Es posible que algunas aplicaciones GUI de git no funcionen de manera confiable con git-crypt. (Aunque se ha el caso específico de Atlassian SourceTree, mencionado en el LÉAME).
Hay más información en esta sección del .
Una mejor manera de usar git-crypt
En lugar de administrar su archivo de clave git-crypt directamente, hay una mejor manera de administrar repositorios encriptados al integrar git-crypt con , de modo que pueda usar su clave privada gpg para descifrar el repositorio git. Esto también le permite agregar múltiples colaboradores a un repositorio de git sin transmitir ningún secreto entre las partes. Sin embargo, esto requiere una configuración más complicada, así que lo dejaremos para otro artículo.