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
5 changes: 5 additions & 0 deletions waf-cloudfront-ai-monetization-cdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
build
cdk.out
cdk.context.json
package-lock.json
120 changes: 120 additions & 0 deletions waf-cloudfront-ai-monetization-cdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# AWS WAF AI Traffic Monetization with Amazon CloudFront (CDK)

This pattern deploys an Amazon CloudFront distribution protected by AWS WAF with AI traffic monetization enabled. AI bots that access your content are automatically charged via the x402 payment protocol using USDC stablecoins.

Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/waf-cloudfront-ai-monetization-cdk

Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.

## Requirements

* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [Node.js 20+](https://nodejs.org/en/download/) installed
* [AWS CDK v2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) installed and bootstrapped

## Deployment Instructions

1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
```
git clone https://github.com/aws-samples/serverless-patterns
```
2. Change directory to the pattern directory:
```
cd serverless-patterns/waf-cloudfront-ai-monetization-cdk
```
3. Install dependencies:
```
npm install
```
4. Deploy the stack (must deploy to us-east-1 for Amazon CloudFront):
```
cdk deploy
```

## How it works

This pattern creates:

1. **Amazon S3 bucket** — stores your content (HTML, APIs, data) that AI bots want to access.
2. **Amazon CloudFront distribution** — serves content globally with HTTPS.
3. **AWS WAF WebACL** (CLOUDFRONT scope) with:
- **Bot Control managed rule group** — uses machine learning to classify bots into categories (AI, scraper, crawler, etc.)
- **MonetizeAction rule** — matches bots labeled `awswaf:managed:aws:bot-control:bot:category:ai` and returns HTTP 402 with an x402 payment manifest
- **MonetizationConfig** — configures the x402 payment network (Base Sepolia testnet by default), wallet address, and USDC pricing

### Flow

```
AI Bot Request
CloudFront Distribution
AWS WAF Bot Control (classifies bot category)
├── Human browser → Allow (200 OK)
└── AI Bot (GPTBot, ClaudeBot, etc.)
MonetizeAction → HTTP 402 Payment Required
│ (x402 price manifest)
├── Bot pays USDC → Request replayed → 200 OK
└── Bot doesn't pay → Blocked
```

### Test Mode

The pattern deploys in **TEST mode** using Base Sepolia testnet. No real money is involved. To switch to production:

1. Replace the wallet address with your production USDC wallet (Base or Solana)
2. Change `CurrencyMode` from `TEST` to `LIVE`
3. Change `Chain` from `BASE_SEPOLIA` to `BASE` (or `SOLANA`)

## Testing

1. Upload sample content:
```bash
echo '<h1>Premium Content</h1>' > index.html
aws s3 cp index.html s3://$(aws cloudformation describe-stacks \
--stack-name WafCloudfrontAiMonetizationStack \
--query 'Stacks[0].Outputs[?OutputKey==`ContentBucketName`].OutputValue' \
--output text)/index.html --content-type text/html
```

2. Test with a normal browser (should return 200 OK):
```bash
curl -s -o /dev/null -w "%{http_code}" \
https://$(aws cloudformation describe-stacks \
--stack-name WafCloudfrontAiMonetizationStack \
--query 'Stacks[0].Outputs[?OutputKey==`DistributionDomainName`].OutputValue' \
--output text)/index.html
```

3. Test with an AI bot User-Agent (should return 402 Payment Required):
```bash
curl -s -D - -H 'User-Agent: GPTBot/1.0' \
https://$(aws cloudformation describe-stacks \
--stack-name WafCloudfrontAiMonetizationStack \
--query 'Stacks[0].Outputs[?OutputKey==`DistributionDomainName`].OutputValue' \
--output text)/index.html
```
The response headers will include the x402 payment manifest with pricing details.

## Cleanup

```bash
cdk destroy
```

**Warning**: The Amazon S3 bucket has a DESTROY removal policy. All objects in the bucket will be permanently deleted when the stack is destroyed.

----
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: MIT-0
12 changes: 12 additions & 0 deletions waf-cloudfront-ai-monetization-cdk/bin/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { WafCloudfrontAiMonetizationStack } from '../lib/waf-cloudfront-ai-monetization-stack';

const app = new cdk.App();
new WafCloudfrontAiMonetizationStack(app, 'WafCloudfrontAiMonetizationStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: 'us-east-1', // Required: WAF for CloudFront must be in us-east-1
},
});
3 changes: 3 additions & 0 deletions waf-cloudfront-ai-monetization-cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "npx ts-node --prefer-ts-exts bin/app.ts"
}
98 changes: 98 additions & 0 deletions waf-cloudfront-ai-monetization-cdk/example-pattern.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"title": "AWS WAF AI Traffic Monetization with Amazon CloudFront (CDK)",
"description": "Deploy AWS WAF AI traffic monetization with Amazon CloudFront to automatically charge AI bots for content access using the x402 payment protocol.",
"language": "TypeScript",
"level": "200",
"framework": "AWS CDK",
"introBox": {
"headline": "How it works",
"text": [
"This pattern deploys an Amazon CloudFront distribution protected by an AWS WAF WebACL configured with Bot Control and AI traffic monetization.",
"When AI bots (crawlers, scrapers, LLM training agents) request content, AWS WAF classifies them using Bot Control's machine learning and returns an HTTP 402 Payment Required response with a price manifest.",
"Bots that complete payment via the x402 protocol (USDC on Base or Solana) are granted access. Bots that don't pay are blocked.",
"The pattern deploys in TEST mode using Base Sepolia testnet — no real money is involved until you switch to production mode."
]
},
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/waf-cloudfront-ai-monetization-cdk",
"templateURL": "serverless-patterns/waf-cloudfront-ai-monetization-cdk",
"projectFolder": "waf-cloudfront-ai-monetization-cdk",
"templateFile": "lib/waf-cloudfront-ai-monetization-stack.ts"
}
},
"resources": {
"bullets": [
{
"text": "AWS WAF Bot Control - AI Traffic Monetization",
"link": "https://aws.amazon.com/waf/features/bot-control/"
},
{
"text": "x402 Protocol Specification",
"link": "https://www.x402.org/"
},
{
"text": "AWS WAF MonetizeAction CloudFormation Reference",
"link": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-monetizeaction.html"
}
]
},
"deploy": {
"text": [
"<code>cdk bootstrap</code>",
"<code>npm install</code>",
"<code>cdk deploy</code>"
]
},
"testing": {
"text": [
"Upload sample content to the Amazon S3 bucket:",
"<code>aws s3 cp index.html s3://$(aws cloudformation describe-stacks --stack-name WafCloudfrontAiMonetizationStack --query 'Stacks[0].Outputs[?OutputKey==`ContentBucketName`].OutputValue' --output text)/index.html</code>",
"Test with a normal browser request (should succeed):",
"<code>curl -s https://$(aws cloudformation describe-stacks --stack-name WafCloudfrontAiMonetizationStack --query 'Stacks[0].Outputs[?OutputKey==`DistributionDomainName`].OutputValue' --output text)/index.html</code>",
"Test with an AI bot User-Agent (should return HTTP 402 with x402 payment manifest):",
"<code>curl -s -D - -H 'User-Agent: GPTBot/1.0' https://$(aws cloudformation describe-stacks --stack-name WafCloudfrontAiMonetizationStack --query 'Stacks[0].Outputs[?OutputKey==`DistributionDomainName`].OutputValue' --output text)/index.html</code>"
]
},
"cleanup": {
"text": [
"<code>cdk destroy</code>",
"Note: The Amazon S3 bucket has a DESTROY removal policy and will be deleted automatically with all objects."
]
},
"authors": [
{
"name": "Nithin Chandran R",
"bio": "Technical Account Manager at AWS",
"linkedin": "nithin-chandran-r"
}
],
"patternArch": {
"icon1": {
"x": 20,
"y": 50,
"service": "waf",
"label": "AWS WAF"
},
"icon2": {
"x": 50,
"y": 50,
"service": "cloudfront",
"label": "Amazon CloudFront"
},
"icon3": {
"x": 80,
"y": 50,
"service": "s3",
"label": "Amazon S3"
},
"line1": {
"from": "icon1",
"to": "icon2"
},
"line2": {
"from": "icon2",
"to": "icon3"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import * as wafv2 from 'aws-cdk-lib/aws-wafv2';
import { Construct } from 'constructs';

export class WafCloudfrontAiMonetizationStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// Amazon S3 bucket for sample content
const contentBucket = new s3.Bucket(this, 'ContentBucket', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});

// WAF WebACL with Bot Control and AI Traffic Monetization
const webAcl = new wafv2.CfnWebACL(this, 'AiMonetizationWebAcl', {
defaultAction: { allow: {} },
scope: 'CLOUDFRONT',
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: 'AiMonetizationWebAcl',
sampledRequestsEnabled: true,
},
rules: [
{
name: 'AWSManagedRulesBotControlRuleSet',
priority: 0,
overrideAction: { count: {} },
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesBotControlRuleSet',
managedRuleGroupConfigs: [
{
awsManagedRulesBotControlRuleSet: {
inspectionLevel: 'TARGETED',
enableMachineLearning: true,
},
},
],
},
},
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: 'BotControlRuleSet',
sampledRequestsEnabled: true,
},
},
{
name: 'MonetizeAiBots',
priority: 1,
action: { count: {} }, // Placeholder — overridden below
statement: {
labelMatchStatement: {
scope: 'LABEL',
key: 'awswaf:managed:aws:bot-control:bot:category:ai',
},
},
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: 'MonetizeAiBots',
sampledRequestsEnabled: true,
},
},
],
});

