Commits firmados: el por qué y el cómo

En nuestro último post de nuestra serie "Píldoras técnicas sobre Platform Engineering: más allá de lo que encuentras en la documentación", hablamos de cómo aprovechar las Step Functions de AWS en la optimización de transformaciones de datos a gran escala, y hoy cambiamos de rumbo radicalmente para explicar la importancia de firmar los commits.

Tener tus commits firmados añade una capa adicional de seguridad al proceso de desarrollo. Al hacerlo, tanto tú como el resto de personas podréis verificar la integridad, autenticidad y origen de los cambios de código.

¿Por qué firmar los commits?

Cuando se desarrolla como parte de un equipo, cualquiera con los permisos suficientes puede subir código a tu repositorio. Mientras que estar autenticado es necesario para hacer el push, por sí mismo no garantiza que el código subido fue generado por la persona que lo sube. Cualquiera podría cambiar sus user.name y user.email para cuadrar con los tuyos y crear un commit, efectivamente suplantando tu identidad.

Esto puede prevenirse si tienes como hábito firmar tus commits, de forma que cualquiera que examine el git log (al menos cuando lo haces con el flag --show-signature) puede, de un vistazo, verificar si los commits que se te atribuyen fueron firmados con tu clave.

Por desgracia esto no prevendrá a la gente usar tu nombre de usuario o email en commits maliciosos, pero si todos tus commits están firmados al menos destacarán e invitarán a pensar: “quizás este commit no es genuino”.

Idealmente, si todo el mundo firmase cada commit cualquier commit que esté firmado con una clave desconocida o que ni siquiera esté firmado sería sospechoso.

¿Cómo funciona?

Si ya conoces cómo funciona PKI, puedes saltarte esta sección ya que no necesitas saber cómo funcionan por debajo los commits firmados.

Las claves criptográficas juegan un papel fundamental en la firma de commits. Puedes encontrar la explicación completa en Wikipedia, pero aquí tienes un resumen.

Siempre hay dos partes en juego, una pública y una privada:

  • Clave pública: aquella que puedes compartir de forma segura y se usa para verificar. Es como una cerradura a la que cualquiera puede acceder. Cuando firmas un commit, utilizas tu clave privada para crear una firma única. Otros entonces pueden hacer uso de tu clave pública para verificar la firma y confirmar que fuiste tú el que creó el commit.

  • Clave privada: esta clave se mantiene secreta y nunca debe compartirse. Es la llave para la cerradura que mencionamos antes: utilizarás la clave privada para crear la firma de los commits. Dado que sólo tú la conoces, asegura que sólo tú puedes producir una firma válida para tus commits.

Para obtener estas claves probablemente usarás GPG (GNU Privacy Guard), ampliamente reconocido por su fiabilidad y seguridad. Con ella puedes crear el par de claves previamente mencionadas y realizar diversas tareas de gestión.

Obteniendo tus claves

Antes de nada, necesitarás GPG disponible. Si estás en Linux o MacOS, o lo tienes ya instalado por defecto o puedes instalarlo utilizando un gestor de paquetes como pacman, apt y yum (Linux) o brew (MacOS). En el caso de Windows, deberás descargarlo desde su sitio web.

Una vez lo tengas instalado podrás proceder:

  1. Usa gpg para crear tu par de claves
    gpg --full-generate-key
  2. Elige el tipo de clave. RSA (sign only) será suficiente para este caso
  3. Elige el tamaño de la clave. Recomiendo 4096 y, sobre todo, nunca bajar de 2048

  4. Define una fecha de expiración. Mi recomendación es dejarlo por defecto

  5. Rellena tus datos

    • Opcionalmente protege la clave con una clave de seguridad. Altamente recomendado

Para poder utilizarla tendrás que informar al proveedor de git (y opcionalmente a nuestro equipo) tu clave pública. Así es como cualquiera podrá corroborar la firma.

Podrás hacerlo con dos simples comandos.

El primero te dará la información que necesitamos para exportar la clave pública más adelante:

gpg --list-secret-keys --keyid-format long

 

La salida debería verse similar a esta:

 
/home/nahuel/.gnupg/pubring.kbx
------------------------
sec   rsa4096/C0C8AF0F2B994FA5 2015-10-21 [SC]
      2AA35F533E6A86C60F303250C0C8AF0F2B994FA5
uid                 [ultimate] Nahuel (My key) <email@example.com>
</email@example.com>

 

De aquí te interesa el ID de la key, en este ejemplo sería C0C8AF0F2B994FA5. Cópiala ya que la necesitaremos para el paso final.

El último comando que necesitarás ejecutar tendrá como salida la llave pública:

gpg --armor --export C0C8AF0F2B994FA5

 

Se verá similar a esto:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBGXWjBwBEADCFaYuamcSIfyigZspureZFVuJTlTyGFVFaxuSx2me2rZBoJDp
MUCHAS LÍNEAS SIMILARES
PN8qmuUdyr8/k87CwLrtOwft2Rt3jV4=
=UQNM
-----END PGP PUBLIC KEY BLOCK-----

 

Como paso final, copiarás todas esas líneas y las pegarás en el proveedor de Git. Puedes referirte a GitHub o GitLab para las instrucciones específicas.

Firmando commits

Has alcanzado el paso final! Ahora configurarás Git con la clave que necesita usar para firmar los commits.

Necesitarás de nuevo el ID obtenido en el paso anterior con el comando de gpg, y ejecutarás:

git config --global user.signingkey C0C8AF0F2B994FA5

 

Esto instruirá a Git a usar esa clave para firmar los commits de ahora en adelante. Aún tienes que solicitar al commit que sea firmado, y para eso tienes dos opciones:

  • Dejar que Git firme cada commit (recomendado)
git config --global commit.gpgsign true

 

ⓘ Nota: Por defecto, Git debería firmar tags automáticamente, pero lo puedes activar explícitamente ejecutando:

git config --global tag.gpgSign true

 

  • Firmar explicitamente cada commit
git commit -S -m "Not an awful commit message"

 

Esta decisión depende completamente de ti. Al final, el resultado de ambos será la firma de los commits con la clave definida.

Conclusión

Por desgracia, sólo una pequeña fracción de la gente que crea commits los firma. No es un requisito en absoluto, ni dañará tu código de ninguna manera.

Ten en cuenta que tener a alguien haciéndose pasar por ti y con acceso a tu repositorio para hacer commit en tu nombre es una situación que debería ser bastante inusual; aun así es mejor prevenir que curar. Especialmente cuando los commits están relacionados con nuestro trabajo del día a día.

¡Te animo a acostumbrarte a este proceso y empezar a firmar los commits!

Recursos adicionales

  • GitLab provee documentación acerca de temas relacionados que amplían la firma de commits, como por ejemplo firmas condicionales, revocar claves de gpg y resolución de problemas.
  • También es posible firmar commits con una clave ssh. De nuevo… ¡GitLab!
codurance_migracion_al_cloud