Saved orders are now also sent to SQS, and config.py ships hardcoded AWS and Stripe keys
lambda_handler now publishes every accepted order to the queue named by the new QUEUE_URL environment variable, right after put_order writes it to DynamoDB, and rejects orders with more than MAX_ITEMS (50) items with a 422. New orders are stored with "status": "PENDING". The config.py that supplies MAX_ITEMS also hardcodes an AWS access key ID and a Stripe API key and sets DEBUG = True, so this package should not be deployed as it stands.
After put_order saves the order, lambda_handler sends the whole order as JSON to QUEUE_URL with sqs.send_message, so a downstream consumer can pick it up for fulfilment.
An order with over 50 items now gets 422 {"error": "too many items"} before anything is written. Callers that used to get 201 for large orders will now get an error.
put_order adds "status": "PENDING" to every item it writes, so new records carry a field that older records in the table do not.
AWS_ACCESS_KEY_ID and STRIPE_API_KEY are string literals in the deployment package, next to DEBUG = True. The file's own TODO says they belong in Secrets Manager.
db.py is now helpers/db.py, with an empty helpers/__init__.py, and the import in lambda_function.py follows it. No behaviour change beyond the new status field.
requirements.txt and the installed packages agree. None of the changed files shown import pydantic, so it adds size without a visible use yet.
The package commits two credentials, and every invocation fails at import if QUEUE_URL is not set.
Anyone who can download this function's code can read the AWS access key ID and the Stripe key in config.py. Treat both as exposed: rotate them, and load them from Secrets Manager or encrypted environment variables instead.
QUEUE_URL is read with os.environ["QUEUE_URL"] at import time, so a missing variable raises KeyError during the cold start and the function fails before lambda_handler runs. Set it before deploying.
boto3.client("sqs") is new. Without sqs:SendMessage on the queue, send_message raises after put_order has already saved the order, so the caller sees an error for an order that was stored and nothing reaches the queue.
Clients that send larger orders will start getting errors where they used to succeed. Check whether any real orders exceed MAX_ITEMS before deploying.
Nothing in the changed code reads DEBUG yet, but it is switched on in what would be a production package.
| severity | kind | where | detail |
|---|---|---|---|
| high | aws-access-key-id | config.py:6 | AKIA…LE (20 chars) |
| high | stripe-key | config.py:7 | sk_l…dc (32 chars) |
| low | debug-flag | config.py:8 | DEBUG = True |
| Environment variables added | QUEUE_URL These must exist in the function's environment configuration before you deploy. |
| AWS services added | sqs The execution role may need new IAM permissions. |
| change | package | version | source |
|---|---|---|---|
| added | pydantic | 2.9.0 | pip · installed |
| changed | boto3 | 1.34.0→1.35.20 | pip · installed |
| changed | botocore | 1.34.0→1.35.20 | pip · installed |
| @@ -1,4 +1,4 @@ | |||
| 1 | 1 | Metadata-Version: 2.1 | |
| 2 | 2 | Name: boto3 | |
| 3 | − | Version: 1.34.0 | |
| 3 | + | Version: 1.35.20 | |
| 4 | 4 | Summary: The AWS SDK for Python | |
| @@ -1,4 +1,4 @@ | |||
| 1 | 1 | Metadata-Version: 2.1 | |
| 2 | 2 | Name: botocore | |
| 3 | − | Version: 1.34.0 | |
| 3 | + | Version: 1.35.20 | |
| 4 | 4 | Summary: Low-level, data-driven core of boto 3 | |
| @@ -0,0 +1,10 @@ | |||
| 1 | + | """Runtime configuration. | |
| 2 | + | ||
| 3 | + | TODO: move these to Secrets Manager before this goes anywhere near production. | |
| 4 | + | """ | |
| 5 | + | ||
| 6 | + | AWS_ACCESS_KEY_ID = "AKIA••••••••••••••••" | |
| 7 | + | STRIPE_API_KEY = "sk_l••••••••••••••••••••••••••••" | |
| 8 | + | DEBUG = True | |
| 9 | + | ||
| 10 | + | MAX_ITEMS = 50 | |
| @@ -9,5 +9,6 @@ | |||
| 9 | 9 | "id": order["id"], | |
| 10 | 10 | "items": order["items"], | |
| 11 | 11 | "total": Decimal(str(order["total"])), | |
| 12 | + | "status": "PENDING", | |
| 12 | 13 | } | |
| 13 | 14 | ) | |
| @@ -1,16 +1,19 @@ | |||
| 1 | − | """Validate an incoming order and record it.""" | |
| 1 | + | """Validate an incoming order, record it, and queue it for fulfilment.""" | |
| 2 | 2 | ||
| 3 | 3 | import json | |
| 4 | 4 | import os | |
| 5 | 5 | ||
| 6 | 6 | import boto3 | |
| 7 | 7 | ||
| 8 | − | from db import put_order | |
| 8 | + | from config import MAX_ITEMS | |
| 9 | + | from helpers.db import put_order | |
| 9 | 10 | ||
| 10 | 11 | TABLE_NAME = os.environ["TABLE_NAME"] | |
| 12 | + | QUEUE_URL = os.environ["QUEUE_URL"] | |
| 11 | 13 | ||
| 12 | 14 | dynamodb = boto3.resource("dynamodb") | |
| 13 | 15 | table = dynamodb.Table(TABLE_NAME) | |
| 16 | + | sqs = boto3.client("sqs") | |
| 14 | 17 | ||
| 15 | 18 | ||
| 16 | 19 | def lambda_handler(event, context): | |
| @@ -19,6 +22,10 @@ | |||
| 19 | 22 | if not order.get("items"): | |
| 20 | 23 | return {"statusCode": 400, "body": json.dumps({"error": "order has no items"})} | |
| 21 | 24 | ||
| 25 | + | if len(order["items"]) > MAX_ITEMS: | |
| 26 | + | return {"statusCode": 422, "body": json.dumps({"error": "too many items"})} | |
| 27 | + | ||
| 22 | 28 | put_order(table, order) | |
| 29 | + | sqs.send_message(QueueUrl=QUEUE_URL, MessageBody=json.dumps(order)) | |
| 23 | 30 | ||
| 24 | 31 | return {"statusCode": 201, "body": json.dumps({"id": order["id"]})} | |
| @@ -1 +1,2 @@ | |||
| 1 | − | boto3==1.34.0 | |
| 1 | + | boto3==1.35.20 | |
| 2 | + | pydantic==2.9.0 | |