Última revisión: mayo de 2026
Crea los servicios de AWS del examen AIF-C01 con Terraform puro: bloque a bloque, cada uno vinculado a un dominio del examen. El mismo código funciona en OpenTofu.
Al final de este laboratorio habrás aprovisionado, con Terraform puro, una configuración funcional de Amazon Bedrock que demuestra cuatro de los cinco dominios del examen AIF-C01: un almacén de Amazon S3 para entradas y salidas de IA, un rol de AWS IAM de mínimo privilegio que Amazon Bedrock puede asumir para invocar modelos fundacionales, una barrera de protección (guardrail) que filtra las instrucciones (prompts) y respuestas para garantizar la seguridad y proteger la PII (información de identificación personal), y el registro de invocaciones a nivel de cuenta y región.
Cada recurso es Terraform puro; el mismo código funciona sin modificaciones en OpenTofu. No hay variables, ni módulos, ni estado remoto. Coloca los siguientes fragmentos en un único archivo main.tf, ejecuta terraform init una vez y luego aplica terraform apply paso a paso.
>= 1.5 o OpenTofu >= 1.6.us-east-1 de forma predeterminada porque Amazon Bedrock y sus modelos fundacionales más recientes se lanzan allí primero).La mayoría de los recursos en este laboratorio no cuestan nada mientras estén inactivos: los roles de AWS IAM, la configuración de la barrera de protección (guardrail), la configuración de registro, un bucket de Amazon S3 vacío y un grupo de logs de Amazon CloudWatch Logs sin eventos son completamente gratuitos.
Conceptos de facturación que podrías ver si realmente utilizas el laboratorio:
Lo que omitimos intencionadamente: el laboratorio no crea una Amazon Bedrock Knowledge Base (base de conocimientos). Las bases de conocimientos requieren una colección de Amazon OpenSearch Serverless que factura un mínimo aproximado de ~$350 al mes mientras está inactiva. Esto queda deliberadamente fuera del alcance aquí; consulta la página de la certificación AIF-C01 si deseas estudiar las bases de conocimientos a nivel conceptual sin aprovisionar una.
Antes de crear cualquier recurso, debemos indicarle a Terraform qué versión de sí mismo esperamos y qué proveedor de AWS utilizaremos. Fijamos el proveedor de AWS en ~> 5.60 porque cada recurso relacionado con Amazon Bedrock que tocamos en este laboratorio se introdujo en esa línea, y desplegamos todo en us-east-1 (AWS lanza primero los modelos fundacionales allí, y la mayoría de las preguntas del AIF-C01 asumen la disponibilidad en us-east-1 cuando hacen referencia a un servicio “más nuevo”).
Agrega esto en un archivo main.tf nuevo para comenzar. Todo lo que sigue en el laboratorio se ubicará en este mismo archivo.
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
provider "aws" {
region = "us-east-1"
}Cada servicio de IA de AWS que utilizaremos en este laboratorio — Amazon Bedrock hoy, y el registro de auditoría que conectaremos en el Paso 5 — lee entradas y escribe salidas a través de Amazon S3, por lo que la primera pieza de infraestructura real es un bucket. Volveremos a él en casi todos los pasos posteriores.
Activamos el control de versiones para que se pueda revertir una carga corrupta, bloqueamos el acceso público (se trata de entradas de entrenamiento y logs de invocación de modelos, no de recursos de un sitio web) y habilitamos el cifrado AES256 en reposo. Este último punto es importante para el examen AIF-C01: el dominio Security, Compliance, and Governance for AI Solutions (Seguridad, conformidad y gobernanza para soluciones de IA) evalúa explícitamente que recurras al cifrado en reposo por defecto en cualquier almacén de datos de IA.
resource "aws_s3_bucket" "ai_data" {
bucket_prefix = "certlabpro-aif-c01-"
}
resource "aws_s3_bucket_public_access_block" "ai_data" {
bucket = aws_s3_bucket.ai_data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_versioning" "ai_data" {
bucket = aws_s3_bucket.ai_data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "ai_data" {
bucket = aws_s3_bucket.ai_data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}Amazon Bedrock no puede invocar un modelo por sí solo: necesita un rol de AWS IAM que pueda asumir. Creamos uno con una política de confianza que nombra a bedrock.amazonaws.com como el único principal permitido, y luego adjuntamos una política de permisos mínimos: invocar cualquier modelo fundacional y leer/escribir únicamente en el bucket que creamos en el Paso 2.
Los patrones de mínimo privilegio como este son un tema recurrente en el AIF-C01. Ten en cuenta que no otorgamos s3:*, sino solo las dos acciones de objetos que realmente necesitamos, limitadas a los objetos dentro de nuestro bucket. El examen premia el identificar esa misma estructura en escenarios de opción múltiple: cuando ambas opciones de respuesta “funcionan”, la más restringida casi siempre es la correcta.
resource "aws_iam_role" "bedrock_caller" {
name = "certlabpro-aif-c01-bedrock-caller"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "bedrock.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "bedrock_caller" {
name = "bedrock-invoke"
role = aws_iam_role.bedrock_caller.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
]
Resource = "arn:aws:bedrock:*::foundation-model/*"
},
{
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:PutObject",
]
Resource = "${aws_s3_bucket.ai_data.arn}/*"
},
]
})
}Un modelo de Amazon Bedrock por sí solo responderá gustosamente cualquier cosa que sus datos de entrenamiento le permitan responder. Las barreras de protección (Guardrails) se sitúan delante de cada llamada al modelo y aplican políticas de contenido y PII de forma independiente al modelo fundacional que utilices, lo que significa que un único guardrail cubre Claude, Llama, Titan y cualquier modelo futuro.
Aquí configuramos dos capas. Un filtro de contenido bloquea el odio, la violencia y el contenido sexual de alta gravedad tanto en las instrucciones como en las respuestas, y una política de información sensible bloquea la filtración de correos electrónicos, números de teléfono y números de Seguro Social de EE. UU. Estos se asignan directamente al dominio Guidelines for Responsible AI (Directrices para una IA responsable) de la certificación AIF-C01, donde el filtrado de contenido y el manejo de PII son los dos pilares fundamentales.
Con la barrera de protección en su lugar, el rol que creamos en el Paso 3 puede invocar un modelo y el resultado se filtra antes de que llegue al cliente que realiza la llamada.
resource "aws_bedrock_guardrail" "safety" {
name = "certlabpro-aif-c01-safety"
description = "Default safety rails for the lab."
blocked_input_messaging = "I can't help with that."
blocked_outputs_messaging = "I can't share that response."
content_policy_config {
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "HATE"
}
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "VIOLENCE"
}
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "SEXUAL"
}
}
sensitive_information_policy_config {
pii_entities_config {
action = "BLOCK"
type = "EMAIL"
}
pii_entities_config {
action = "BLOCK"
type = "PHONE"
}
pii_entities_config {
action = "BLOCK"
type = "US_SOCIAL_SECURITY_NUMBER"
}
}
}El registro de invocaciones de Amazon Bedrock captura la instrucción completa, la respuesta y la carga útil de incrustación (embedding) de cada llamada al modelo en la cuenta y región. Escribe en Amazon CloudWatch Logs (ideal para búsquedas rápidas con grep) y en Amazon S3 (ideal para retención a largo plazo); configuramos ambos. El rol que asociamos otorga exactamente las acciones que el servicio de Amazon Bedrock necesita y nada más.
Un detalle relevante para el examen AIF-C01 que vale la pena conocer: el registro de invocaciones es un recurso único (singleton), es decir, una configuración por cuenta por región. Si ejecutas este laboratorio por segunda vez en us-east-1, Terraform informará que no hay cambios, pero la configuración existente se volverá a vincular. Destruye la infraestructura antes de volver a ejecutarla si alguna vez cambias los destinos de los logs.
Con el registro configurado, cada llamada al modelo que realicemos utilizando el rol del Paso 3, a través de la barrera de protección del Paso 4, termina archivada en el bucket del Paso 2. Esa es la cadena de auditoría completa, exactamente el tipo de escenario de “muéstrame la evidencia” que el examen espera que seas capaz de describir.
resource "aws_iam_role" "bedrock_logging" {
name = "certlabpro-aif-c01-bedrock-logging"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "bedrock.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_cloudwatch_log_group" "bedrock_invocations" {
name = "/aws/bedrock/invocations"
retention_in_days = 30
}
resource "aws_iam_role_policy" "bedrock_logging" {
name = "write-logs-and-s3"
role = aws_iam_role.bedrock_logging.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents",
]
Resource = aws_cloudwatch_log_group.bedrock_invocations.arn
},
{
Effect = "Allow"
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.ai_data.arn}/bedrock-invocations/*"
},
]
})
}
resource "aws_bedrock_model_invocation_logging_configuration" "this" {
logging_config {
embedding_data_delivery_enabled = true
image_data_delivery_enabled = true
text_data_delivery_enabled = true
cloudwatch_config {
log_group_name = aws_cloudwatch_log_group.bedrock_invocations.name
role_arn = aws_iam_role.bedrock_logging.arn
}
s3_config {
bucket_name = aws_s3_bucket.ai_data.bucket
key_prefix = "bedrock-invocations/"
}
}
}Un comando terraform destroy estándar elimina todo en este laboratorio. Dos notas:
aws_bedrock_model_invocation_logging_configuration tiene alcance de cuenta y región; destruirlo desactivará el registro globalmente en us-east-1. Si otra carga de trabajo también depende de esa configuración, te convendrá omitir este paso o coordinarlo.force_destroy = false significa que el comando destroy fallará si queda algún objeto (incluidos los marcadores de eliminación). Vacía el bucket a través de la consola antes de destruirlo, o bien establece force_destroy = true en el recurso del bucket y vuelve a aplicar el código antes de la destrucción.El examen AIF-C01 cubre una amplia gama de servicios de IA de AWS — Rekognition, Comprehend, Textract, Polly, Translate, Transcribe, Lex, SageMaker, Kendra, Personalize y Q. Decidimos deliberadamente no aprovisionarlos en este laboratorio.
La razón no es que no sean importantes, sino que la práctica real con estos servicios o bien no requiere ninguna infraestructura (Textract, Comprehend y Rekognition son puras llamadas de API sobre datos existentes en S3), utiliza recursos que no existen en el proveedor de AWS para Terraform (léxicos de Polly, terminologías de Translate, Amazon Q) o consume dinero mientras están inactivos (Bedrock Knowledge Bases, Kendra, dominios de SageMaker).
Para esos servicios, las secciones Navegar, Guía y Editorial de esta página de certificación contienen la cobertura conceptual que necesitará para el examen. El valor práctico se centra en lo que es más difícil de asimilar sin hacerlo uno mismo: el plano de control de IAM, guardrail y registro de Bedrock.