CLOUD 18 min

Serverless Seguro en AWS: Cognito, API Gateway y Lambda

Diseña y despliega una arquitectura Serverless empresarial en AWS. Profundizamos en User Pools de Cognito, autorizadores en API Gateway, gestión de estado en Lambda y mitigación de Cold Starts.

Escrito por Samir El Azem Crovetto • Senior Backend Engineer & DevSecOps

El Paradigma Serverless y su Superficie de Ataque en Producción

El modelo de computación Serverless en Amazon Web Services (AWS) —articulado en torno a AWS Lambda, Amazon API Gateway y Amazon Cognito— traslada la responsabilidad del mantenimiento del sistema operativo, el escalado horizontal y la infraestructura física al proveedor de nube. Sin embargo, abstraer la gestión de servidores no elimina las responsabilidades de seguridad; al contrario, transforma el modelo de amenazas hacia la capa de aplicación, la gestión de identidades y la configuración de permisos entre servicios.

En una arquitectura serverless tradicional mal configurada, surgen vectores de ataque críticos:

  • *Roles IAM con sobreprivilegios (Overprivileged Functions): Funciones Lambda a las que se asigna la política AdministratorAccess o permisos comodín () sobre DynamoDB, S3 o KMS. Si la función sufre una inyección de código o deserialización insegura, el atacante asume el control del entorno cloud.
  • *Inyección en Eventos (Event Injection):* A diferencia de las aplicaciones web monolíticas que reciben solicitudes HTTP tradicionales, las funciones Lambda son activadas por múltiples fuentes de eventos: payloads JSON de API Gateway, mensajes de colas SQS, streams de DynamoDB o eventos de EventBridge. Tratar los datos del evento sin saneamiento estricto conduce a inyecciones SQL, NoSQL o de comandos.
  • Filtración de Secretos en Variables de Entorno: Almacenar tokens de API, contraseñas de bases de datos o claves privadas directamente como variables de entorno de Lambda en texto plano, haciéndolas visibles en la consola de AWS, en llamadas a la API GetFunction y en logs de despliegue.
  • *Agotamiento de Concurrencia y Facturación (Denial of Wallet):* Ausencia de cuotas de concurrencia reservada y ausencia de rate-limiting en la pasarela, permitiendo a un atacante saturar la cuenta de AWS y generar costes imprevistos abusando de la escala automática.

Construir una arquitectura serverless robusta exige aplicar el principio de Zero Trust desde el borde de la red (Edge) hasta la capa de ejecución de cómputo.


Arquitectura de Referencia: Flujo de Autorización y Ejecución

La arquitectura recomendada integra AWS WAF para inspección perimetral, Amazon Cognito para gestión de identidades y emisión de tokens OIDC, Amazon API Gateway con validación nativa de JWT en el borde, funciones AWS Lambda ejecutadas bajo roles IAM de mínimo privilegio y AWS Secrets Manager para inyección segura de credenciales:

sequenceDiagram
    autonumber
    actor Client as Cliente Web / Móvil
    participant Cognito as Amazon Cognito User Pool
    participant WAF as AWS WAF (Rate Limiting)
    participant APIGW as Amazon API Gateway (Authorizer)
    participant Lambda as AWS Lambda (Least Privilege)
    participant Secrets as AWS Secrets Manager
    participant DB as Amazon DynamoDB

    Client->>Cognito: Autenticación PKCE (OAuth 2.1)
    Cognito-->>Client: Emisión de JWT (id_token + access_token)
    Client->>WAF: Solicitud HTTPS con Bearer Token
    WAF->>APIGW: Tráfico filtrado (Anti-DDoS e inspección)
    Note over APIGW: Validación JWT en el Edge:<br/>Firma criptográfica, Expiración, Emisor y Scopes
    alt Token Inválido o Expirado
        APIGW-->>Client: HTTP 401 Unauthorized (Sin coste Lambda)
    else Token Válido
        APIGW->>Lambda: Invocación con Contexto de Identidad (Claims)
        Lambda->>Secrets: Obtener credenciales (Caché local en memoria)
        Secrets-->>Lambda: Clave descifrada vía KMS
        Lambda->>DB: Operación CRUD (Permiso IAM estricto por ARN)
        DB-->>Lambda: Resultado de datos
        Lambda-->>APIGW: Payload de respuesta JSON
        APIGW-->>Client: HTTP 200 OK con datos
    end

1. Amazon Cognito User Pools: Gestión de Identidades y Tokens OIDC

Amazon Cognito User Pools actúa como el Proveedor de Identidad (IdP) conforme a OAuth 2.1 y OpenID Connect (OIDC), facilitando el registro seguro de usuarios, autenticación multifactor (MFA), verificación por correo electrónico/SMS y políticas estrictas de contraseñas.