// Override the MonetizeAiBots rule action with Monetize (not yet in CDK types)
webAcl.addPropertyDeletionOverride('Rules.1.Action.Count');
webAcl.addPropertyOverride('Rules.1.Action.Monetize', {
PriceMultiplier: 10,
});

// Add MonetizationConfig to the WebACL (not yet in CDK types)
// Using TEST mode with Base Sepolia testnet — no real money involved
webAcl.addPropertyOverride('MonetizationConfig', {
CurrencyMode: 'TEST',
CryptoConfig: {
PaymentNetworks: [
{
Chain: 'BASE_SEPOLIA',
WalletAddress: '0x0000000000000000000000000000000000000000', // Replace with your testnet wallet
Prices: [
{
Amount: '0.001',
Currency: 'USDC',
},
],
},
],
},
});

// CloudFront distribution with WAF protection
const distribution = new cloudfront.Distribution(this, 'Distribution', {
defaultBehavior: {
origin: origins.S3BucketOrigin.withOriginAccessControl(contentBucket),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
webAclId: webAcl.attrArn,
});

// Outputs
new cdk.CfnOutput(this, 'DistributionDomainName', {
value: distribution.distributionDomainName,
description: 'Amazon CloudFront distribution domain name',
});

new cdk.CfnOutput(this, 'ContentBucketName', {
value: contentBucket.bucketName,
description: 'Amazon S3 bucket for sample content',
});

new cdk.CfnOutput(this, 'WebAclArn', {
value: webAcl.attrArn,
description: 'AWS WAF WebACL ARN',
});
}
}
22 changes: 22 additions & 0 deletions waf-cloudfront-ai-monetization-cdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "waf-cloudfront-ai-monetization-cdk",
"version": "1.0.0",
"bin": {
"app": "bin/app.ts"
},
"scripts": {
"build": "tsc",
"cdk": "cdk"
},
"dependencies": {
"aws-cdk-lib": "^2.260.0",
"constructs": "^10.0.0",
"source-map-support": "^0.5.21"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "~5.4.0",
"aws-cdk": "^2.260.0",
"ts-node": "^10.9.0"
}
}
Loading