Introducción
Una entrega verificada solo resulta útil si esos bytes verificados se convierten en la versión en funcionamiento. Waymark necesita un receptor reutilizable que rechace un paquete no aprobado antes de cambiar su guía del festival de paseos.
Sustituirás un breve script de shell, pondrás a prueba sus decisiones de rechazo y publicarás la actualización solicitada por el organizador. Este entorno independiente empieza con la guía original y sus propios paquetes. El laboratorio guiado anterior enseñó firmas, claves de confianza independientes, metadatos solicitados y resúmenes de archivos comprimidos. Ahora los combinarás sin necesidad de programar en Python.
Comprende la guía en funcionamiento y el contrato del receptor
En este paso identificarás qué debe cambiar la actualización y qué debe conservar. Abre Event Guide y después Old Mill Walk. La edición original de event-guide es 2.0 y el paseo tiene su encuentro a las 11:00. Usa All walks para volver y descarga la hoja de rutas. Tanto la página de detalle como la descarga deben funcionar después de la actualización.
La página de inicio de la guía identifica la edición encima del encabezado y muestra la hora de encuentro de cada paseo en su tarjeta:

Cambia a Workspace. cd cambia de directorio; esta ruta absoluta funciona desde cualquier ubicación:
cd /home/labex/project/waymark
cat muestra archivos. Lee la solicitud de actualización proporcionada de forma independiente:
cat /opt/labex-waymark/trust/request.json
Solicita el producto event-guide, versión 2.1. La actualización aprobada cambia Old Mill Walk a las 14:00. El otro paseo conserva las 09:30. Lee el script inicial:
cat receive.sh
El script inicial toma un resumen del propio paquete y se lo pasa al publicador. Otro editor podría proporcionar un manifiesto y un archivo comprimido coincidentes. Este script todavía no verifica una firma ni el producto y la versión solicitados por el organizador. Lo sustituirás antes de publicar.
La interfaz requerida es:
bash receive.sh CANDIDATE_DIRECTORY DESTINATION_DIRECTORY
El primer argumento es un paquete del proveedor. El segundo es un directorio de publicación de la guía; en el proyecto activo es published. Ambas rutas pueden ser absolutas o relativas, cambiar de nombre y contener espacios. No fijes en el código una etiqueta de paquete ni el destino. Una actualización correcta devuelve cero. Un rechazo devuelve un valor distinto de cero y conserva sin cambios todos los archivos de publicación existentes. Una actualización legítima conserva las versiones anteriores y las cargas ajenas a ella.
Puedes editar receive.sh y crear archivos temporales. Conserva sin cambios los paquetes originales, la clave y la solicitud independientes, el publicador preparado y los demás archivos de ejecución. El receptor debe funcionar desde otro directorio cuando se copie solo, disponiendo de las mismas herramientas preparadas y archivos de confianza independientes. La evaluación prueba este contrato en directorios desechables, además de comprobar la guía real.
Si escribes mal una ruta, ejecuta el cd absoluto anterior, usa ls candidates para comprobar las etiquetas y vuelve a ejecutar el comando. Una comprobación fallida es motivo para inspeccionar la evidencia correspondiente, no para restablecer el entorno.
Diseña un receptor que se detenga antes de publicar
En este paso comprenderás el breve script antes de escribirlo. Permanece en Workspace.
El receptor copiará los tres archivos relacionados a un directorio temporal privado, verificará ese manifiesto copiado, comparará su producto y versión con la solicitud independiente y pasará el archivo comprimido copiado junto con el resumen firmado a un publicador preparado. Nunca verificará un candidato para después volver a abrir otra ruta de candidato para la entrega.
El publicador /opt/labex-waymark/publish.py es código preparado para manejar archivos comprimidos. Lee el archivo suministrado en un único búfer de bytes, compara ese búfer con el resumen suministrado, extrae de forma segura solo site.json y routes.csv, y publica esos mismos bytes. Conserva las versiones anteriores y uploads/. No decide en la firma de quién confiar ni qué producto y versión solicitó el organizador; esas decisiones corresponden a tu receptor.
Usarás estas funciones del shell:
#!/bin/bashidentifica el shell del script. Ejecutarbash receive.shtambién selecciona Bash explícitamente.set -euo pipefailhace que un comando fallido sin gestionar, una variable sin definir o una tubería fallida detengan el script. Una firma fallida nunca debe dejar que la ejecución continúe hasta publicar.$1y$2son los dos argumentos.candidate=$1guarda un valor;"$candidate"lo expande como un único argumento, incluidos los espacios.$#cuenta los argumentos, y[ "$#" -ne 2 ]comprueba si esa cantidad no es dos.if,thenyfidelimitan el bloque condicional.$(command)guarda la salida de un comando.mktemp -dcrea un directorio temporal único.trap '...' EXITejecuta la limpieza al terminar el script. Aquírm -rf -- "$stage"elimina solo ese directorio temporal generado; nunca lo sustituyas por el directorio de tu proyecto.--finaliza la interpretación de opciones para que una ruta se trate como datos.cp -- SOURCE SOURCE SOURCE DIRECTORY/copia los tres archivos. La barra final identifica el directorio de destino.jq -r .product FILElee una cadena JSON sin las comillas de JSON.jq -edevuelve un estado de fallo para un resultado falso.--arg product "$product"proporciona al filtro una variable de cadena llamada$product.andexige que todas las condiciones se cumplan. Las comillas simples conservan el texto del filtro para jq.> /dev/nulldescarta el booleano mostrado y conserva su estado de salida.echo ... >&2escribe un error en el flujo de errores;exit 2termina con un estado distinto de cero.
El comando de firma usa la misma clave pública fijada de forma independiente que el laboratorio anterior. Su --bundle apunta al bundle de firma copiado y su último argumento es el manifiesto copiado. --insecure-ignore-tlog es la limitación explícita de estos datos de prueba sintéticos sin conexión: omite la verificación del registro público mientras sigue comprobando la firma con la clave fijada. Este receptor no verifica identidades públicas ni registros de transparencia.
El último comando de Python invoca el publicador preparado; no estás escribiendo Python. Recibe el archivo comprimido copiado, el resumen del manifiesto verificado y el destino solicitado. Si el resumen no coincide con los bytes del archivo, rechaza la actualización antes de tocar la guía existente.
Guarda el receptor reutilizable
En este paso escribirás el receptor con los mecanismos que acabas de revisar. Empieza en Workspace, en /home/labex/project/waymark.
El siguiente comando sustituye receive.sh. cat > receive.sh redirige el texto proporcionado al archivo. <<'RECEIVER' inicia un here-document: todo lo que aparece hasta la línea que contiene únicamente RECEIVER pasa a ser contenido del archivo. Las comillas de ese marcador conservan $1, $stage y las variables de jq para la ejecución posterior del script. Pega el bloque completo, incluido su marcador final:
cat > receive.sh <<'RECEIVER'
#!/bin/bash
set -euo pipefail
if [ "$#" -ne 2 ]; then
echo "Usage: bash receive.sh CANDIDATE_DIRECTORY DESTINATION_DIRECTORY" >&2
exit 2
fi
candidate=$1
destination=$2
stage=$(mktemp -d)
trap 'rm -rf -- "$stage"' EXIT
cp -- "$candidate/manifest.json" "$candidate/manifest.sigstore.json" "$candidate/guide.tar.gz" "$stage/"
/opt/labex-waymark/bin/cosign verify-blob --key /opt/labex-waymark/trust/publisher.pub --bundle "$stage/manifest.sigstore.json" --insecure-ignore-tlog "$stage/manifest.json"
product=$(jq -r .product /opt/labex-waymark/trust/request.json)
version=$(jq -r .version /opt/labex-waymark/trust/request.json)
jq -e --arg product "$product" --arg version "$version" '.product == $product and .version == $version and .archive == "guide.tar.gz"' "$stage/manifest.json" > /dev/null
digest=$(jq -r .sha256 "$stage/manifest.json")
python3 /opt/labex-waymark/publish.py "$stage/guide.tar.gz" "$digest" "$destination"
RECEIVER
Vuelve a leerlo:
cat receive.sh
Confirma que la clave pública y la solicitud proceden de /opt/labex-waymark/trust/, mientras que el manifiesto, el bundle y el archivo comprimido proceden todos de "$stage". Observa que el directorio del candidato original no se vuelve a leer tras copiarlo. Cambiar o renombrar la entrega del proveedor después de esa copia no puede cambiar los bytes que se entregan al publicador.
Si el terminal muestra un indicador de continuación porque se omitió el marcador final, escribe RECEIVER en una línea independiente y pulsa Intro. Si se pegó mal el archivo, repite el here-document completo; esto sustituye únicamente receive.sh. No ejecutes un receptor incompleto.
La comprobación de política preparada ejecuta tu script sin cambios como una cuenta ordinaria contra directorios de publicación desechables. Comprueba los archivos realmente publicados, los casos rechazados y el comportamiento de conservación; no busca una forma concreta de escribir los comandos:
sudo python3 /opt/labex-waymark/verify.py policy
sudo es necesario para que esta comprobación preparada ejecute la cuenta ordinaria aislada, no para tu receptor. La comprobación no toca la guía activa. Su última línea debería indicar que se acepta la guía firmada solicitada y se rechazan los cuatro casos no aprobados. Si falla, inspecciona la decisión indicada y corrige receive.sh antes de continuar.
Observa los rechazos antes de actualizar la guía activa
En este paso confirmarás que el receptor se detiene ante tres fallos distintos mientras la guía original sigue disponible. Empieza en Workspace, en /home/labex/project/waymark.
Primero prueba el paquete firmado por otro editor. Se espera un error de verificación de firma y un estado distinto de cero:
bash receive.sh candidates/parcel-102 published
$? contiene el estado de salida del comando inmediatamente anterior. Léelo antes de ejecutar cualquier otra cosa:
echo $?
Ahora prueba la edición auténtica pero anterior. Se espera que la verificación de firma tenga éxito, seguida de un estado distinto de cero porque la comparación con el producto y la versión solicitados es falsa:
bash receive.sh candidates/parcel-101 published
echo $?
La comparación de jq es silenciosa de forma intencionada; el estado distinto de cero registra su rechazo. Una firma válida no anuló la solicitud independiente.
Por último, prueba el archivo modificado. Se espera que la firma pase la verificación, pero que el publicador informe de una discrepancia del resumen y conserve la guía existente:
bash receive.sh candidates/parcel-103 published
echo $?
Cambia a Event Guide y actualiza. La guía debe seguir en la edición 2.0; Old Mill Walk debe seguir teniendo su encuentro a las 11:00. Usa All walks para volver, descarga la hoja de rutas y abre Visitor notice. Un receptor que rechazara todo también conservaría esta guía antigua, por eso se exige además una actualización legítima correcta.
La ausencia de un archivo o un error de conexión no equivalen a estos rechazos de política esperados. Si escribiste mal la ruta de un paquete, vuelve a la ruta absoluta del espacio de trabajo, enumera candidates y vuelve a intentarlo. Si el sitio web no está disponible, inspecciona el error indicado; no lo consideres un rechazo correcto.
Publica y usa la nueva guía aprobada
En este paso entregarás la actualización verificada y usarás sus páginas y descarga reales. Empieza en Workspace, en /home/labex/project/waymark.
Recibe el paquete aprobado:
bash receive.sh candidates/parcel-104 published
Deberías ver Verified OK y:
Published event-guide 2.1. Previous releases and uploads kept.
Comprueba su estado inmediatamente:
echo $?
Debería ser 0. Cambia a Event Guide y actualiza. La página de inicio muestra ahora la edición 2.1 de event-guide. Abre Old Mill Walk y confirma las 14:00; después usa All walks y abre Riverside Welcome para confirmar que se conserva el encuentro a las 09:30. Vuelve con All walks y descarga la nueva hoja de rutas. Las dos filas deben concordar con las páginas de detalle. Abre Visitor notice para confirmar que se conservan los consejos originales.
La página de inicio aprobada muestra la edición 2.1; fíjate en la hora de encuentro de Old Mill Walk, 14:00:

