Lab práctico · Semana 8: Gobierno, cumplimiento e IA responsable

Auditoría y gobierno con model invocation logging, CloudTrail y model cards

⏱ 90-120 minDificultad: mediaTask statements: 3.33.4

Qué vas a construir

La «caja negra» de una aplicación de IA generativa: todo lo que un auditor, un regulador o tu equipo de seguridad te pedirá demostrar.

  1. Model invocation logging de Amazon Bedrock hacia CloudWatch Logs y S3: registro completo de cada prompt, cada respuesta, el modelo, la identidad que llamó y los tokens.
  2. Una política de protección de datos de CloudWatch Logs que enmascara emails en esos logs (redacción a nivel de token para quien no tenga permiso logs:Unmask).
  3. Metadatos por petición (requestMetadata) para atribuir cada invocación a un equipo y a un caso de uso.
  4. Un trail de AWS CloudTrail con eventos de gestión y data events de guardrails y knowledge bases: quién hizo qué, cuándo y desde dónde.
  5. Consultas de auditoría con CloudWatch Logs Insights.
  6. Una alarma automática cuando un guardrail interviene demasiadas veces (posible abuso).
  7. Una SageMaker model card que documenta el uso del modelo, su riesgo y sus limitaciones (transparencia, IA responsable).
flowchart LR
    APP["App (Converse + requestMetadata)"] --> BR["Amazon Bedrock"]
    BR -- "prompts y respuestas" --> CWL["CloudWatch Logs (emails enmascarados)"]
    BR -- "prompts y respuestas" --> S3L["S3: BedrockModelInvocationLogs"]
    BR -- "quién, qué, cuándo" --> CT["CloudTrail trail"]
    CT --> S3T["S3 del trail"]
    GR["Guardrail"] -- "InvocationsIntervened" --> AL["Alarma CloudWatch"] --> SNS["Tema SNS"]
    MC["SageMaker model card"] -.-> AUD["Auditoría y cumplimiento"]
    CWL --> LI["Logs Insights"]

La diferencia clave que busca el examen: CloudTrail registra la llamada a la API (identidad, IP, operación, modelo, hora) pero no el contenido del prompt ni de la respuesta; el model invocation logging registra el contenido completo. Para auditar «qué se preguntó y qué contestó el modelo» necesitas el segundo; para «quién borró el guardrail», el primero.

Antes de empezar

  • Región eu-central-1 y AWS CloudShell con permisos de administrador. Sin claves en ficheros.
  • El model invocation logging es por cuenta y región y está desactivado por defecto. Si ya lo tienes activado en eu-central-1, anota tu configuración actual (aws bedrock get-model-invocation-logging-configuration) porque este lab la reemplaza y la limpieza la borra.
  • Coste: tokens de Nova Micro (céntimos), almacenamiento mínimo en S3 y CloudWatch Logs, y data events de CloudTrail, que se cobran aparte de los eventos de gestión (consulta los precios de CloudTrail). Con unas decenas de llamadas, el total queda en céntimos.
mkdir -p ~/lab15 && cd ~/lab15
export AWS_REGION=eu-central-1
export AWS_DEFAULT_REGION=eu-central-1
export CUENTA=$(aws sts get-caller-identity --query Account --output text)
export BUCKET_LOGS="lab15-invocaciones-${CUENTA}"
export BUCKET_TRAIL="lab15-cloudtrail-${CUENTA}"
export LOG_GROUP="/lab15/bedrock/invocaciones"

Paso 1: destinos del model invocation logging

Bucket S3

Los destinos deben estar en la misma cuenta y región que la configuración de logging. La política permite a Bedrock escribir solo bajo AWSLogs/CUENTA/BedrockModelInvocationLogs/, y solo en nombre de tu cuenta (condiciones aws:SourceAccount y aws:SourceArn, que evitan el problema del confused deputy).

aws s3api create-bucket --bucket "$BUCKET_LOGS" \
  --create-bucket-configuration LocationConstraint=eu-central-1
aws s3api put-public-access-block --bucket "$BUCKET_LOGS" \
  --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

