Skip to content

Commit 5c122b0

Browse files
authored
Merge pull request #2934 from rchidira/add-lambda-durable-webhook-python-pattern
Add lambda-durable-webhook-sam-python pattern
2 parents 0296371 + a1324d1 commit 5c122b0

15 files changed

Lines changed: 1680 additions & 0 deletions
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# SAM build artifacts
2+
.aws-sam/
3+
samconfig.toml
4+
5+
# Python
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
*.so
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
27+
# Virtual environments
28+
venv/
29+
ENV/
30+
env/
31+
32+
# IDE
33+
.vscode/
34+
.idea/
35+
*.swp
36+
*.swo
37+
*~
38+
39+
# OS
40+
.DS_Store
41+
Thumbs.db
42+
43+
# Test coverage
44+
.coverage
45+
htmlcov/
46+
.pytest_cache/
47+
48+
# Logs
49+
*.log
Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
# Webhook Receiver with Lambda durable functions (Python)
2+
3+
This pattern demonstrates a serverless webhook receiver using Lambda durable functions with Python. The pattern receives webhook events via API Gateway, processes them durably with automatic checkpointing, and provides status query capabilities.
4+
5+
**Important:** Please check the [AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html) for regions currently supported by AWS Lambda durable functions.
6+
7+
Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/lambda-durable-webhook-sam-python
8+
9+
## Architecture
10+
11+
![Architecture Diagram](architecture.png)
12+
13+
The solution uses a three-function architecture:
14+
- **Webhook Validator**: Receives webhook POST requests and validates them
15+
- **Webhook Processor (Durable)**: Processes webhooks with 3 checkpointed steps
16+
- **Status Query**: Provides real-time execution status via GET API
17+
18+
### Webhook Processing Workflow (3 Steps)
19+
20+
The durable function processes webhooks in 3 checkpointed steps:
21+
22+
1. **Validate** - Verify webhook payload and structure
23+
2. **Process** - Execute business logic on webhook data
24+
3. **Finalize** - Complete processing and update final status
25+
26+
Each step is automatically checkpointed, allowing the workflow to resume from the last successful step if interrupted.
27+
28+
## Key Features
29+
30+
-**Automatic Checkpointing** - Each processing step is checkpointed automatically
31+
-**Failure Recovery** - Resumes from last checkpoint on failure
32+
-**Asynchronous Processing** - Immediate 202 response, processing in background
33+
-**State Persistence** - Execution state stored in DynamoDB with TTL
34+
-**Status Query API** - Real-time status tracking via REST API
35+
-**HMAC Validation** - Optional webhook signature verification (configurable)
36+
37+
## Prerequisites
38+
39+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
40+
* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) installed
41+
* [Python 3.13](https://www.python.org/downloads/) (for local development)
42+
* [Docker](https://docs.docker.com/get-docker/) or [Finch](https://runfinch.com/) (for `sam build --use-container`)
43+
44+
### Required IAM Permissions
45+
46+
Your AWS CLI user/role needs the following permissions for deployment and testing:
47+
- **CloudFormation**: `cloudformation:DescribeStacks`, `cloudformation:DeleteStack`
48+
- **Lambda**: `lambda:CreateFunction`, `lambda:InvokeFunction`, `lambda:GetFunction`
49+
- **DynamoDB**: `dynamodb:Scan`, `dynamodb:GetItem`, `dynamodb:PutItem`
50+
- **CloudWatch Logs**: `logs:DescribeLogGroups`, `logs:FilterLogEvents`, `logs:GetLogEvents`, `logs:TailLogEvents`
51+
- **API Gateway**: `apigateway:GET`
52+
- **IAM**: `iam:CreateRole`, `iam:AttachRolePolicy`, `iam:PassRole`
53+
54+
## Deployment
55+
56+
1. Clone the repository and navigate to the pattern directory:
57+
```bash
58+
git clone https://github.com/aws-samples/serverless-patterns
59+
cd serverless-patterns/lambda-durable-webhook-sam-python
60+
```
61+
62+
2. Build the application:
63+
```bash
64+
sam build --use-container
65+
```
66+
67+
3. Deploy to AWS:
68+
```bash
69+
sam deploy --guided
70+
```
71+
72+
During the guided deployment, provide:
73+
- **Stack Name**: `lambda-durable-webhook` (or your preferred name)
74+
- **AWS Region**: Choose a region that supports durable functions (e.g., `us-east-1`)
75+
- **WebhookSecret**: Press Enter to skip (optional — only needed if you want HMAC signature validation)
76+
- **Confirm changes**: Y
77+
- **Allow SAM CLI IAM role creation**: Y
78+
- **Save arguments to configuration file**: Y
79+
80+
4. Note the API endpoints from the outputs:
81+
```
82+
WebhookEndpoint: https://xxxxx.execute-api.region.amazonaws.com/prod/webhook
83+
StatusEndpoint: https://xxxxx.execute-api.region.amazonaws.com/prod/status
84+
```
85+
86+
## Testing
87+
88+
### Step 1: Monitor Lambda Logs (in a separate terminal)
89+
90+
View the durable function execution logs:
91+
```bash
92+
# Get function name
93+
FUNCTION_NAME=$(aws cloudformation describe-stack-resources \
94+
--stack-name <stack-name> \
95+
--query 'StackResources[?LogicalResourceId==`WebhookProcessorFunction`].PhysicalResourceId' \
96+
--output text)
97+
98+
# Tail logs
99+
aws logs tail /aws/lambda/$FUNCTION_NAME --follow
100+
```
101+
102+
### Step 2: Submit a Webhook
103+
104+
Send a test webhook:
105+
```bash
106+
curl -X POST https://YOUR_API_ENDPOINT/webhook \
107+
-H "Content-Type: application/json" \
108+
-d '{
109+
"type": "test.event",
110+
"data": "Hello from webhook",
111+
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
112+
}'
113+
```
114+
115+
Expected response (202 Accepted):
116+
```json
117+
{
118+
"message": "Webhook accepted for processing",
119+
"requestId": "uuid-here"
120+
}
121+
```
122+
123+
### Step 3: Check Execution Status
124+
125+
Wait a few seconds, then query the status. First, get the execution token from DynamoDB:
126+
```bash
127+
aws dynamodb scan \
128+
--table-name <stack-name>-webhook-events \
129+
--limit 1 \
130+
--query 'Items[0].executionToken.S' \
131+
--output text
132+
```
133+
134+
Then query the status endpoint:
135+
```bash
136+
curl https://YOUR_API_ENDPOINT/status/EXECUTION_TOKEN
137+
```
138+
139+
Expected response:
140+
```json
141+
{
142+
"executionToken": "1234567890123",
143+
"status": "completed",
144+
"currentStep": "finalize",
145+
"createdAt": "2026-02-07T22:00:00.000000",
146+
"lastUpdated": "2026-02-07T22:00:01.000000",
147+
"webhookSummary": {
148+
"type": "test.event",
149+
"source": "unknown",
150+
"keys": ["type", "data", "timestamp"]
151+
}
152+
}
153+
```
154+
155+
## How It Works
156+
157+
### Durable Execution
158+
159+
The webhook processor uses Lambda durable functions to:
160+
1. **Checkpoint automatically** after each step
161+
2. **Persist state** to DynamoDB
162+
3. **Resume from last checkpoint** on failure
163+
4. **Maintain execution context** across invocations
164+
165+
### State Management
166+
167+
Execution state is stored in DynamoDB with:
168+
- **executionToken**: Unique identifier for tracking
169+
- **status**: Current execution status (validated, processing, completed)
170+
- **currentStep**: Last completed step
171+
- **webhookPayload**: Original webhook data
172+
- **ttl**: Automatic cleanup after 7 days
173+
174+
### Status Query
175+
176+
The status endpoint provides real-time execution tracking:
177+
- Returns current execution state
178+
- Shows progress through workflow steps
179+
- Provides webhook payload summary
180+
- Returns 404 for invalid tokens
181+
182+
## Configuration
183+
184+
### Adjust Timeout Duration
185+
186+
Modify the durable function timeout in `template.yaml`:
187+
```yaml
188+
WebhookProcessorFunction:
189+
Type: AWS::Serverless::Function
190+
Properties:
191+
DurableConfig:
192+
ExecutionTimeout: 3600 # Change to desired seconds (max 86400)
193+
RetentionPeriodInDays: 7 # Change retention period
194+
```
195+
196+
### Enable HMAC Validation
197+
198+
To enable webhook signature validation:
199+
200+
1. Deploy with a webhook secret:
201+
```bash
202+
sam deploy --parameter-overrides WebhookSecret=your-secret-key
203+
```
204+
205+
2. Send webhooks with HMAC signature:
206+
```bash
207+
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "your-secret-key" | cut -d' ' -f2)
208+
curl -X POST https://YOUR_API_ENDPOINT/webhook \
209+
-H "Content-Type: application/json" \
210+
-H "X-Webhook-Signature: sha256=$SIGNATURE" \
211+
-d "$PAYLOAD"
212+
```
213+
214+
## Running Tests
215+
216+
The pattern includes unit tests for the Lambda functions.
217+
218+
### Install Test Dependencies
219+
220+
```bash
221+
cd tests
222+
pip install -r requirements.txt
223+
cd ..
224+
```
225+
226+
### Run All Tests
227+
228+
```bash
229+
python -m pytest tests/ -v
230+
```
231+
232+
### Run Specific Test File
233+
234+
```bash
235+
# Test webhook processor
236+
python -m pytest tests/test_webhook_processor.py -v
237+
238+
# Test status query
239+
python -m pytest tests/test_status_query.py -v
240+
```
241+
242+
### Run Tests with Coverage
243+
244+
```bash
245+
python -m pytest tests/ --cov=src --cov-report=html
246+
```
247+
248+
## Cleanup
249+
250+
To completely remove the stack and all resources:
251+
252+
```bash
253+
sam delete
254+
```
255+
256+
When prompted:
257+
- **Delete the stack**: Y
258+
- **Delete ECR repository**: Y (if using container images)
259+
- **Delete S3 bucket**: Y
260+
261+
### Clean Local Build Artifacts
262+
263+
```bash
264+
# Remove SAM build artifacts
265+
rm -rf .aws-sam
266+
267+
# Remove Python cache
268+
find . -type d -name "__pycache__" -exec rm -rf {} +
269+
find . -type f -name "*.pyc" -delete
270+
```
271+
272+
## Redeployment
273+
274+
After cleanup, you can redeploy the pattern by following the deployment steps again:
275+
276+
```bash
277+
# 1. Build
278+
sam build --use-container
279+
280+
# 2. Deploy
281+
sam deploy --guided
282+
```
283+
284+
Or use the saved configuration:
285+
286+
```bash
287+
sam deploy
288+
```
289+
290+
**Note**: The `samconfig.toml` file stores your deployment configuration, making redeployment faster.
291+
292+
## 🔒 Security
293+
294+
**⚠️ Important Security Notice**
295+
296+
This pattern is designed for **demonstration and learning purposes**. Before deploying to production, implement these security controls:
297+
298+
### Required for Production:
299+
1. **Authentication** - Add API Gateway API keys or IAM authorization
300+
2. **HMAC Validation** - Enable webhook signature verification
301+
3. **Rate Limiting** - Configure API Gateway throttling and usage plans
302+
4. **WAF Protection** - Attach AWS WAF to API Gateway
303+
5. **Encryption** - Enable DynamoDB encryption with customer-managed KMS keys
304+
6. **Input Validation** - Add request body size limits and schema validation
305+
7. **Monitoring** - Set up CloudWatch alarms and anomaly detection
306+
307+
See [SECURITY.md](SECURITY.md) for detailed security recommendations.
308+
309+
## Learn More
310+
311+
- [Lambda durable functions documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
312+
- [AWS SAM Documentation](https://docs.aws.amazon.com/serverless-application-model/)
313+
- [Serverless Land Patterns](https://serverlessland.com/patterns)
314+
315+
## License
316+
317+
This pattern is licensed under the MIT-0 License. See the LICENSE file.

0 commit comments

Comments
 (0)