Módulo 5: Securing The Ai Workload
5. Manos a la obra: Trivy sobre el Terraform nuevo
Descripción
Esta lección corre trivy config de verdad —0.74.0, la misma versión que cloud-security-and-guardrails-guide, Módulo 5, ya fijó, sin reinstalar nada— sobre las dos piezas de Terraform genuinamente nuevas de esta guía: bedrock.tf y modules/bedrock-guardrail/. El resultado, tal como corrió mientras se escribía esta lección, es honesto en las dos direcciones: ni una falsa promesa de que Trivy "certifica" que el guardrail está bien configurado desde el punto de vista de negocio, ni una simulación de hallazgos que no ocurrieron.
Conexión con el módulo
cloud-security-and-guardrails-guide, Módulo 5, lección 4, corrió trivy config . sobre el proyecto completo de esa guía y encontró once hallazgos reales, repartidos en cuatro archivos —dynamodb.tf, lambda.tf, modules/s3-bucket/main.tf, secrets.tf—, mientras que iam.tf/oidc.tf, ya endurecidos por el Módulo 2 de esa guía, no generaron ningún hallazgo en absoluto. Esta lección repite exactamente el mismo comando —mismo binario, misma versión, cero reinstalación— sobre el Terraform que este módulo agrega, y documenta con la misma honestidad qué encontró.
Analogía retomada: el mismo inspector, ahora en el ala nueva del edificio
cloud-security-and-guardrails-guide, Módulo 5, lección 4, comparó a Trivy con un inspector que camina la casa completa con una lista de doscientos puntos de verificación. Esta lección es ese mismo inspector, entrando por primera vez al ala del edificio que este módulo acaba de construir —bedrock.tf, modules/bedrock-guardrail/—. No trae una lista distinta, no necesita que nadie le explique qué es un guardrail de Bedrock antes de empezar: aplica exactamente la misma lista de siempre, y reporta, con la misma precisión, lo que encuentra —o lo que no encuentra—.
Paso 1 — El comando, sobre exactamente lo nuevo
A diferencia de trivy config . (que escanea el proyecto andes-cargo-infra/ completo, heredado y nuevo mezclados), esta lección aísla el Terraform genuinamente nuevo de este módulo, para que el resultado no se confunda con hallazgos que ya existían antes de este módulo:
trivy config bedrock.tf modules/bedrock-guardrail/
Qué esperar (el primer intento, literal — Trivy no acepta más de un DIR como argumento posicional):
FATAL Fatal error multiple targets cannot be specified
Un error real, y vale la pena leerlo con atención en vez de descartarlo: trivy config acepta exactamente un DIR como objetivo, no una lista de archivos y carpetas sueltos. La forma correcta de aislar "solo lo nuevo de este módulo" es escanear un directorio que contenga exactamente esos archivos —no pasarle dos rutas distintas en la misma invocación—.
Paso 2 — El comando correcto: un directorio aislado con solo lo nuevo
mkdir -p bedrock-scan/modules
cp bedrock.tf locals.tf variables.tf bedrock-scan/
cp -r modules/bedrock-guardrail modules/iam-role bedrock-scan/modules/
cd bedrock-scan
trivy config .
modules/iam-role/ entra también, aunque no es nuevo de este módulo —bedrock.tf lo referencia con source = "./modules/iam-role" para declarar BedrockManifestExtractorRole—, porque sin él Trivy no podría resolver el módulo completo y reportaría un error de referencia, no un hallazgo real.
Qué esperar (literal — ejecutado para escribir esta lección, con Trivy 0.74.0):
2026-08-14T15:49:53-06:00 INFO [misconfig] Misconfiguration scanning is enabled
2026-08-14T15:49:53-06:00 INFO [checks-client] Using existing checks from cache path="~/Library/Caches/trivy/policy/content"
2026-08-14T15:49:53-06:00 INFO [terraform scanner] Scanning root module file_path="."
2026-08-14T15:49:53-06:00 INFO Detected config files num=1
Report Summary
┌────────┬───────────┬───────────────────┐
│ Target │ Type │ Misconfigurations │
├────────┼───────────┼───────────────────┤
│ . │ terraform │ 0 │
└────────┴───────────┴───────────────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)
Cero hallazgos. Antes de interpretar ese 0 —y es fácil interpretarlo mal en cualquiera de las dos direcciones—, confirma con --debug que Trivy de verdad leyó los nueve archivos involucrados, no que se saltó algo silenciosamente:
trivy config . --debug 2>&1 | grep -i "parsing\|module"
Qué esperar (recortado a las líneas relevantes, literal):
DEBUG [terraform parser] Parsing module="root" file_path="bedrock.tf"
DEBUG [terraform parser] Added file module="root" file_path="bedrock.tf"
DEBUG [terraform parser] Parsing module="root" file_path="locals.tf"
DEBUG [terraform parser] Added file module="root" file_path="locals.tf"
DEBUG [terraform parser] Parsing module="root" file_path="variables.tf"
DEBUG [terraform parser] Added file module="root" file_path="variables.tf"
DEBUG [terraform parser] Parsing FS module="root" file_path="modules/bedrock-guardrail"
DEBUG [terraform parser] Parsing module="root" file_path="modules/bedrock-guardrail/main.tf"
DEBUG [terraform parser] Added file module="root" file_path="modules/bedrock-guardrail/main.tf"
DEBUG [terraform parser] Parsing FS module="root" file_path="modules/iam-role"
DEBUG [terraform parser] Parsing module="root" file_path="modules/iam-role/main.tf"
DEBUG [terraform parser] Added file module="root" file_path="modules/iam-role/main.tf"
Nueve archivos, los nueve parseados sin ningún error de sintaxis ni de referencia — el 0 del reporte es un resultado real de haber evaluado el HCL completo, no el resultado de que Trivy se rindiera antes de leerlo.
Por qué el resultado es cero, con precisión
Vale la pena ser exacto sobre qué significa —y qué NO significa— este resultado, con la misma disciplina de honestidad del resto de esta guía. El checks bundle de Trivy —el mismo conjunto de reglas que encontró once hallazgos reales contra s3.tf, dynamodb.tf, lambda.tf y secrets.tf en cloud-security-and-guardrails-guide— no contiene, todavía, ninguna regla específica para aws_bedrock_guardrail. aws_bedrock_guardrail es un recurso relativamente nuevo del provider hashicorp/aws (Módulo 3, lección 1 de esta guía ya confirmó la versión v6.60.0 en este entorno); las reglas de Trivy para un recurso específico se escriben y se agregan al bundle con el tiempo, a medida que la comunidad de seguridad las desarrolla — al momento de escribir esta lección, ese trabajo todavía no existe para este recurso en particular.
BedrockManifestExtractorRole (vía modules/iam-role/), en cambio, sí está sujeto a reglas reales de Trivy sobre políticas IAM — y pasa limpio, no por ausencia de reglas, sino porque el mínimo privilegio del Módulo 3, lección 4 (una acción, un recurso, ningún comodín) no dispara ninguna de ellas. Esto es, en los hechos, el mismo patrón que cloud-security-and-guardrails-guide, Módulo 5, lección 4 ya documentó para iam.tf/oidc.tf: un archivo puede estar ausente de la tabla de hallazgos por dos razones completamente distintas —porque nadie escribió todavía una regla que aplique (el caso del guardrail), o porque el HCL ya cumple con las reglas que sí existen (el caso del rol)—.
POR QUÉ "0 HALLAZGOS" NO SIGNIFICA LO MISMO PARA CADA PIEZA
modules/bedrock-guardrail/ modules/iam-role/ (BedrockManifestExtractorRole)
│ │
│ 0 hallazgos porque el │ 0 hallazgos porque el HCL SÍ cumple
│ *checks bundle* de Trivy │ con reglas reales que SÍ existen
│ todavía no tiene reglas │ (mínimo privilegio de IAM, ya
│ para este tipo de recurso │ verificado también por
│ │ bedrock-least-privilege.rego, L3)
▼ ▼
"sin cobertura todavía", "cobertura real, pasada limpio"
no "certificado seguro"
Este es exactamente el mismo tipo de límite que la lección 4 de este módulo ya nombró para las API keys de Bedrock: precisión sobre qué SÍ está verificado frente a qué queda fuera del alcance de la herramienta, sin inflar el resultado en ninguna dirección.
Paso 3 — Confirmando que el resto del proyecto sigue limpio
Para cerrar el círculo, confirma que agregar bedrock.tf no introdujo ningún hallazgo nuevo en el resto de andes-cargo-infra/ — el mismo argumento aditivo que el Módulo 3, lección 5 de esta guía ya hizo con terraform plan (17 to add, 0 to change, nunca 0 to change roto):
cd ..
trivy config . --exit-code 1 --severity CRITICAL,HIGH
echo "exit: $?"
Qué esperar (literal — sobre el proyecto andes-cargo-infra/ completo, ya endurecido por cloud-security-and-guardrails-guide hasta su capstone; el mismo comando exacto que el job iac-scan de ci.yml corre):
Report Summary
┌────────┬───────────┬───────────────────┐
│ Target │ Type │ Misconfigurations │
├────────┼───────────┼───────────────────┤
│ . │ terraform │ 0 │
└────────┴───────────┴───────────────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)
exit: 0
Cero hallazgos CRITICAL/HIGH en todo el proyecto, bedrock.tf incluido — el mismo filtro de severidad que ci.yml (heredado de cloud-security-and-guardrails-guide, Módulo 8, lección 3) ya usa en el job iac-scan. La lección 8 de este módulo corre este comando exacto dentro de ese job real, con act pull_request.
Errores comunes
Pasar varios archivos/carpetas sueltos a trivy config, esperando que funcione como cp o git add (de suponer que todos los comandos CLI aceptan múltiples rutas). Qué pasa: alguien, acostumbrado a comandos de shell que aceptan una lista de rutas, escribe trivy config bedrock.tf modules/bedrock-guardrail/ directamente. Cómo detectarlo: el mensaje multiple targets cannot be specified, mostrado tal cual en el Paso 1 de esta lección. Cómo corregirlo: trivy config escanea exactamente un DIR — para aislar un subconjunto de archivos, cópialos a un directorio dedicado (Paso 2), o escanea el proyecto completo y filtra el resultado por archivo en la tabla del Report Summary.
Interpretar "0 hallazgos" en modules/bedrock-guardrail/ como "Trivy certificó que el guardrail está bien configurado" (de sobre-confiar en la ausencia de un hallazgo). Qué pasa: alguien lee 0 en la tabla y concluye que las seis políticas del guardrail (Módulo 4) están correctamente configuradas desde el punto de vista de seguridad, con la misma confianza que tendría en un hallazgo real de Trivy. Cómo detectarlo: si tu explicación de este resultado no menciona que el checks bundle de Trivy todavía no tiene reglas específicas para aws_bedrock_guardrail. Cómo corregirlo: la sección de esta lección "Por qué el resultado es cero, con precisión" existe exactamente para esta distinción — un 0 puede significar "sin problemas encontrados" o "sin reglas que buscar problemas todavía", y confundir los dos casos es exactamente el tipo de falso sentido de seguridad que cloud-security-and-guardrails-guide, Módulo 1, lección 2 ya advirtió con "verde no es sinónimo de seguro".
Olvidar que modules/iam-role/ tiene que copiarse junto con modules/bedrock-guardrail/ para que el escaneo aislado funcione (de dependencia entre módulos, específico de este proyecto). Qué pasa: alguien copia solo bedrock.tf y modules/bedrock-guardrail/ al directorio aislado, sin modules/iam-role/, y Trivy no puede resolver la referencia source = "./modules/iam-role" que bedrock.tf declara para BedrockManifestExtractorRole. Cómo detectarlo: un mensaje de Trivy sobre un módulo no encontrado, o un Report Summary que solo cubre el guardrail y omite silenciosamente el rol. Cómo corregirlo: el Paso 2 de esta lección copia los tres directorios necesarios (bedrock.tf, modules/bedrock-guardrail/, modules/iam-role/) — cualquier aislamiento de HCL para escaneo tiene que incluir todo lo que ese HCL referencia, no solo el archivo que a primera vista parece "lo nuevo".
Ejercicios
Ejercicio 1 — Corre trivy config . sobre andes-cargo-infra/ completo (sin el filtro --severity), y compara el resultado con el de cloud-security-and-guardrails-guide, Módulo 5, lección 4. ¿Esperarías más, menos, o los mismos once hallazgos que esa lección documentó?
Ver solución
Menos — cero, de hecho, si corres contra el proyecto tal como esta guía lo hereda: cloud-security-and-guardrails-guide encontró esos once hallazgos en su Módulo 5, pero los resolvió a lo largo de su propio Módulo 5 (lección 6: "arreglar, suprimir o aceptar") antes de llegar a su capstone (Módulo 8). El proyecto que esta guía hereda es el estado posterior a esas correcciones — el mismo argumento de "hereda sin repetir" que el Módulo 1 de esta guía ya estableció para toda la infraestructura previa.
Ejercicio 2 — Explica por qué trivy config bedrock-scan/ (el directorio aislado) y trivy config . (el proyecto completo, filtrado a solo las líneas de bedrock.tf) podrían, en teoría, dar resultados distintos para el mismo archivo. Piensa en qué información tiene disponible Trivy en cada caso.
Ver solución
Podrían diferir si bedrock.tf dependiera de algún valor definido en otro archivo del proyecto completo que no esté presente en el directorio aislado —por ejemplo, si una variable con un default inseguro se declarara en variables.tf del proyecto raíz pero el directorio aislado tuviera una versión distinta de ese archivo—. En esta lección específica no ocurre, porque el Paso 2 copió los tres archivos raíz relevantes (bedrock.tf, locals.tf, variables.tf) exactamente como existen en el proyecto completo — pero en general, cualquier escaneo aislado de un subconjunto de HCL corre el riesgo de perder contexto que el proyecto completo sí tiene, la misma razón por la que el Paso 3 de esta lección también confirma el resultado contra el proyecto entero.
Ejercicio 3 — Predice qué pasaría con el Report Summary de esta lección si, en el futuro, la comunidad de seguridad de Trivy agregara una regla nueva específica para aws_bedrock_guardrail —por ejemplo, exigiendo que content_policy_config esté siempre presente—. ¿El HCL de esta guía pasaría o fallaría esa regla hipotética?
Ver solución
Pasaría: bedrock.tf (Módulo 4 de esta guía) declara content_policy_config con un filtro PROMPT_ATTACK activo, junto con las otras cinco políticas del guardrail completo — así que una regla hipotética que exigiera la presencia de esa política específica encontraría que el HCL ya la cumple. El punto de este ejercicio es notar que "0 hallazgos hoy" y "0 hallazgos mañana, cuando existan más reglas" no están garantizados a ser la misma afirmación — el resultado de Trivy es una fotografía del checks bundle en el momento exacto de la corrida, no una promesa permanente, la misma disciplina de honestidad temporal que esta guía aplica a cualquier resultado ejecutado.
Resumen y siguiente paso
Esta lección corrió trivy config de verdad, con 0.74.0, la misma versión heredada sin reinstalar, sobre bedrock.tf y modules/bedrock-guardrail/ (más modules/iam-role/, necesario para resolver la referencia). El resultado —0 misconfiguraciones— se confirmó con --debug como un resultado real, de nueve archivos parseados sin error, no un escaneo silenciosamente incompleto. Distinguiste, con precisión, por qué ese 0 significa cosas distintas para el guardrail (sin reglas específicas todavía en el checks bundle) y para el rol IAM (con reglas reales, pasadas limpio) — y confirmaste, contra el proyecto completo con el mismo filtro de severidad que usa ci.yml, que agregar este módulo no introdujo ningún hallazgo CRITICAL/HIGH nuevo.
Antes de avanzar deberías poder: explicar por qué trivy config rechaza múltiples rutas posicionales; distinguir "sin hallazgos por falta de reglas" de "sin hallazgos porque el HCL cumple reglas reales"; y correr el mismo comando exacto que el job iac-scan de ci.yml usa, desde tu propia terminal.
La lección 6 firma, con cosign, el primer artefacto binario genuinamente nuevo de esta guía: el .zip de extract-shipment-manifest-fields.
Recursos
- trivy.dev — Terraform coverage — documentación oficial de la cobertura de Terraform de Trivy, incluida la lista de recursos con reglas activas.
- Terraform Registry —
aws_bedrock_guardrail— el recurso que, al momento de escribir esta lección, todavía no tiene reglas dedicadas en el checks bundle de Trivy. cloud-security-and-guardrails-guide, Módulo 5, lección 4 (04-hands-on-scanning-andes-cargo-infra-with-trivy.md) — la corrida original detrivy config .que encontró los once hallazgos ya resueltos, heredados por esta guía sin repetirse.cloud-security-and-guardrails-guide, Módulo 8, lección 3 — el jobiac-scandeci.yml, con el comando exacto (trivy config --exit-code 1 --severity CRITICAL,HIGH .) que esta lección reprodujo en el Paso 3.