Security Architecture
8.1 Authentication Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ AUTHENTICATION ARCHITECTURE │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ TOKEN LIFECYCLE │ │
│ │ │ │
│ │ 1. Customer creates API token via console │ │
│ │ ┌──────────────┐ │ │
│ │ │ POST /tokens │ ──▶ Generate JWT signed with platform key │ │
│ │ └──────────────┘ │ │ │
│ │ ▼ │ │
│ │ 2. Token stored: ┌──────────────┐ │ │
│ │ - Hash in D1 │ Token Claims │ │ │
│ │ - Cache in KV │ - customer_id│ │ │
│ │ │ - permissions│ │ │
│ │ │ - expires_at │ │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ │ 3. Client uses token in requests │ │
│ │ Authorization: Bearer <token> │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ REQUEST AUTHENTICATION │ │
│ │ │ │
│ │ Request ──▶ Extract Token ──▶ Validate Signature ──▶ Check Expiry │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ KV Cache │ │ JWT Verify │ │ Permission │ │ │
│ │ │ Lookup │ │ (EdDSA) │ │ Check │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
8.2 JWT Token Structure
// auth/src/tokens.ts
interface TokenPayload {
// Standard claims
iss: 'compute-arbitrage';
sub: string; // customer_id
aud: 'api';
exp: number; // Expiration timestamp
iat: number; // Issued at
jti: string; // Unique token ID
// Custom claims
permissions: Permission[];
tier: 'free' | 'pro' | 'enterprise';
metadata: Record<string, string>;
}
type Permission =
| 'workloads:create'
| 'workloads:read'
| 'workloads:delete'
| 'workloads:*'
| 'billing:read'
| 'tokens:manage';
export async function createToken(
env: Env,
customerId: string,
options: TokenOptions
): Promise<{ token: string; id: string }> {
const tokenId = crypto.randomUUID();
const payload: TokenPayload = {
iss: 'compute-arbitrage',
sub: customerId,
aud: 'api',
exp: options.expiresAt || Math.floor(Date.now() / 1000) + 86400 * 365, // 1 year
iat: Math.floor(Date.now() / 1000),
jti: tokenId,
permissions: options.permissions,
tier: options.tier,
metadata: options.metadata || {},
};
// Sign with Ed25519 private key
const token = await signJWT(payload, env.JWT_PRIVATE_KEY);
// Store token metadata (not the token itself)
await env.DB.prepare(`
INSERT INTO api_tokens (id, customer_id, token_hash, name, permissions, created_at, expires_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`).bind(
tokenId,
customerId,
await hashToken(token),
options.name,
JSON.stringify(options.permissions),
Date.now(),
payload.exp * 1000
).run();
// Cache token prefix for fast validation
const tokenPrefix = token.substring(0, 16);
await env.AUTH_KV.put(
`token:${tokenPrefix}`,
JSON.stringify({ customerId, permissions: options.permissions, expiresAt: payload.exp }),
{ expirationTtl: Math.max(3600, payload.exp - Math.floor(Date.now() / 1000)) }
);
return { token, id: tokenId };
}
export async function validateToken(
env: Env,
token: string
): Promise<TokenValidation> {
// Fast path: check KV cache
const tokenPrefix = token.substring(0, 16);
const cached = await env.AUTH_KV.get(`token:${tokenPrefix}`, 'json');
if (cached && cached.expiresAt > Math.floor(Date.now() / 1000)) {
return {
valid: true,
customerId: cached.customerId,
permissions: cached.permissions,
};
}
// Slow path: full JWT validation
try {
const payload = await verifyJWT(token, env.JWT_PUBLIC_KEY);
// Check if token was revoked
const tokenRecord = await env.DB.prepare(
'SELECT * FROM api_tokens WHERE id = ?'
).bind(payload.jti).first();
if (!tokenRecord) {
return { valid: false, error: 'Token revoked' };
}
// Update cache
await env.AUTH_KV.put(
`token:${tokenPrefix}`,
JSON.stringify({
customerId: payload.sub,
permissions: payload.permissions,
expiresAt: payload.exp,
}),
{ expirationTtl: Math.min(3600, payload.exp - Math.floor(Date.now() / 1000)) }
);
return {
valid: true,
customerId: payload.sub,
permissions: payload.permissions,
};
} catch (e) {
return { valid: false, error: e.message };
}
}
8.3 Network Security
┌─────────────────────────────────────────────────────────────────────────────┐
│ NETWORK SECURITY MODEL │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ End User Access │ │
│ │ │ │
│ │ Users ──▶ Cloudflare Edge ──▶ Workers ──▶ Workload Instances │ │
│ │ (DDoS protection) (Auth) (Isolated VPCs) │ │
│ │ │ │
│ │ - All traffic through Cloudflare (no direct instance access) │ │
│ │ - TLS 1.3 everywhere │ │
│ │ - JWT validation at edge │ │
│ │ - Per-customer rate limiting │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Cloud Infrastructure Security │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Customer │ │ Customer │ │ │
│ │ │ VPC/VNet │ │ VPC/VNet │ │ │
│ │ │ │ │ │ │ │
│ │ │ ┌────────┐ │ │ ┌────────┐ │ │ │
│ │ │ │Workload│ │ │ │Workload│ │ │ │
│ │ │ │Instance│ │ │ │Instance│ │ │ │
│ │ │ └────────┘ │ │ └────────┘ │ │ │
│ │ │ │ │ │ │ │
│ │ │ Security │ │ Security │ │ │
│ │ │ Groups: │ │ Groups: │ │ │
│ │ │ - Ingress: │ │ - Ingress: │ │ │
│ │ │ CF IPs │ │ CF IPs │ │ │
│ │ │ - Egress: │ │ - Egress: │ │ │
│ │ │ Internet │ │ Internet │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ │ - Full VPC isolation per customer │ │
│ │ - Security groups allow only Cloudflare IPs │ │
│ │ - IAM roles scoped to minimum permissions │ │
│ │ - All provisioning via Kivera (audit + policy enforcement) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
8.4 Secrets Management
// All secrets stored in Cloudflare Workers Secrets (encrypted at rest)
// Accessed via env bindings
interface Env {
// Platform secrets
JWT_PRIVATE_KEY: string;
JWT_PUBLIC_KEY: string;
// Kivera credentials
KIVERA_USERNAME: string;
KIVERA_PASSWORD: string;
KIVERA_PROXY_ENDPOINT: string;
// Per-provider credentials (stored per customer in encrypted format)
// Actual credentials fetched from encrypted storage at runtime
CREDENTIALS_ENCRYPTION_KEY: string;
}
// Customer credentials stored encrypted in D1
// Decrypted only when needed for provisioning
async function getCustomerCloudCredentials(
env: Env,
customerId: string,
provider: string
): Promise<CloudCredentials> {
const encrypted = await env.DB.prepare(`
SELECT encrypted_credentials FROM customer_cloud_accounts
WHERE customer_id = ? AND provider = ?
`).bind(customerId, provider).first();
if (!encrypted) {
throw new Error(`No ${provider} credentials for customer`);
}
// Decrypt using platform key
return decryptCredentials(encrypted.encrypted_credentials, env.CREDENTIALS_ENCRYPTION_KEY);
}