La proliferación de aplicaciones de Generative AI (GenAI) en entornos empresariales presenta un desafío fundamental en la computación distribuida: cómo gestionar el acceso a la información sensible de manera granular y escalable en un contexto multi-inquilino o multi-departamento. Específicamente, en arquitecturas de Retrieval Augmented Generation (RAG), donde los Large Language Models (LLMs) acceden a bases de conocimiento propietarias, es crítico asegurar que los usuarios solo recuperen documentos a los que están autorizados. Este problema se agrava cuando las reglas de acceso son dinámicas y requieren actualizaciones frecuentes, lo que tradicionalmente implicaría ciclos de desarrollo y despliegue. La solución propuesta aborda esto externalizando la lógica de autorización a un sistema de políticas centralizado, desacoplando la decisión de acceso del código de la aplicación y permitiendo una gestión ágil y auditable.

Históricamente, la gestión de permisos ha evolucionado desde listas de control de acceso (ACLs) estáticas hasta modelos de Role-Based Access Control (RBAC) y, más recientemente, Attribute-Based Access Control (ABAC). Este patrón se alinea con ABAC al evaluar atributos del usuario (grupos de departamento) y del recurso (documentos con metadatos) en tiempo de ejecución. La necesidad de un control de acceso dinámico y de bajo costo para RAG surge de la complejidad operacional y económica de provisionar infraestructuras de RAG aisladas para cada grupo o departamento, un problema que se intensifica con el crecimiento de la adopción de GenAI en la empresa.

Arquitectura del Sistema

La arquitectura propuesta implementa un patrón de autorización de defensa en profundidad con dos capas independientes. La primera capa (Layer 1) es un Lambda Authorizer en Amazon API Gateway que valida el JSON Web Token (JWT) del usuario (emitido por Amazon Cognito) y consulta Amazon Verified Permissions para determinar si el usuario tiene permiso para invocar la API. Esta es una verificación de acceso a nivel de API.

La segunda capa (Layer 2) es una AWS Lambda function de middleware que, tras la autorización de la Layer 1, realiza una segunda consulta a Amazon Verified Permissions. Esta consulta determina a qué recursos de Amazon Bedrock Knowledge Bases (identificados por metadatos de departamento) el usuario está autorizado a acceder. Basándose en esta decisión, la Lambda construye un filtro de metadatos que se pasa a la API RetrieveAndGenerate de Amazon Bedrock. Este filtro asegura que Amazon Bedrock Knowledge Bases solo realice la búsqueda de similitud vectorial y la recuperación de documentos sobre un subconjunto autorizado de la base de conocimiento. La ingesta de documentos se realiza a través de un pipeline event-driven: los documentos subidos a Amazon S3 bajo prefijos de departamento (ej. docs/dept-a/) disparan eventos de Amazon EventBridge, que a través de Amazon SQS, invocan una Lambda que crea un archivo sidecar .metadata.json con el tag de departamento. Una Lambda programada periódicamente inicia el trabajo de ingestión en Amazon Bedrock Knowledge Bases, que indexa los documentos y sus metadatos. Amazon Verified Permissions utiliza Cedar, un lenguaje de políticas declarativo, para definir las reglas de autorización, que son evaluadas en tiempo real. Guardrails for Amazon Bedrock actúa como una capa de seguridad de salida, validando la respuesta del FM para asegurar que se mantenga fiel al contexto recuperado y filtre contenido inapropiado.

Flujo de Ingestión de Documentos con Metadatos

  1. 1 S3 Upload Documento subido a S3 con prefijo de departamento (ej. docs/dept-a/)
  2. 2 EventBridge Dispara evento ObjectCreated en S3
  3. 3 SQS Queue Buffer para cargas masivas y reintentos
  4. 4 Metadata Tagging Lambda Crea archivo .metadata.json sidecar con tag de departamento
  5. 5 EventBridge Scheduler Dispara Lambda de ingestión cada 5 minutos
  6. 6 Ingestion Lambda Llama StartIngestionJob en Bedrock Knowledge Bases
  7. 7 Bedrock Knowledge Bases Lee documentos y sidecars, chunks, embeddings, indexa vectores con metadatos