Flujo Seguro de Autenticación con PKCE

En clientes web y aplicaciones móviles (Single Page Applications o apps nativas), el único flujo de autenticación autorizado es el Authorization Code Flow con PKCE (Proof Key for Code Exchange), tal como detallamos en la guía sobre autenticación y autorización moderna. Se prohíbe el uso del obsoleto flujo implícito (Implicit Grant), que exponía los tokens en los fragmentos de la URL del navegador.

Anatomía de los Tokens JWT de Cognito

Tras autenticar satisfactoriamente al usuario, Cognito emite tres tokens:

  1. ID Token (idtoken): Contiene claims de identidad del usuario (sub, email, cognito:groups, preferredusername). Diseñado exclusivamente para el consumo por parte de la aplicación cliente frontend.
  2. Access Token (access_token): Contiene el identificador del sujeto (sub), alcances (scopes OAuth como aws.cognito.signin.user.admin o scopes personalizados), y metadatos de autorización. Este es el token que debe enviarse en la cabecera Authorization: Bearer <token> hacia las APIs protegidas.
  3. Refresh Token (refresh_token): Token de larga duración almacenado en cookies HttpOnly para renovar el par de tokens sin requerir que el usuario vuelva a ingresar credenciales.

2. Amazon API Gateway: Hardening y Autorización en el Borde

Delegar la validación del token JWT al código de la función Lambda es un antipatrón grave: cada solicitud no autorizada incurriría en costes de cómputo y latencia de invocación. API Gateway debe interceptar y validar las credenciales criptográficas antes de activar cualquier recurso de cómputo.

Cognito User Pool Authorizer vs. Lambda Authorizer

API Gateway ofrece dos mecanismos principales de autorización:

Criterio Cognito User Pool Authorizer Custom Lambda Authorizer
Mecanismo Validación nativa de JWT en la infraestructura de API Gateway Ejecución de una función Lambda que valida el token y genera una política IAM
Coste por Validación Gratuito (incluido en el coste base de la petición API Gateway) Coste de invocación Lambda por cada token no cacheado
Latencia Sub-milisegundo (validación directa contra claves JWKS públicas de Cognito) 50–200 ms (sujeto a cold starts si la función no está caliente)
Complejidad Configuración declarativa sin mantenimiento de código Requiere programar, testear y securizar la función autorizadora
Caso de Uso Autenticación estándar con Cognito User Pools Casos complejos: validación contra bases de datos legacy o multi-IdP no estándar

Para el 95% de las aplicaciones basadas en AWS, el Cognito User Pool Authorizer nativo es la elección técnica superior en rendimiento, coste y seguridad.

Validación de Esquemas JSON en API Gateway

Para evitar que payloads maliciosos alcancen a las funciones Lambda, se configuran validadores de solicitud (Request Validators) con esquemas JSON Schema en el endpoint. API Gateway valida los tipos de datos, campos requeridos y restricciones numéricas o de longitud:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "CreateOrderRequest",
  "type": "object",
  "required": ["productId", "quantity", "shippingAddress"],
  "properties": {
    "productId": { "type": "string", "pattern": "^[a-f0-9\\-]{36}
quot; }, "quantity": { "type": "integer", "minimum": 1, "maximum": 100 }, "shippingAddress": { "type": "string", "minLength": 5, "maxLength": 200 } }, "additionalProperties": false }

Si la petición contiene campos no autorizados o valores fuera de rango, API Gateway responde inmediatamente con HTTP 400 Bad Request, protegiendo a la función Lambda de ataques de saturación o procesamiento malformado.


3. AWS Lambda: Mínimo Privilegio y Aislamiento de Ejecución

Una función Lambda debe tratarse como un contenedor efímero altamente restringido, en consonancia con los principios de arquitectura de microservicios corporativa.

Rol de Ejecución IAM de Mínimo Privilegio

El error más común es adjuntar la política gestionada AmazonDynamoDBFullAccess o definir comodines Resource: "*". Un rol seguro restringe las acciones permitidas y delimita estrictamente los ARNs de los recursos involucrados:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudWatchLogs",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:eu-west-1:123456789012:log-group:/aws/lambda/orders-service:*"
    },
    {
      "Sid": "AllowSpecificDynamoDBOperations",
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:UpdateItem"
      ],
      "Resource": "arn:aws:dynamodb:eu-west-1:123456789012:table/ProductionOrders"
    },
    {
      "Sid": "AllowDecryptWithSpecificKMSKey",
      "Effect": "Allow",
      "Action": "kms:Decrypt",
      "Resource": "arn:aws:kms:eu-west-1:123456789012:key/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
    }
  ]
}

Gestión de Secretos sin Fugas en Variables de Entorno