Cambia a Workspace. La autocomprobación del servicio activo lee la página de detalle en funcionamiento, los bytes descargados de la hoja de rutas, los archivos actuales de la guía, la versión anterior conservada y el aviso:
python3 /opt/labex-waymark/verify.py live
Resultado esperado:
The running guide and download match the approved release. Previous releases and visitor notice are preserved.
ls enumera los directorios de versiones conservados:
ls published/releases
Debería haber una versión anterior event-guide-2.0-... y la nueva event-guide-2.1-.... Los caracteres finales proceden del resumen real del archivo y no son valores que debas memorizar.
Si falla la comprobación del servicio activo, usa su mensaje para distinguir una decisión del receptor de un sitio web no disponible o un archivo original modificado. Corrige el receptor si hace falta y vuelve a recibir el paquete aprobado original. Repetir la misma actualización válida es seguro: el publicador reutiliza la versión idéntica y conserva los archivos anteriores. Repite la autocomprobación del servicio activo para confirmar el resultado.
Resumen
Has sustituido un receptor que confiaba en su entrega por otro que comprueba una clave de editor y una solicitud del organizador independientes, y después vincula el resumen firmado del archivo comprimido a los bytes que se publican realmente. Se rechazaron firmantes incorrectos, versiones antiguas auténticas y archivos modificados mientras el servicio original seguía siendo utilizable.
La actualización aprobada es ahora una guía real con páginas de detalle funcionales y una descarga de rutas coincidente. El desafío aplica estas mismas herramientas a una guía accesible e incluye un paquete firmado auténtico de un producto incorrecto.