Flujo de Consulta con Autorización de Doble Capa

  1. 1 User Request Consulta con JWT a través de CloudFront y WAF
  2. 2 API Gateway Enruta la solicitud
  3. 3 Lambda Authorizer (Layer 1) Valida JWT, consulta Verified Permissions para autorización de API
  4. 4 Middleware Lambda (Layer 2) Consulta Verified Permissions para autorización de documentos (qué departamen...
  5. 5 Middleware Lambda (Layer 2) Construye filtro de metadatos basado en decisión de política
  6. 6 Bedrock RetrieveAndGenerate Aplica filtro de metadatos, realiza búsqueda vectorial y generación de FM
  7. 7 Guardrails for Bedrock Valida la respuesta del FM (fidelidad contextual, filtrado de contenido)
  8. 8 Response to User Respuesta final
CapaTecnologíaJustificación
orchestration AWS Lambda Funciones serverless para el Lambda Authorizer (Layer 1), la lógica de middleware (Layer 2) y el pipeline de ingestión de metadatos. vs Amazon ECS Fargate, Amazon EC2 Python 3.12 runtime, variables de entorno para IDs de servicios.
security Amazon Verified Permissions Motor de decisión de políticas externo para autorización granular a nivel de API y documento, utilizando el lenguaje Cedar. vs AWS IAM Policies (directamente en recursos), Open Policy Agent (OPA) Almacén de políticas con esquema Cedar definido para Principals, Actions, Resources.
data-processing Amazon Bedrock Knowledge Bases Servicio RAG gestionado que maneja la ingesta, chunking, generación de embeddings, indexación vectorial y recuperación con filtrado de metadatos. vs OpenSearch Service (para vector store), Pinecone, Weaviate Chunking de 300 tokens con 20% de solapamiento, uso de Titan Text Embeddings V2.
storage Amazon S3 Almacenamiento de documentos brutos y archivos sidecar de metadatos, fuente de datos para Bedrock Knowledge Bases. vs Amazon EFS, Amazon FSx Versioning habilitado, políticas IAM para restringir s3:PutObject a la Lambda de tagging.
networking Amazon API Gateway Endpoint para la aplicación RAG, integra el Lambda Authorizer para la Layer 1 de autorización. vs Application Load Balancer (ALB) Lambda Authorizer (TOKEN type), TTL de caché del authorizer configurado para producción.
messaging Amazon SQS Cola de mensajes para amortiguar picos de carga en la ingesta de documentos y gestionar reintentos/DLQ. vs Amazon Kinesis Data Streams Ventana de batching de 30 segundos para procesar cargas masivas.
observability Amazon CloudWatch Monitoreo de logs, métricas y alarmas para decisiones de autorización, latencia de Verified Permissions, y fallos de ingestión. vs Datadog, Splunk Filtros de métricas para tasas de denegación, latencia y mensajes en DLQ.
security Amazon Cognito Servicio de identidad para gestionar usuarios y emitir JWTs con claims de grupo de departamento. vs Okta, Microsoft Entra ID Pools de usuarios configurados con grupos basados en departamentos (ej. dept-a, dept-b).
security AWS WAF Firewall de aplicaciones web para protección contra ataques comunes, rate limiting y filtrado de IP. vs Cloudflare, Akamai
security Guardrails for Amazon Bedrock Capa de seguridad de salida para validar las respuestas del FM, asegurando fidelidad contextual y filtrado de contenido. vs Lógica de filtrado personalizada post-generación Configuración de contextual grounding y content filtering en la llamada RetrieveAndGenerate.

Trade-offs

Ganancias
  • Flexibilidad en la gestión de políticas de acceso
  • Reducción de costos y complejidad operacional
  • Seguridad mejorada con defensa en profundidad
  • Auditoría detallada de decisiones de autorización
Costes
  • Dependencia de Amazon Verified Permissions para ambas capas de autorización
  • Latencia adicional por llamadas a Verified Permissions (especialmente con TTL=0)
  • Aislamiento lógico (no físico) de documentos
import os
import json
import jwt
import requests
from botocore.exceptions import ClientError
import boto3

# ... (JWKS caching, helper functions for JWT validation and Verified Permissions call)

def lambda_handler(event, context):
    token = event['authorizationToken'].split(' ')[1]
    try:
        # 1. Validate JWT signature and claims (e.g., cognito:groups)
        # 2. Extract user groups from JWT
        # 3. Call Verified Permissions IsAuthorized API
        #    principal = GenAIApp::UserGroup::"dept-a"
        #    action = GenAIApp::Action::"invokeApi"
        #    resource = GenAIApp::Resource::"GenAIRAGApp"
        # 4. If authorized, return IAM policy allowing access
        # 5. Else, raise exception for 403
        pass # Placeholder for actual implementation
    except Exception as e:
        print(f"Authorization failed: {e}")
        raise Exception('Unauthorized') # API Gateway returns 403
Lógica de un Lambda Authorizer que valida un JWT y llama a Amazon Verified Permissions para una decisión de autorización de API.
import os
import json
import boto3

# ... (helper functions for Verified Permissions call)

def lambda_handler(event, context):
    user_groups = event['requestContext']['authorizer']['claims']['cognito:groups'] # From Layer 1
    policy_store_id = os.environ['POLICY_STORE_ID']
    kb_id = os.environ['KB_ID']

    permitted_departments = []
    # 1. For each user_group, call Verified Permissions IsAuthorized
    #    action = GenAIApp::Action::"query"
    #    resource = GenAIApp::KnowledgeBase::"dept-X"
    # 2. Collect all 'dept-X' resources for which the user_group is permitted
    # 3. Construct metadata filter
    if not permitted_departments:
        raise PermissionError("No authorized departments found.")

    metadata_filter = {
        "or": [
            {"equals": {"key": "department", "value": dept}} 
            for dept in permitted_departments
        ]
    }

    # 4. Call Bedrock RetrieveAndGenerate with metadata_filter and guardrailConfiguration
    #    response = bedrock_runtime.retrieve_and_generate(
    #        input={'text': event['body']['query']},
    #        retrieveAndGenerateConfiguration={
    #            'type': 'KNOWLEDGE_BASE',
    #            'knowledgeBaseConfiguration': {
    #                'knowledgeBaseId': kb_id,
    #                'modelArn': '...', # Determined by Verified Permissions for invokeModel
    #                'retrievalConfiguration': {'vectorSearchConfiguration': {'filter': metadata_filter}}
    #            }
    #        },
    #        guardrailConfiguration={'guardrailId': '...', 'guardrailVersion': 'DRAFT'}
    #    )
    # 5. Return response
    pass # Placeholder for actual implementation
Lógica de una Lambda de middleware que consulta Verified Permissions para determinar los permisos de acceso a documentos y construye un filtro de metadatos para Bedrock RetrieveAndGenerate.

Fundamentos Teóricos

El concepto de externalización de la lógica de autorización, como se implementa con Amazon Verified Permissions y Cedar, tiene sus raíces en los sistemas de gestión de políticas y los motores de decisión de políticas (PDP - Policy Decision Point) que han sido objeto de estudio en la seguridad informática durante décadas. Este enfoque se alinea con el principio de separación de preocupaciones (Separation of Concerns), donde la lógica de negocio se desacopla de la lógica de seguridad. La formalización de políticas de acceso mediante lenguajes declarativos como Cedar se inspira en trabajos sobre lenguajes de políticas de seguridad como XACML (eXtensible Access Control Markup Language), que buscan proporcionar una forma estructurada y auditable de definir y aplicar reglas de acceso complejas.

La estrategia de "defensa en profundidad" (Defense in Depth) es un principio de seguridad bien establecido, popularizado por el NIST (National Institute of Standards and Technology) y otras organizaciones de seguridad, que aboga por múltiples capas de controles de seguridad independientes. Este patrón aplica este principio al tener capas de autorización a nivel de API y a nivel de documento, asegurando que un fallo o una configuración errónea en una capa no comprometa la seguridad general. La aplicación de filtros de metadatos antes de la búsqueda vectorial en RAG es una adaptación de las técnicas de pre-filtrado y post-filtrado en sistemas de recuperación de información, donde los criterios de acceso se aplican para reducir el espacio de búsqueda o para refinar los resultados antes de su presentación al usuario.