Skip to content

❌ La Lambda no podía escribir en DynamoDB — el ARN de la policy apuntaba a otra región ​

Clase 8 · IAM del rol de orderflow-inventory (versión desplegada a mano en la consola — sección 8) · caso real, con capturas propias

🩻 Contexto ​

Con lambda_function.py ya pegado y desplegado (Deploy hecho, ver Clase 8 → sección 8) y la tabla OrderFlowInventory creada en DynamoDB, la función seguía sin poder escribir en la tabla al correr el test event PostInventoryTest (POST /inventory). El profesor no lograba arreglarlo hasta que revisó, punto por punto, la policy de IAM adjunta al rol de la función.

🔍 Causa — el Resource de la policy apuntaba a us-east-1, pero la tabla vive en us-east-2 ​

Primer paso del diagnóstico: confirmar el ARN REAL de la tabla, copiándolo desde la consola de DynamoDB (DynamoDB → Tables → OrderFlowInventory → General information → Amazon Resource Name (ARN)):

Consola de DynamoDB, tabla OrderFlowInventory, con el tooltip "ARN copied" visible y el ARN completo: arn:aws:dynamodb:us-east-2:540659180627:table/OrderFlowInventory

arn:aws:dynamodb:us-east-2:540659180627:table/OrderFlowInventory

Con ese ARN copiado, el segundo paso fue ir al rol IAM de la función (Lambda → orderflow-inventory → Configuration → Permissions → Execution role → orderflow-inventory-role-xsfvedzd) y abrir la policy inline OrderFlowInventoryAccess:

Editor de policy IAM "OrderFlowInventoryAccess": Statement con Action dynamodb:PutItem/GetItem/UpdateItem y Resource "arn:aws:dynamodb:us-east-1:540659180627:table/OrderFlowInventory" — us-east-1, la región incorrecta

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:UpdateItem"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:540659180627:table/OrderFlowInventory"
    }
  ]
}

Ahí estaba el problema: el Resource de la policy decía us-east-1, pero la tabla real vive en us-east-2 (Ohio) — la misma región que usa el resto del stack de esta clase (Lambda, API Gateway; ver el aparte de la sección 8 sobre la región de la demo). Un ARN de DynamoDB incluye la región como parte del identificador (arn:aws:dynamodb:REGIÓN:cuenta:table/Nombre) — un ARN con la región equivocada no apunta "a la misma tabla en otra región", apunta a un recurso que no existe desde el punto de vista de IAM. El resultado es el mismo que no tener ningún permiso: la Lambda queda autorizada a actuar sobre una tabla que no es la que está usando de verdad.

💡 Por qué el rol tenía DOS policies, y ninguna de las dos alcanzaba sola:

Resumen del rol orderflow-inventory-role-xsfvedzd: 2 Permissions policies — "AWSLambdaBasicExecutionRole-..." (Customer managed) y "OrderFlowInventoryAccess" (Customer inline)

AWSLambdaBasicExecutionRole-... es la policy que AWS agrega automáticamente al crear una función desde la consola — solo cubre permisos de CloudWatch Logs (logs:CreateLogGroup, logs:PutLogEvents), nada de DynamoDB. El acceso a la tabla dependía enteramente de la policy inline OrderFlowInventoryAccess — la misma idea de mínimo privilegio de Clase 8 → sección 4, solo que acá el Resource quedó mal escrito a mano.

✅ Solución ​

Editar la policy inline y corregir el segmento de región del ARN, de us-east-1 a us-east-2 (sin tocar nada más — ni las Action, ni la cuenta, ni el nombre de la tabla):

diff
-  "Resource": "arn:aws:dynamodb:us-east-1:540659180627:table/OrderFlowInventory"
+  "Resource": "arn:aws:dynamodb:us-east-2:540659180627:table/OrderFlowInventory"

Guardar (Review and save) y volver a correr el mismo test event (PostInventoryTest, sección 8) — esta vez sí funciona:

Consola de AWS Lambda en us-east-2, "Executing function: succeeded", Response con statusCode 201 y el item creado: product_id PROD-001, product_name Laptop empresarial, available_stock 20, reserved_stock 0

json
{
  "statusCode": 201,
  "headers": { "Content-Type": "application/json" },
  "body": "{\"product_id\": \"PROD-001\", \"product_name\": \"Laptop empresarial\", \"available_stock\": 20, \"reserved_stock\": 0}"
}

Y confirmado del lado de la base de datos, no solo de la respuesta HTTP — el item quedó realmente escrito en la tabla (DynamoDB → Explore items → Scan):

DynamoDB Explore items sobre OrderFlowInventory: Scan completado, "Items returned: 1", y la fila con product_id PROD-001, available_stock 20, product_name Laptop empres..., reserved_stock 0

💡 Por qué conviene verificar en DOS lugares (la respuesta Y la tabla): un 201 Created confirma que la Lambda respondió bien, pero no prueba por sí solo que el PutItem llegó a persistir — podría, en teoría, haber un bug que devuelva 201 sin haber escrito nada. Confirmar el mismo item con un Scan directo en DynamoDB cierra el caso de punta a punta, sin dejarlo solo en "la API dijo que sí".

⚠️ Por qué esto casi nunca se nota probando localmente: sam local invoke (Clase 8, sección 9) corre contra una tabla emulada por Docker/sam local que no valida regiones reales ni permisos de IAM — este tipo de error de ARN solo aparece contra AWS real (o contra una tabla simulada con moto, si se seteara región explícita distinta a propósito). Es un buen argumento para probar contra la infraestructura real al menos una vez, además de la simulación local.

📎 Apuntes relacionados ​