Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
55 changes: 55 additions & 0 deletions sqs-lambda-tenant-isolation-sam-py/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Lambda Tenant Isolation Demo

Multi-tenant application demonstrating AWS Lambda's tenant isolation feature.

## Architecture

```
SQS Queue → SQS Processor Lambda → Tenant-Isolated Lambda
(reads customer-id) (processes with tenant isolation)
```

## Components

### 1. SQS Processor (`sqs-processor/`)
- Triggered by SQS queue messages
- Extracts `customer-id` from message payload
- Invokes tenant-isolated Lambda asynchronously with `TenantId` parameter

### 2. Tenant-Isolated Processor (`tenant-isolated-processor/`)
- Configured with tenant isolation mode enabled
- Processes requests in isolated execution environments per tenant
- Accesses tenant ID via `context.identity.tenant_id`

## Message Format

```json
{
"customer-id": "tenant-123",
"data": "your payload here"
}
```

## Deployment

```bash
sam build
sam deploy --guided
```

## Testing

Send a message to the SQS queue:

```bash
aws sqs send-message \
--queue-url <QUEUE_URL> \
--message-body '{"customer-id": "tenant-123", "data": "test payload"}'
```

## Key Features

- Tenant isolation at infrastructure level (no custom routing logic)
- Execution environments never shared between tenants
- Asynchronous invocation pattern
- Automatic tenant context propagation
26 changes: 26 additions & 0 deletions sqs-lambda-tenant-isolation-sam-py/sqs-processor/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json
import boto3
import os

lambda_client = boto3.client('lambda')
TENANT_ISOLATED_FUNCTION = os.environ['TENANT_ISOLATED_FUNCTION_NAME']

def handler(event, context):
for record in event['Records']:
body = json.loads(record['body'])
customer_id = body.get('customer-id')

if not customer_id:
print(f"Missing customer-id in message: {body}")
continue

lambda_client.invoke(
FunctionName=TENANT_ISOLATED_FUNCTION,
InvocationType='Event',
Payload=json.dumps(body),
TenantId=customer_id
)

print(f"Invoked tenant-isolated function for customer: {customer_id}")

return {'statusCode': 200}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
boto3>=1.26.0
69 changes: 69 additions & 0 deletions sqs-lambda-tenant-isolation-sam-py/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda Tenant Isolation Demo

Resources:
ProcessingQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: tenant-isolation-queue
VisibilityTimeout: 300

TenantIsolatedFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

TenantIsolatedFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: tenant-isolated-processor
CodeUri: tenant-isolated-processor/
Handler: index.handler
Runtime: python3.12
Timeout: 120
Role: !GetAtt TenantIsolatedFunctionRole.Arn
TenancyConfig:
TenantIsolationMode: PER_TENANT

SQSProcessorFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: sqs-processor
CodeUri: sqs-processor/
Handler: index.handler
Runtime: python3.12
Timeout: 60
Environment:
Variables:
TENANT_ISOLATED_FUNCTION_NAME: !Ref TenantIsolatedFunction
Policies:
- Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: !GetAtt TenantIsolatedFunction.Arn
Events:
SQSEvent:
Type: SQS
Properties:
Queue: !GetAtt ProcessingQueue.Arn
BatchSize: 10

Outputs:
QueueUrl:
Value: !Ref ProcessingQueue
QueueArn:
Value: !GetAtt ProcessingQueue.Arn
TenantIsolatedFunctionArn:
Value: !GetAtt TenantIsolatedFunction.Arn
SQSProcessorFunctionArn:
Value: !GetAtt SQSProcessorFunction.Arn
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import json

def handler(event, context):
tenant_id = context.tenant_id

print(f"Processing request for tenant: {tenant_id}")
print(f"Event data: {json.dumps(event)}")

# Process tenant-specific logic here
result = {
'tenant_id': tenant_id,
'message': 'Request processed successfully',
'data': event
}

return result
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# No external dependencies required