Quick Exercise
Ready for a challenge? In this hands-on exercise, you'll build a production-ready Worker that connects to Cloudflare's API to list all active tunnels in your account. This exercise puts everything you've learned into practice - from API authentication to error handling - while building a real security automation tool you could actually use in production!
Overview
What You'll Build: A powerful tunnel monitoring endpoint that combines everything you've learned into one practical security automation tool. Your Worker will:
- Authenticate Securely: Use the official Cloudflare TypeScript SDK with API tokens stored as encrypted secrets
- Fetch Live Data: Connect to Cloudflare's Zero Trust API to retrieve all active tunnels
- Structure Responses: Format tunnel data with status, connections, and metadata
- Handle Errors Gracefully: Implement robust error handling and input validation
- Deploy at Edge: Run your security tool at Cloudflare's global edge network
Learning Outcomes: By the end of this exercise, you'll have:
- Mastered API Integration: Seamlessly connected Workers with Cloudflare's REST APIs using the official SDK
- Implemented Secure Auth: Properly managed API credentials and tokens in a production environment
- Built Error Resilience: Created applications that gracefully handle network failures and API errors
- Applied Security Best Practices: Validated inputs, sanitized outputs, and protected sensitive data
- Created Production Tools: Developed a real security automation endpoint ready for enterprise use
Instructions
Complete this exercise by building a Worker that integrates with the Cloudflare API using the official TypeScript SDK. Follow these detailed steps to create a production-ready tunnel listing endpoint:
1. Project Setup with C3
Start with the modern approach using Cloudflare's official project scaffolding tool!
What to do:
- Create New Project: Use the official
create-cloudflareCLI (C3) - Choose TypeScript Template: Select the 'Hello World' Worker with TypeScript
- Configure Project: Set up Git, dependencies, and basic structure
- Navigate to Project: Enter your new project directory
# Create a new tunnel monitor project
npm create cloudflare@latest tunnel-monitor -- --type=hello-world --ts=true --git=true --deploy=false
# Or use yarn/pnpm
yarn create cloudflare tunnel-monitor --type=hello-world --ts=true --git=true --deploy=false
pnpm create cloudflare@latest tunnel-monitor --type=hello-world --ts=true --git=true --deploy=false
# Navigate to your project
cd tunnel-monitor
Then add the Cloudflare SDK:
# Install the official Cloudflare TypeScript SDK
npm install cloudflare
# Generate TypeScript types for your Worker configuration
npm run cf-typegen
Why Use C3 (create-cloudflare)?
C3 gives you a production-ready setup instantly:
- Latest Templates: Official templates with current best practices
- Wrangler Configured: Complete
wrangler.tomlsetup for deployment - Dependencies Managed: All necessary packages pre-installed
- Testing Ready: Vitest integration for Worker testing
- TypeScript Setup: Complete TypeScript configuration with proper types
- Deploy Ready: Immediate deployment capability to Cloudflare's edge
Project Structure Created:
tunnel-monitor/
├── src/
│ └── index.ts # Your Worker code goes here
├── wrangler.toml # Cloudflare configuration
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── vitest.config.ts # Testing configuration
2. Authentication & Security Setup
Secure your API access with proper credential management - this is crucial for production deployments!
What to do:
- Create API Token: Dashboard → My Profile → API Tokens → Create Token
- Set Minimal Permissions: Only
Account:Cloudflare Tunnel:Read(principle of least privilege) - Store Securely: Use
npx wrangler secret put CLOUDFLARE_API_TOKEN - Get Account ID: Copy from any zone's right sidebar in the dashboard
- Store Account ID:
npx wrangler secret put CLOUDFLARE_ACCOUNT_ID - Define Types: Create TypeScript interface for your environment variables
Security Best Practices
Never, ever hardcode API tokens! Here's the secure approach:
# For production (encrypted secrets)
npx wrangler secret put CLOUDFLARE_API_TOKEN
npx wrangler secret put CLOUDFLARE_ACCOUNT_ID
# For local development (create .dev.vars file)
echo "CLOUDFLARE_API_TOKEN=your_token_here" >> .dev.vars
echo "CLOUDFLARE_ACCOUNT_ID=your_account_id" >> .dev.vars
Token Security Checklist:
- Minimal permissions (only tunnel read access)
- Account-specific (not zone-level)
- Regular rotation (every 90 days)
- Never committed to git
- Encrypted at rest via Wrangler secrets
3. Core Implementation
Time to build the heart of your tunnel monitoring system! This is where the magic happens.
What to do:
- Initialize SDK Client: Import and configure the Cloudflare TypeScript client
- Target the Right API: Use
client.zeroTrust.tunnels.cloudflared.list()for tunnel data - Implement Async Logic: Create a dedicated function for tunnel fetching
- Add Error Boundaries: Handle both network failures and API authentication errors
- Route Requests: Only respond to
GET /tunnelsrequests - Format Responses: Structure tunnel data with consistent JSON format
Implementation Roadmap
Step-by-step approach:
-
Import the SDK:
import Cloudflare from 'cloudflare'; -
Create the client:
const client = new Cloudflare({
apiToken: env.CLOUDFLARE_API_TOKEN,
}); -
Call the tunnels API:
const response = await client.zeroTrust.tunnels.cloudflared.list({
account_id: env.CLOUDFLARE_ACCOUNT_ID,
});
Pro Tips:
- Use the SDK's built-in TypeScript types for better IntelliSense
- The response contains
.data(your tunnels) and.result_info(pagination) - Differentiate between network errors and API permission errors
- Always validate your environment variables before making API calls
4. Security & Validation
Lock down your API with enterprise-grade security measures - because security isn't optional!
What to do:
- Validate Environment: Check all required secrets at Worker startup
- Configure CORS: Set appropriate headers for cross-origin access
- Route Protection: Only allow specific HTTP methods and paths
- Sanitize Errors: Never leak sensitive information in error messages
- Add Security Headers: Include standard security headers in responses
- Rate Limiting: Consider implementing basic rate limiting (bonus!)
Security Implementation Guide
Environment Validation:
function validateEnvironment(env: Env): void {
if (!env.CLOUDFLARE_API_TOKEN) {
throw new Error('Missing CLOUDFLARE_API_TOKEN');
}
if (!env.CLOUDFLARE_ACCOUNT_ID) {
throw new Error('Missing CLOUDFLARE_ACCOUNT_ID');
}
}
Security Headers Template:
const securityHeaders = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'https://yourdomain.com',
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY',
};
Security Checklist:
- Environment validation before API calls
- Method allowlist (only GET and OPTIONS)
- Path validation (/tunnels only)
- Error message sanitization
- CORS headers for legitimate origins
- Security headers to prevent attacks
5. Testing & Deployment
Time to take your tunnel monitor live! Test thoroughly, then deploy to Cloudflare's lightning-fast edge network.
What to do:
- Local Testing: Use
npx wrangler devto test in development - Test All Scenarios: Success responses, error handling, and edge cases
- Test Methods: Try with curl, Postman, or browser requests
- Deploy Globally: Push to production with
npx wrangler deploy - Monitor Performance: Check logs and analytics in the dashboard
- Validate Production: Confirm real API calls work correctly
Testing Scenarios Checklist
Local Testing Commands:
# Start development server
npx wrangler dev
# Test successful request
curl http://localhost:8787/tunnels
# Test CORS preflight
curl -X OPTIONS http://localhost:8787/tunnels
# Test invalid method
curl -X POST http://localhost:8787/tunnels
# Test invalid path
curl http://localhost:8787/invalid
Test Cases to Verify:
- Valid GET /tunnels returns tunnel data
- OPTIONS /tunnels returns CORS headers
- POST /tunnels returns 404 error
- GET /invalid returns 404 error
- Error responses don't leak secrets
- Response includes security headers
- Invalid credentials show proper error
Production Validation:
- Worker responds at
https://your-worker.your-subdomain.workers.dev/tunnels - Real tunnel data is returned
- Logs show successful API calls
- No errors in dashboard analytics
Local development uses localhost:8787 by default. Always test both success and error scenarios before deploying. After deployment, monitor your Worker's performance in the Cloudflare dashboard - you'll see real-time analytics and logs!
Success Criteria
Your production-ready tunnel monitor should achieve all of these goals:
- Functional API: Return structured JSON with tunnel data at
GET /tunnels - Robust Security: Handle auth errors gracefully without exposing tokens
- Proper Headers: Implement CORS and security headers correctly
- Type Safety: Use official Cloudflare SDK TypeScript definitions
- Environment Validation: Check required secrets at startup
- Error Handling: Graceful failure with appropriate HTTP status codes
- Route Protection: Only respond to valid endpoints and methods
Bonus Points:
- Add request timing/performance metrics
- Implement basic rate limiting
- Add tunnel health status indicators
- Include response caching headers
Need Help? Don't worry! The complete solution with best practices is available below. Use it to check your implementation or get unstuck! 👇
Testing and Validation
Testing Checklist
Environment Setup:
- API token has correct permissions
- Account ID is valid and accessible
- Secrets are properly configured in Wrangler
- TypeScript types are generated with
wrangler types
Functionality Testing:
- Worker responds to GET /tunnels requests
- Returns proper JSON format with tunnel information
- Handles cases with no tunnels gracefully
- Non-existent endpoints return 404
- Invalid methods return appropriate errors
Security Testing:
- API tokens are not exposed in responses
- CORS headers are properly configured
- Error messages don't leak sensitive information
- Input validation prevents malicious requests
Error Handling:
- Gracefully handles Cloudflare API failures
- Returns meaningful error messages
- Logs errors for debugging without exposing details
- Maintains proper HTTP status codes
Sample Response Format
{
"success": true,
"timestamp": "2024-07-25T06:30:14.123Z",
"total_tunnels": 3,
"tunnels": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "production-tunnel",
"status": "active",
"created_at": "2024-01-15T10:30:00Z",
"connections": 2,
"active": true
},
{
"id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
"name": "staging-tunnel",
"status": "inactive",
"created_at": "2024-02-01T14:22:00Z",
"connections": 0,
"active": false
}
]
}
Exercise Completion
Once you've successfully implemented this tunnel listing endpoint, you'll have:
- Built a Production-Ready API: Created a secure, scalable endpoint
- Integrated with Cloudflare Services: Connected Workers to Cloudflare's broader ecosystem
- Implemented Security Best Practices: Secured API credentials and validated inputs
- Gained Real-World Experience: Built a tool that could be used in actual security automation workflows
This exercise demonstrates the power of Cloudflare Workers for security automation and sets the foundation for more advanced integrations in the upcoming modules!
Solution
🔒 Please Help Me
This content is password-protected. Enter the password to view the content.