cat > politica-bucket-logs.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AmazonBedrockLogsWrite",
    "Effect": "Allow",
    "Principal": {"Service": "bedrock.amazonaws.com"},
    "Action": ["s3:PutObject"],
    "Resource": ["arn:aws:s3:::${BUCKET_LOGS}/AWSLogs/${CUENTA}/BedrockModelInvocationLogs/*"],
    "Condition": {
      "StringEquals": {"aws:SourceAccount": "${CUENTA}"},
      "ArnLike": {"aws:SourceArn": "arn:aws:bedrock:eu-central-1:${CUENTA}:*"}
    }
  }]
}
EOF
aws s3api put-bucket-policy --bucket "$BUCKET_LOGS" --policy file://politica-bucket-logs.json

Log group y rol para CloudWatch Logs

aws logs create-log-group --log-group-name "$LOG_GROUP"
aws logs put-retention-policy --log-group-name "$LOG_GROUP" --retention-in-days 7

cat > confianza-bedrock.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "bedrock.amazonaws.com"},
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": {"aws:SourceAccount": "${CUENTA}"},
      "ArnLike": {"aws:SourceArn": "arn:aws:bedrock:eu-central-1:${CUENTA}:*"}
    }
  }]
}
EOF

cat > permisos-logs.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
    "Resource": "arn:aws:logs:eu-central-1:${CUENTA}:log-group:${LOG_GROUP}:log-stream:aws/bedrock/modelinvocations"
  }]
}
EOF

aws iam create-role --role-name lab15-bedrock-logging \
  --assume-role-policy-document file://confianza-bedrock.json
aws iam put-role-policy --role-name lab15-bedrock-logging \
  --policy-name escribir-logs --policy-document file://permisos-logs.json
export ROL_LOGS=$(aws iam get-role --role-name lab15-bedrock-logging --query Role.Arn --output text)

Paso 2: activar el model invocation logging

Activas solo la modalidad de texto. Los cuerpos de más de 100 KB (o binarios) no caben en CloudWatch Logs y se envían al bucket indicado en largeDataDeliveryS3Config.

cat > logging-config.json <<EOF
{
  "cloudWatchConfig": {
    "logGroupName": "${LOG_GROUP}",
    "roleArn": "${ROL_LOGS}",
    "largeDataDeliveryS3Config": {"bucketName": "${BUCKET_LOGS}", "keyPrefix": "grandes"}
  },
  "s3Config": {"bucketName": "${BUCKET_LOGS}", "keyPrefix": "invocaciones"},
  "textDataDeliveryEnabled": true,
  "imageDataDeliveryEnabled": false,
  "embeddingDataDeliveryEnabled": false,
  "videoDataDeliveryEnabled": false
}
EOF

sleep 10   # da tiempo a que el rol recién creado se propague
aws bedrock put-model-invocation-logging-configuration --logging-config file://logging-config.json
aws bedrock get-model-invocation-logging-configuration

Si recibes un error de validación sobre el rol, espera unos segundos y repite: IAM tarda un poco en propagar los roles nuevos.

Paso 3: enmascarar datos sensibles en CloudWatch Logs

Una data protection policy de CloudWatch Logs detecta datos sensibles con identificadores gestionados y los enmascara en todos los puntos de salida (consola, Logs Insights, filtros de métricas y de suscripción). Solo quien tenga logs:Unmask ve el valor original. Se aplica a lo que se ingiere después de crearla.

cat > proteccion-datos.json <<'EOF'
{
  "Name": "lab15-proteccion",
  "Description": "Enmascara emails en los logs de invocación",
  "Version": "2021-06-01",
  "Statement": [
    {
      "Sid": "auditar",
      "DataIdentifier": ["arn:aws:dataprotection::aws:data-identifier/EmailAddress"],
      "Operation": {"Audit": {"FindingsDestination": {}}}
    },
    {
      "Sid": "enmascarar",
      "DataIdentifier": ["arn:aws:dataprotection::aws:data-identifier/EmailAddress"],
      "Operation": {"Deidentify": {"MaskConfig": {}}}
    }
  ]
}
EOF
aws logs put-data-protection-policy --log-group-identifier "$LOG_GROUP" \
  --policy-document file://proteccion-datos.json

Esta política protege CloudWatch Logs, no la copia de S3. En S3 la protección es cifrado, política de bucket, bloqueo de acceso público y, si hace falta inmutabilidad para auditoría, S3 Object Lock.

Paso 4: trail de CloudTrail con data events de Bedrock