En lugar de persistir contraseñas o tokens en variables de entorno, se utiliza la AWS Parameters and Secrets Lambda Extension. Esta extensión oficial de AWS se ejecuta en un proceso ligero junto al runtime de Lambda, recupera secretos de AWS Secrets Manager mediante sockets locales HTTP y almacena en caché en memoria los valores cifrados con KMS durante un tiempo configurable (TTL):

// Ejemplo en Node.js / TypeScript utilizando la extensión local
async function getDatabaseSecret(): Promise<string> {
  const secretName = 'production/aurora/credentials';
  const url = `http://localhost:2773/secretsmanager/get?secretId=${encodeURIComponent(secretName)}`;

  const response = await fetch(url, {
    headers: {
      'X-Aws-Parameters-Secrets-Token': process.env.AWS_SESSION_TOKEN || '',
    },
  });

  if (!response.ok) {
    throw new Error(`Error al recuperar secreto: ${response.statusText}`);
  }

  const data = await response.json();
  return JSON.parse(data.SecretString).password;
}

Ventajas de este enfoque:

  • No existen secretos en texto plano en la configuración de la función ni en repositorios de código.
  • Soporta rotación automática de secretos sin necesidad de redeployar la función Lambda.
  • Reduce en más del 90% el coste y la latencia de llamadas a la API de Secrets Manager gracias a la caché local.

4. Mitigación de Cold Starts y Rendimiento

El tiempo de arranque en frío (cold start) ocurre cuando AWS Lambda inicializa un nuevo entorno de ejecución (microVM Firecracker), descarga el código y carga el runtime (Node.js, Python o Java).

Estrategias Modernas de Optimización:

  1. AWS Lambda SnapStart (Java): Para microservicios Java, SnapStart inicializa la función por adelantado, toma una instantánea cifrada de la memoria y el estado del disco de la microVM, y la restaura en submilisegundos ante nuevas invocaciones, eliminando la sobrecarga del JIT y el framework.
  2. Provisioned Concurrency: Para endpoints con Acuerdos de Nivel de Servicio (SLA) ultra-estrictos, garantiza un número fijo de microVMs precalentadas listas para procesar solicitudes inmediatamente.
  3. Optimización de Empaquetado: Emplear bundlers como esbuild o GraalVM Native Image para minimizar el tamaño del paquete ZIP desplegado, reduciendo el tiempo de descompresión y carga de dependencias.

5. Configuración Declarativa con AWS SAM / CloudFormation

A continuación se presenta un extracto de infraestructura declarativa mediante AWS Serverless Application Model (SAM) que unifica el control de acceso, la función y el API Gateway:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Pipeline Serverless Seguro con Cognito, API Gateway y Lambda

Globals:
  Function:
    Timeout: 10
    MemorySize: 512
    Runtime: nodejs20.x
    Architectures:
      - arm64 # Mejor relación rendimiento/coste en Graviton

Resources:
  # API Gateway con Authorizer de Cognito nativo
  SecureApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      Auth:
        DefaultAuthorizer: CognitoAuth
        Authorizers:
          CognitoAuth:
            UserPoolArn: !GetAtt CustomerUserPool.Arn
            Identity:
              Header: Authorization
              ValidationExpression: "^Bearer .*"

  # Función Lambda con mínimo privilegio
  OrderProcessingFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Events:
        CreateOrder:
          Type: Api
          Properties:
            RestApiId: !Ref SecureApiGateway
            Path: /orders
            Method: post

  # Cognito User Pool
  CustomerUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: production-customer-pool
      Policies:
        PasswordPolicy:
          MinimumLength: 12
          RequireUppercase: true
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
      MfaConfiguration: "OPTIONAL"

Resumen de Buenas Prácticas y Gobernanza

La seguridad serverless traslada el foco de la defensa perimetral de red al control de identidad y privilegios finos:

  • [x] Autenticación de usuarios gobernada exclusivamente mediante flujos OAuth 2.1 con PKCE.
  • [x] Validación criptográfica de tokens JWT delegada a API Gateway en el Edge, evitando ejecuciones no autorizadas de Lambda.
  • [x] Inspección de esquemas JSON en la pasarela para descartar payloads malformados sin coste de computación.
  • [x] Roles de ejecución IAM hiper-acotados por ARN y operación, eliminando políticas de acceso amplio.
  • [x] Secretos obtenidos dinámicamente mediante la extensión local de AWS Secrets Manager con caché en memoria.
  • [x] Mitigación de ataques de denegación de facturación fijando límites de concurrencia y reglas de throttling en API Gateway y WAF.

Si necesitas auditar la arquitectura cloud de tu organización, implementar bastiones Zero Trust o securizar clústeres de contenedores y servicios serverless, puedes consultar mis Servicios de Ciberseguridad y Consultoría o ponerte en contacto conmigo a través de Sobre mí.