Introducción
Un informe de liquidación necesita acceso a la base de datos mientras se ejecuta. Una vez que el trabajo termina, su credencial guardada debe dejar de abrir nuevas conexiones. Un mensaje de aceptación de un servicio de secretos no es evidencia suficiente de ese resultado.
Este entorno independiente de MarketLedger empieza con los permisos correctos sobre la vista. Ejecutarás el informe, revocarás su concesión exacta de OpenBao, observarás la caducidad natural de otra concesión y te recuperarás obteniendo un nuevo inicio de sesión. La tienda y su informe de inventario independiente deben seguir siendo utilizables. El laboratorio guiado anterior enseñó los campos de las credenciales y la política limitada de informes; no se transfieren archivos ni estado de sesión.
Empieza por la tienda en funcionamiento y la política correcta del informe
En este paso identificarás el negocio normal y los dos roles de informes antes de iniciar el reloj de cualquiera de las concesiones. Usa Terminal en todo momento. Entra en el espacio de trabajo independiente:
cd /home/labex/project/market-report
cat muestra el ejemplo funcional preparado:
cat demo.tsv
La liquidación abarca 2026-10-28: Birch tiene dos pedidos pagados que suman 4700 céntimos, Elm uno que suma 2000 y Maple uno que suma 2700. Se excluye el pedido cancelado. El informe usa reporting.daily_settlement; los correos privados de clientes y las referencias bancarias quedan fuera de su alcance.
El cliente de tienda preparado se comunica con el servicio real de tienda. Sus argumentos identifican un pedido nuevo, un vendedor y un importe en céntimos. Haz un pedido normal para la siguiente fecha comercial sintética, 2026-10-29:
python3 shop.py place --order O201 --vendor V101 --cents 600
Este pedido posterior no pertenece a la liquidación de ayer. Si repites el comando, el servicio rechaza el duplicado; usa python3 shop.py list para ver el pedido existente en lugar de eliminarlo.
El env.sh suministrado contiene las direcciones locales de los servicios y lee el token del operador restringido desde su archivo privado. source carga esas asignaciones en el shell actual; export las pone a disposición de los comandos hijos. Un terminal nuevo debe cargarlas otra vez:
source env.sh
El token del operador autoriza solicitudes de OpenBao; no es una contraseña de base de datos. Este token puede obtener y revocar las concesiones exactas de los roles settlement-report y settlement-short. No puede gestionar el informe de inventario independiente ni leer la conexión de administrador de base de datos.
Lee las sentencias correctas de creación de cuentas:
cat role.sql
Crean un inicio de sesión generado con la caducidad de contraseña suministrada, conceden búsqueda en el esquema y acceso de lectura a la vista de liquidación, y conservan la auditoría SQL nativa. Conserva sin cambios estas sentencias y las configuraciones de ambos roles en este laboratorio.
El rol normal de informes dura diez minutos por defecto. Un rol preparado independiente, settlement-short, dura treinta segundos y tiene los mismos permisos sobre la vista. Ningún reloj empieza hasta que solicitas credenciales. No necesitas apresurarte por la lección antes de que caduquen credenciales creadas durante la preparación.
Puedes emitir credenciales de estos roles, ejecutar la consulta de informe suministrada, guardar el informe y las respuestas privadas de credenciales, y revocar las concesiones exactas de informes que hayas obtenido. Conserva los registros originales de la base de datos, la tienda, el rol y la concesión independientes de inventario, la consulta suministrada, el entorno, el token del operador y el entorno de ejecución preparado. Nunca revoques un prefijo completo de concesiones.
Para una ruta mal escrita, vuelve con el cd absoluto anterior, ejecuta ls y reintenta con el nombre de archivo real. Esta recuperación funciona sin restablecer el entorno.
Ejecuta la liquidación con un nuevo inicio de sesión temporal
En este paso producirás un informe real antes de terminar el acceso de ese trabajo. Permanece en Terminal, con env.sh cargado.
umask 077 hace que los archivos nuevos sean privados para tu cuenta. bao read -format=json solicita una credencial dinámica real y emite JSON; > lo guarda en un archivo en lugar de mostrar su contraseña. Esta emisión inicia el reloj de diez minutos de la concesión:
umask 077
bao read -format=json database/creds/settlement-report > lease.json
jq selecciona campos JSON. Lee el ID de concesión no secreto, la duración y el nombre de usuario de base de datos generado:
jq '.lease_id, .lease_duration, .data.username' lease.json
El ID de concesión identifica esta emisión en OpenBao; el nombre de usuario identifica su inicio de sesión de PostgreSQL. Ninguno es el token del operador. No sobrescribas esta respuesta solo para volver a inspeccionarla: necesitarás su ID de concesión exacto al terminar el acceso.
La opción -r elimina las comillas de JSON. Las sustituciones de comandos entre comillas cargan el usuario y la contraseña generados en el entorno del cliente de base de datos sin mostrar la contraseña:
export PGUSER="$(jq -r .data.username lease.json)"
export PGPASSWORD="$(jq -r .data.password lease.json)"
psql -X ignora los archivos personales de inicio de psql, -v ON_ERROR_STOP=1 detiene la ejecución ante errores SQL y -c suministra un comando SQL. Pregunta a la conexión real qué identidad usa:
psql -X -v ON_ERROR_STOP=1 -c 'SELECT current_user;'
Se espera tu nombre de usuario recién generado. -f report.sql lee la consulta preparada; > guarda su salida real separada por tabulaciones:
psql -X -v ON_ERROR_STOP=1 -f report.sql > settlement.tsv
cat settlement.tsv
Se esperan las tres filas de vendedores con las mismas cantidades de pedidos pagados y totales que el ejemplo funcional. Ejecuta la comprobación de resultado de solo lectura:
sudo python3 /opt/labex-report/verify.py result
El comprobador preparado usa sudo para leer evidencia nativa protegida y probar el SQL de política en un entorno de prueba aislado de cuenta ordinaria. No emite tus credenciales reales ni genera el informe. Una demostración copiada sin una consulta real de informe bajo la identidad emitida no pasa la comprobación.
Si lees despacio y el inicio de sesión caduca antes de ejecutar el informe, solicita un reemplazo una sola vez, vuelve a cargar ambas variables de base de datos y repite los comandos de identidad e informe. Si todavía quieres terminar explícitamente una emisión existente, conserva su respuesta con otro nombre de archivo antes de solicitar otra. También debe terminarse la concesión exacta de cada reemplazo utilizado para ejecutar el informe; la comprobación final utiliza la ejecución real más reciente del informe.
Revoca la concesión exacta del trabajo terminado
En este paso terminarás el acceso del trabajo de informe y probarás una nueva conexión con la credencial antigua guardada. Permanece en Terminal.
bao lease revoke solicita revocar una emisión. La sustitución entre comillas $(jq -r .lease_id lease.json) proporciona el ID completo de concesión guardado. Usa ese ID exacto, no un nombre de usuario de base de datos ni un prefijo que contenga otras concesiones. Si esta emisión de diez minutos ya caducó mientras leías, la revocación puede indicar que ya no encuentra su concesión. Para el ejercicio de revocación explícita, conserva esa respuesta antigua, obtén una credencial de reemplazo del rol normal con un nombre de archivo nuevo, vuelve a cargar ambas variables de base de datos, ejecuta de nuevo el informe y usa el nombre de archivo del reemplazo en el comando y la prueba siguientes. Una emisión ya caducada no demuestra tu revocación explícita:
bao lease revoke "$(jq -r .lease_id lease.json)"
La CLI puede indicar que las operaciones de revocación se pusieron en cola. Esa respuesta por sí sola no establece que PostgreSQL haya rechazado el inicio de sesión antiguo.
La prueba preparada access.py lee la credencial guardada y abre una nueva conexión TCP autenticada con contraseña. --wait-denied 10 permite hasta diez segundos para un rechazo de contraseña. Distingue ese rechazo de una base de datos no disponible o una consulta SQL rechazada; detener el servidor no puede satisfacerla:
python3 /opt/labex-report/access.py lease.json --wait-denied 10
Se espera el mensaje password authentication failed de PostgreSQL seguido de la confirmación de que esta credencial guardada no puede abrir una nueva conexión. La prueba informa del estado nativo 2 de psql. La propia prueba devuelve éxito solo después de confirmar la denegación esperada.
echo $? muestra el estado de salida del comando inmediatamente anterior. Aquí se espera 0: la prueba confirmó correctamente el fallo previsto, en lugar de que psql se conectara correctamente:
echo $?
Comprueba el trabajo terminado:
sudo python3 /opt/labex-report/verify.py finished
La comprobación exige una revocación nativa correcta de la concesión exacta, el evento correspondiente de revocación completada, un fallo posterior de autenticación nueva y un inicio de sesión de PostgreSQL realmente inutilizable. También mantiene intactos el informe completo y las funciones independientes de tienda e informes. No revoca nada por ti.
Este ejercicio prueba conexiones nuevas realizadas por comandos cliente de corta duración. La caducidad de una contraseña no obliga a cerrar todas las conexiones ya abiertas, y esta lección no afirma vaciar todos los pools de conexiones de producción.
Observa la caducidad natural de otra concesión
En este paso distinguirás la caducidad natural de tu revocación explícita. Usa Terminal con el mismo operador restringido de OpenBao.
El rol preparado settlement-short tiene un TTL de treinta segundos. Solicitarás su credencial y probarás inmediatamente una lectura real permitida en una sola operación, para que leer la explicación siguiente no consuma su tiempo útil. && ejecuta la prueba solo si la emisión de credenciales tiene éxito:
bao read -format=json database/creds/settlement-short > short-lease.json && python3 /opt/labex-report/access.py short-lease.json
Se espera un nombre de usuario generado, la vista de liquidación real de tres filas y Native psql exit: 0. Son un nombre de usuario y un ID de concesión diferentes de los del trabajo revocado explícitamente. La prueba de solo lectura no crea tu archivo de informe ni termina el trabajo de informe por ti.
Ahora deja que esta concesión caduque por sí sola. No revoques ni renueves short-lease.json. La siguiente prueba abre conexiones nuevas repetidamente y espera hasta cuarenta segundos para una denegación real de autenticación con contraseña:
python3 /opt/labex-report/access.py short-lease.json --wait-denied 40
Si tardaste más de treinta segundos en leer antes de este comando, la denegación puede aparecer inmediatamente. Sigue siendo caducidad natural: la operación combinada anterior ya demostró que la credencial funcionó inicialmente. De lo contrario, la prueba espera hasta la caducidad. Se espera el fallo nativo de PostgreSQL y la confirmación de la prueba, igual que antes.
Un error de conexión que indique que el servidor no está disponible no demuestra caducidad. Si falló la emisión inicial o su lectura inmediata, inspecciona ese error antes de repetir la operación combinada. No presentes una contraseña inválida sin usar como evidencia de que caducó una credencial funcional. La comprobación final exige la lectura real correcta del rol breve, el evento nativo de caducidad y el rechazo de autenticación posterior.
El reloj de la concesión empezó por tu solicitud, no durante la preparación, y ningún paso exige que escribas dentro de una ventana incidental de arranque.
Recupérate con un nuevo inicio de sesión y termina también su acceso
En este paso completarás un intento posterior de informe después de que las credenciales antiguas hayan dejado de funcionar. Permanece en Terminal. Recuperarse significa obtener una nueva credencial mediante el servicio autorizado; editar una respuesta antigua no renueva su identidad de base de datos.
Guarda la nueva emisión del rol normal con un nombre diferente para conservar la evidencia anterior:
bao read -format=json database/creds/settlement-report > recovery-lease.json
Carga esa nueva identidad y ejecuta el mismo informe real:
export PGUSER="$(jq -r .data.username recovery-lease.json)"
export PGPASSWORD="$(jq -r .data.password recovery-lease.json)"
psql -X -v ON_ERROR_STOP=1 -f report.sql > settlement.tsv
cat settlement.tsv
El resultado empresarial completo no cambia. El nombre de usuario de base de datos es nuevo, que es la vía de recuperación esperada tras terminar una emisión antigua.
Termina también la concesión exacta de este trabajo de reemplazo:
bao lease revoke "$(jq -r .lease_id recovery-lease.json)"
python3 /opt/labex-report/access.py recovery-lease.json --wait-denied 10
Si vuelves a ejecutar el informe usando otro inicio de sesión de reemplazo, termina también esa concesión exacta. La comprobación final usa la identidad que está detrás de la ejecución real más reciente del informe, por lo que una cuenta revocada anterior no demuestra que haya terminado un trabajo posterior.
El cliente preparado de tienda usa su identidad de escritor independiente. Confirma que se conserva el pedido normal de hoy:
python3 shop.py list
Ejecuta la comprobación final del ciclo de vida:
sudo python3 /opt/labex-report/verify.py lifecycle
Lee los eventos nativos existentes de emisión, consulta, revocación y autenticación antes de hacer pruebas de conservación de solo lectura. Se espera la confirmación de evidencia diferenciada de revocación explícita, caducidad natural y recuperación con inicio de sesión de reemplazo, con las credenciales antiguas probadas incapaces de abrir nuevas conexiones. Los datos originales del informe, la tienda y la credencial independiente de inventario deben permanecer intactos.
Si un comando de informe falla porque un reemplazo caducó mientras leías, conserva esa respuesta, solicita otro reemplazo con un nuevo nombre de archivo, vuelve a cargar sus variables de base de datos, ejecuta de nuevo el informe y termina esa nueva concesión exacta. Usa los mismos comandos enseñados con ese nombre de archivo. No amplíes la caducidad del usuario antiguo ni revoques un prefijo completo del rol.
Resumen
Has ejecutado un informe real, terminado su concesión exacta, observado la caducidad natural de otra credencial y realizado una recuperación con una identidad recién emitida cuyo acceso al trabajo también terminaste. Has distinguido una solicitud en cola de una denegación real de la base de datos, y un servicio detenido de una contraseña rechazada.
El resultado se limita deliberadamente a conexiones nuevas autenticadas con contraseña en este entorno preparado. No afirma que se hayan terminado todas las sesiones ya abiertas ni los pools de producción. El desafío combina la política de permisos y el ciclo de vida del trabajo terminado para una vista de informes diferente.