Recuerda cómo registra CloudTrail las APIs de Bedrock:

  • InvokeModel, InvokeModelWithResponseStream, Converse y ConverseStream son management events: se registran por defecto y aparecen en Event history (90 días) sin crear nada.
  • ApplyGuardrail (incluidas las evaluaciones de guardrail durante la invocación), Retrieve/RetrieveAndGenerate de knowledge bases, InvokeFlow, InvokeAgent y otras son data events: no se registran por defecto, necesitan un trail con selectores avanzados y no aparecen en Event history, solo en el destino del trail.
aws s3api create-bucket --bucket "$BUCKET_TRAIL" \
  --create-bucket-configuration LocationConstraint=eu-central-1
aws s3api put-public-access-block --bucket "$BUCKET_TRAIL" \
  --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

TRAIL_ARN="arn:aws:cloudtrail:eu-central-1:${CUENTA}:trail/lab15-trail"
cat > politica-bucket-trail.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AWSCloudTrailAclCheck",
      "Effect": "Allow",
      "Principal": {"Service": "cloudtrail.amazonaws.com"},
      "Action": "s3:GetBucketAcl",
      "Resource": "arn:aws:s3:::${BUCKET_TRAIL}",
      "Condition": {"StringEquals": {"aws:SourceArn": "${TRAIL_ARN}"}}
    },
    {
      "Sid": "AWSCloudTrailWrite",
      "Effect": "Allow",
      "Principal": {"Service": "cloudtrail.amazonaws.com"},
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::${BUCKET_TRAIL}/AWSLogs/${CUENTA}/*",
      "Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceArn": "${TRAIL_ARN}"}}
    }
  ]
}
EOF
aws s3api put-bucket-policy --bucket "$BUCKET_TRAIL" --policy file://politica-bucket-trail.json

aws cloudtrail create-trail --name lab15-trail --s3-bucket-name "$BUCKET_TRAIL" \
  --enable-log-file-validation

aws cloudtrail put-event-selectors --trail-name lab15-trail --advanced-event-selectors '[
  {
    "Name": "Eventos de gestion",
    "FieldSelectors": [{"Field": "eventCategory", "Equals": ["Management"]}]
  },
  {
    "Name": "Data events de guardrails",
    "FieldSelectors": [
      {"Field": "eventCategory", "Equals": ["Data"]},
      {"Field": "resources.type", "Equals": ["AWS::Bedrock::Guardrail"]}
    ]
  },
  {
    "Name": "Data events de knowledge bases",
    "FieldSelectors": [
      {"Field": "eventCategory", "Equals": ["Data"]},
      {"Field": "resources.type", "Equals": ["AWS::Bedrock::KnowledgeBase"]}
    ]
  }
]'

aws cloudtrail start-logging --name lab15-trail
aws cloudtrail get-trail-status --name lab15-trail --query IsLogging

--enable-log-file-validation genera ficheros de resumen firmados que permiten demostrar que los logs no se han alterado: un requisito clásico de auditoría.

Paso 5: generar tráfico etiquetado

Crea un guardrail sencillo, solo con un word filter (gratuito), para generar data events y métricas:

export GID=$(aws bedrock create-guardrail --name lab15-simple \
  --blocked-input-messaging "Petición bloqueada por la política de uso." \
  --blocked-outputs-messaging "Respuesta bloqueada por la política de uso." \
  --word-policy-config '{"wordsConfig":[{"text":"BancoRival"}]}' \
  --query guardrailId --output text)
sleep 10
aws bedrock get-guardrail --guardrail-identifier "$GID" --query status

Ahora invoca Nova Micro varias veces con requestMetadata, unas etiquetas clave-valor que Bedrock copia tal cual en cada registro de invocación. Son la base para atribuir consumo y responsabilidad por equipo, aplicación o caso de uso (trazabilidad).

cat > trafico.py <<'EOF'
import boto3

rt = boto3.client("bedrock-runtime", region_name="eu-central-1")
MODELO = "eu.amazon.nova-micro-v1:0"

peticiones = [
    ("atencion-cliente", "faq", "¿Cuál es el horario de atención telefónica?"),
    ("atencion-cliente", "faq", "Mi email es cliente.prueba@example.com, ¿podéis escribirme?"),
    ("riesgos", "resumen", "Resume en una frase qué es el riesgo de crédito."),
    ("riesgos", "resumen", "Resume en una frase qué es el riesgo de liquidez."),
    ("marketing", "borrador", "Escribe un eslogan de 8 palabras para una cuenta sin comisiones."),
]

for equipo, caso, texto in peticiones:
    r = rt.converse(
        modelId=MODELO,
        messages=[{"role": "user", "content": [{"text": texto}]}],
        inferenceConfig={"maxTokens": 120},
        requestMetadata={"equipo": equipo, "caso_uso": caso},
    )
    print(equipo, caso, r["usage"], "->", r["output"]["message"]["content"][0]["text"][:80])
EOF
python3 trafico.py

for i in 1 2 3 4 5 6; do
  aws bedrock-runtime apply-guardrail --guardrail-identifier "$GID" --guardrail-version DRAFT \
    --source INPUT --content '[{"text":{"text":"Me han dicho que BancoRival es mejor"}}]' \
    --query action --output text
done

Paso 6: auditar con CloudTrail

Busca en Event history las llamadas de gestión a Bedrock:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventSource,AttributeValue=bedrock.amazonaws.com \
  --max-results 10 \
  --query "Events[].{hora:EventTime,evento:EventName,usuario:Username}" --output table

Verás Converse, CreateGuardrail, PutModelInvocationLoggingConfiguration… Abre uno completo para ver qué se registra:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=Converse \
  --max-results 1 --query "Events[0].CloudTrailEvent" --output text | python3 -m json.tool

Fíjate: identidad (userIdentity), IP, modelId en requestParameters, región… pero ni el prompt ni la respuesta. Si usas un perfil de inferencia, CloudTrail también indica en qué región se procesó la petición.

Los data events de ApplyGuardrail no están aquí: llegan al bucket del trail en unos minutos (hasta unos 15). Compruébalo más tarde:

aws s3 ls "s3://${BUCKET_TRAIL}/AWSLogs/${CUENTA}/CloudTrail/eu-central-1/" --recursive | tail -5

Descarga el fichero más reciente y busca ApplyGuardrail: verás eventCategory Data, el recurso AWS::Bedrock::Guardrail y en responseElements la acción y los assessments, sin el texto evaluado.

Paso 7: auditar el contenido con Logs Insights

Espera un par de minutos a que lleguen los logs y lanza consultas de CloudWatch Logs Insights. Primero, consumo de tokens por identidad:

cat > consulta1.txt <<'EOF'
fields identity.arn as principal, input.inputTokenCount as entrada, output.outputTokenCount as salida
| stats sum(entrada) as tokensEntrada, sum(salida) as tokensSalida, count() as llamadas by principal
EOF

QID=$(aws logs start-query --log-group-name "$LOG_GROUP" \
  --start-time $(date -d '-1 hour' +%s) --end-time $(date +%s) \
  --query-string "$(cat consulta1.txt)" --query queryId --output text)
sleep 5
aws logs get-query-results --query-id "$QID" --query results --output json

Después, por equipo y caso de uso gracias a requestMetadata:

cat > consulta2.txt <<'EOF'
fields requestMetadata.equipo as equipo, requestMetadata.caso_uso as caso
| stats count() as llamadas, sum(input.inputTokenCount) as entrada, sum(output.outputTokenCount) as salida by equipo, caso
| sort entrada desc
EOF

QID=$(aws logs start-query --log-group-name "$LOG_GROUP" \
  --start-time $(date -d '-1 hour' +%s) --end-time $(date +%s) \
  --query-string "$(cat consulta2.txt)" --query queryId --output text)
sleep 5
aws logs get-query-results --query-id "$QID" --query results --output json

Por último, comprueba el enmascarado: busca el registro con el email.

QID=$(aws logs start-query --log-group-name "$LOG_GROUP" \
  --start-time $(date -d '-1 hour' +%s) --end-time $(date +%s) \
  --query-string 'fields @timestamp, @message | filter @message like /escribirme/ | limit 1' \
  --query queryId --output text)
sleep 5
aws logs get-query-results --query-id "$QID" --query "results[0]" --output json | head -c 1500

El email aparece enmascarado con asteriscos. En el objeto equivalente de S3 (bajo invocaciones/AWSLogs/...), en cambio, estará en claro.

Paso 8: alerta automática ante intervenciones del guardrail

Un pico de intervenciones puede indicar un usuario intentando jailbreaks o una fuga de datos. Crea un tema SNS y una alarma sobre InvocationsIntervened en el namespace AWS/Bedrock/Guardrails:

export TOPIC=$(aws sns create-topic --name lab15-alertas-ia --query TopicArn --output text)
# Opcional: recibe el aviso por correo (confirma la suscripción en tu email)
# aws sns subscribe --topic-arn "$TOPIC" --protocol email --notification-endpoint tu-correo@example.com

aws cloudwatch put-metric-alarm \
  --alarm-name lab15-intervenciones-guardrail \
  --alarm-description "Demasiadas intervenciones del guardrail en 5 minutos" \
  --namespace AWS/Bedrock/Guardrails \
  --metric-name InvocationsIntervened \
  --dimensions Name=Operation,Value=ApplyGuardrail \
  --statistic Sum --period 300 --evaluation-periods 1 \
  --threshold 5 --comparison-operator GreaterThanOrEqualToThreshold \
  --treat-missing-data notBreaching \
  --alarm-actions "$TOPIC"

aws cloudwatch describe-alarms --alarm-names lab15-intervenciones-guardrail \
  --query "MetricAlarms[0].StateValue"

Con las seis intervenciones del paso 5, la alarma debería pasar a ALARM en unos minutos. Si se queda en INSUFFICIENT_DATA, es que la métrica se publica con otra combinación de dimensiones: ejecuta aws cloudwatch list-metrics --namespace AWS/Bedrock/Guardrails --metric-name InvocationsIntervened y recrea la alarma con las dimensiones exactas que aparezcan. En producción, el tema SNS podría disparar una Lambda de remediación (por ejemplo, revocar temporalmente la sesión del usuario o abrir un ticket).

Paso 9: documentar el modelo con una model card

Las SageMaker model cards documentan en un solo lugar el propósito, los usos previstos y no previstos, la valoración de riesgo, las evaluaciones y las consideraciones éticas de un modelo. Cada edición (salvo el cambio de estado) crea una versión nueva, lo que deja un registro inmutable, y se pueden exportar a PDF para auditores. Aunque nacieron para modelos entrenados en SageMaker AI, sirven para documentar el uso de un modelo fundacional de Bedrock en tu aplicación.

cat > tarjeta.json <<'EOF'
{
  "model_overview": {
    "model_description": "Uso de Amazon Nova Micro (perfil eu.amazon.nova-micro-v1:0) para responder preguntas frecuentes de clientes de BancoLab.",
    "model_creator": "Amazon (modelo fundacional en Amazon Bedrock)",
    "model_owner": "Equipo de atención al cliente de BancoLab",
    "problem_type": "Generación de texto"
  },
  "intended_uses": {
    "purpose_of_model": "Responder preguntas frecuentes no personalizadas sobre productos y horarios.",
    "intended_uses": "FAQ con fuentes internas mediante RAG y guardrail obligatorio. No apto para asesoramiento financiero, decisiones de crédito ni datos personales sin anonimizar.",
    "factors_affecting_model_efficiency": "Calidad y actualidad de los documentos recuperados; idioma; longitud del contexto.",
    "risk_rating": "Medium",
    "explanations_for_risk_rating": "Contacto directo con clientes; riesgo de alucinaciones mitigado con contextual grounding y revisión humana de reclamaciones."
  },
  "additional_information": {
    "ethical_considerations": "Se evalúa periódicamente el sesgo en las respuestas por idioma y perfil de cliente. El usuario es informado de que habla con un sistema de IA.",
    "caveats_and_recommendations": "Puede generar información incorrecta. Mostrar siempre las fuentes citadas y ofrecer paso a un agente humano."
  }
}
EOF

aws sagemaker create-model-card \
  --model-card-name lab15-faq-nova-micro \
  --model-card-status Draft \
  --content file://tarjeta.json

aws sagemaker update-model-card \
  --model-card-name lab15-faq-nova-micro \
  --model-card-status PendingReview

aws sagemaker describe-model-card --model-card-name lab15-faq-nova-micro \
  --query "{estado:ModelCardStatus,version:ModelCardVersion,creada:CreationTime}"

El flujo Draft → PendingReview → Approved (→ Archived) es tu proceso de aprobación: puedes exigir que ninguna aplicación pase a producción sin una model card aprobada, y comprobarlo en el pipeline de CI/CD.

Comprueba que funciona

  • get-model-invocation-logging-configuration muestra los dos destinos y solo texto activado.
  • En el log group aparecen registros con schemaType ModelInvocationLog, modelId, identity.arn, requestMetadata y recuento de tokens.
  • El email del paso 5 aparece enmascarado en CloudWatch Logs.
  • lookup-events muestra eventos Converse sin contenido del prompt, y el bucket del trail acaba recibiendo data events ApplyGuardrail.
  • Las consultas de Logs Insights agregan tokens por identidad y por equipo.
  • La alarma existe y pasa a ALARM tras las intervenciones.
  • La model card está en PendingReview.

Limpieza

En este orden:

cd ~/lab15

# 1. Dejar de registrar invocaciones
aws bedrock delete-model-invocation-logging-configuration

# 2. CloudTrail
aws cloudtrail stop-logging --name lab15-trail
aws cloudtrail delete-trail --name lab15-trail

# 3. Alarma y SNS
aws cloudwatch delete-alarms --alarm-names lab15-intervenciones-guardrail
aws sns delete-topic --topic-arn "$TOPIC"

# 4. Model card y guardrail
aws sagemaker delete-model-card --model-card-name lab15-faq-nova-micro
aws bedrock delete-guardrail --guardrail-identifier "$GID"

# 5. Política de protección de datos y log group
aws logs delete-data-protection-policy --log-group-identifier "$LOG_GROUP"
aws logs delete-log-group --log-group-name "$LOG_GROUP"

# 6. Rol de logging
aws iam delete-role-policy --role-name lab15-bedrock-logging --policy-name escribir-logs
aws iam delete-role --role-name lab15-bedrock-logging

# 7. Vaciar y borrar buckets
aws s3 rm "s3://${BUCKET_LOGS}" --recursive
aws s3api delete-bucket --bucket "$BUCKET_LOGS"
aws s3 rm "s3://${BUCKET_TRAIL}" --recursive
aws s3api delete-bucket --bucket "$BUCKET_TRAIL"

cd ~ && rm -rf ~/lab15

Si antes del lab tenías tu propia configuración de invocation logging, vuelve a aplicarla con put-model-invocation-logging-configuration.

Preguntas para pensar como arquitecto

  1. Un regulador pide conservar durante cinco años, de forma inalterable, todas las preguntas y respuestas de un chatbot, pero el equipo de soporte no debe ver datos personales. ¿Qué diseñas?
Respuesta

Model invocation logging a S3 con cifrado SSE-KMS de clave propia, S3 Object Lock en modo compliance y reglas de ciclo de vida hacia clases de almacenamiento baratas; acceso a ese bucket solo para el rol de auditoría. Para el día a día, el destino de CloudWatch Logs con retención corta y una data protection policy que enmascare PII, sin conceder logs:Unmask al equipo de soporte. CloudTrail con validación de integridad para demostrar quién accedió y cambió la configuración.

  1. Finanzas quiere saber cuánto gasta en tokens cada unidad de negocio que comparte la misma cuenta y el mismo rol. ¿Qué harías?
Respuesta

Añadir requestMetadata (unidad de negocio, aplicación, caso de uso) en cada llamada desde la capa de acceso común (por ejemplo, la Lambda del gateway de IA) y agregar los tokens por esas claves con Logs Insights o Athena sobre los logs de invocación. Si cada unidad usara su propio rol, bastaría agrupar por identity.arn.

  1. Tras un incidente, necesitas saber quién desactivó un guardrail el martes por la noche y si después hubo respuestas dañinas. ¿Qué fuentes cruzas?
Respuesta

CloudTrail (evento de gestión UpdateGuardrail o DeleteGuardrail, con identidad, IP y hora; GuardDuty también puede señalar este tipo de actividad sospechosa) y, para el contenido posterior, los model invocation logs de esa franja. Las métricas de AWS/Bedrock/Guardrails muestran la caída de intervenciones.

  1. ¿Por qué no basta con activar CloudTrail para cumplir un requisito de «trazabilidad de las decisiones del modelo»?
Respuesta

Porque CloudTrail no guarda el contenido: sabes que alguien llamó a Converse, pero no qué pidió, qué fuentes se usaron ni qué respondió el modelo. Hacen falta los model invocation logs (entrada, salida, tokens), las citas de las fuentes en RAG, las trazas de agentes y la documentación del modelo (model card) para reconstruir y justificar una decisión.


Volver al módulo