Firmando digitalmente el archivo Release …

debian-logo… en mi nuevo y flamante repositorio Debian.

En la entrada en la que describía la creación del repositorio dejé pendiente explicar cómo asegurar el contenido del mismo empleando una firma digital. Voy a hablar de ello ahora.

Para firmar digitalmente el archivo Release tendremos que hacer lo siguiente:

  1. Preparar la infraestructura de GnuPG.
  2. Instalar un script para firmar.
  3. Indicar a mini-dinstall que utilice dicho script.
  4. Situar la clave pública para los clientes del repositorio.

Infraestructura de GnuPG

El programa GnuPG emplea la variable de entorno GNUPGHOME para localizar el directorio donde se encuentran las claves. Es importante tenerlo en cuenta para el programa de firma y para asegurar en lo posible la clave privada. En mi caso he optado por situarlo bajo el directorio de trabajo de mini-dinstall con un nombre raro: /var/lib/debian/.gnupgdir.

Una vez decidido dónde vamos a situar la infraestructura de gnupg tenemos que crear nuestro par de claves de la forma habitual:

# su -l debpkg
$ GNUPGHOME=/var/lib/debian/.secret gpg --gen-key

Ahora guardamos la contraseña de la clave privada en el archivo /var/lib/debian/.gnupgdir/passphrase y nos aseguramos de que sólo el usuario debpkg tenga acceso a él. Usaremos este archivo en el script de firma.

Podemos adelantar trabajo y obtener una copia de la clave pública para ponerla a disposición de los clientes del repositorio con:

# su debpkg --shell /bin/sh
$ cd /var/lib/debian
$ GNUPGHOME=/var/lib/debian/.secret
$ gpg --armor --export victor@taquiones.net > archive_key.asc

Con los permisos restringidos tanto en el directorio como en el archivo esta parte estaría completa.

Instalar un script de firma

El paquete mini-dinstall ofrece un script creado por Colin Walters que podemos adaptar a nuestra instalación concreta. El que yo estoy empleando utiliza un archivo de configuración opcional por si necesito cambiar algún valor en el futuro (es casi una manía personal).

#!/bin/bash
# -*- coding: utf-8 -*-
# 
#   Versión modificada del script de firma para mini-dinstall de Colin Walters
#
# Copyright © 2002 Colin Walters <walters@debian.org>

set -e

#   Variables de usuario
GNUPG_DIR=/var/lib/debian/.secret
KEYID=victor@taquiones.net
PASSPHRASE_FILE=$GNUPG_DIR/passphrase

#   Leemos configuración si existe 
CONFIG=/etc/taquiones/debian.conf
if [ -r $CONFIG ]; then 
    . $CONFIG
fi 

# Preparamos entorno de firma 
GNUPGHOME=$GNUPG_DIR
export GNUPGHOME
PASSPHRASE=$(cat $PASSPHRASE_FILE)

# Esto debería fallar (set -e) si no somos el propietario
chown "$USER" "$GNUPGHOME"
chmod 0700 "$GNUPGHOME"

# Initialize GPG
gpg --help 1>/dev/null 2>&1 || true

rm -f Release.gpg.tmp InRelease.tmp
echo "$PASSPHRASE" | gpg --no-tty --batch --passphrase-fd=0 --default-key "$KEYID" --detach-sign -o Release.gpg.tmp "$1"
mv Release.gpg.tmp Release.gpg
echo "$PASSPHRASE" | gpg --no-tty --batch --passphrase-fd=0 --default-key "$KEYID" --clearsign -o InRelease.tmp "$1"
mv InRelease.tmp InRelease

¿ Y dónde situar el script ? A mi se me ha ocurrido que el directorio de trabajo de mini-dinstall sería un buen lugar (/var/lib/debian/mini-dinstall) y en realidad no veo inconveniente para ello, especialmente por lo que cuento en la siguiente sección.

Configurar mini-dinstall para la firma

La variable release_signscript de la configuración de mini-dinstall contiene la ruta del script de firma y funciona de la siguiente manera:

  1. El programa se ejecuta en el mismo directorio que el archivo Release.
  2. Se le pasa como primer parámetro la ruta de una copia temporal de dicho archivo.
  3. Se espera de él que realice la firma y cree un archivo Release.gpg en el directorio en el que ha sido llamado.

Un detalle que me trae un poco de cabeza es que el programa mini-dinstall, especialmente cuando funciona como demonio, lo hace bajo el usuario root. No he visto forma de cambiarlo ni estoy seguro de si sería conveniente hacerlo sin dispararse en el pié. El caso es que cuando se ejecuta el programa de firma el usuario que lo lanza es el propio administrador y, por alguna razón, no es exactamente lo que queremos.

La solución más inmediata sería usar el programa su y definirlo en la configuración como:

release_signscript = su debpkg /var/lib/debian/mini-dinstall/sign-release.sh

Pero como la documentación sólo menciona un programa y no una línea shell, he mirado los fuentes y he comprobado que mini-dinstall emplea la función execlp y no algún tipo de system o similar. Además, como le pasa el archivo a firmar como primer parámetro no cabe (y no es aconsejable) incluirle más.

En su lugar es mejor emplear un programa envoltorio (wrapper) que realice toda la tarea, nos quitamos de líos y no nos cerramos la puerta a posteriores cambios en el mecanismo de firma.

Así que con el siguiente programa que muestro abajo y que vuelvo a situar en el directorio de trabajo de mini-dinstall con el nombre sign-wrapper.sh la configuración de firma quedaría como:

release_signscript = /var/lib/debian/mini-dinstall/sign-wrapper.sh

Y el programa envoltorio de la siguiente forma:

#   Variables
VERSION=0.2
CONFIG=/etc/taquiones/debian.conf
ROOT_DIR=/var/lib/debian
USER=debpkg

if [ -r $CONFIG ]; then
    . $CONFIG
fi

REAL_SIGN=$ROOT_DIR/mini-dinstall/sign-release.sh

#   Lanzamos el programa de firma con el usuario adecuado
su $USER --shell /bin/bash $REAL_SIGN $*

He empleado el parámetro –shell por pura precaución. El usuario debpkg se declara como cuenta del sistema y suele ocurrir que me equivoque al crearlo y no tenga un shell asignado.

Publicar la clave pública (sic)

Dado que es preceptivo emplear cifrado para utilizar correctamente el repositorio tenemos que hacer que la clave pública sea de fácil acceso. Creo que el mejor lugar, aquél que me gustaría encontrar de primeras cuando empleo el repositorio de otros, es la raíz de la página web.

Así pues:

  1. Obtenemos una versión ascii de la clave pública.
  2. La situamos en el directorio raíz (/var/lib/debian/archive_key.asc).
  3. La anunciamos en la página de inicio o algún otro sitio.
  4. Si queremos podemos enviarla a un servidor de claves como explica Daniel Leidert, aunque en ese caso es aconsejable declarar el identificador de la clave y el servidor donde se aloja también en la página web.

En el caso de mi servidor la clave está en http://debian.astillas.net/astillas.key