Skip to content

liadtal/cdb-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cosmos DB Reverse Proxy – Proof of Concept

A transparent .NET 8 reverse proxy that sits between Azure AI Foundry and Cosmos DB. It intercepts document writes to encrypt the content field with AES-256-GCM before it reaches the database, and decrypts it on reads so callers see the original data.

Why the proxy exists

Azure AI Foundry workloads write documents to Cosmos DB. Some documents contain a "content" field that must be encrypted at rest before it reaches the database. Rather than modifying every client, this transparent reverse proxy intercepts document-write operations and encrypts the sensitive field in-flight.

The proxy is intentionally minimal:

  • Default behavior is pass-through. Reads, queries, metadata, change feed, patch, and batch requests flow to Cosmos DB untouched.
  • Transparent encryption/decryption. Document writes get content encrypted; reads get it decrypted. Callers never see ciphertext.
  • Removable. Point the AI Foundry connection target back to the real Cosmos endpoint and the system works without the proxy (documents already stored will remain encrypted).

Architecture

flowchart LR
    A[AI Foundry Agent] -->|HTTPS<br/>CosmosDB connection target| C[Web App - Proxy]
    C -->|HTTPS<br/>public endpoint| D[Cosmos DB]

    style C fill:#f9f,stroke:#333
Loading

Routing

sequenceDiagram
    participant Client as AI Foundry Agent
    participant Proxy as Web App (Proxy)
    participant Cosmos as Cosmos DB

    Client->>Proxy: HTTPS request (via connection target)
    Proxy->>Cosmos: Forward to public endpoint
    Cosmos-->>Proxy: Response
    Proxy-->>Client: Response (decrypted if needed)
Loading
  1. The AI Foundry project has a CosmosDB connection whose target points to the proxy Web App URL (e.g. https://proxy-xxx.azurewebsites.net).
  2. The capability host's threadStorageConnections references this connection so agents route Cosmos DB traffic to the proxy.
  3. The proxy forwards all requests to the real Cosmos DB public endpoint (configured via the COSMOS_ENDPOINT env var).

Request flow

flowchart TD
    A[Incoming Request] --> B{POST or PUT<br/>and path contains /docs?}
    B -->|No| C[Pass through unchanged]
    B -->|Yes| D{Body has 'query' property?}
    D -->|Yes| E[Cosmos SQL query — pass through]
    D -->|No| F[Encrypt 'content' field<br/>AES-256-GCM]
    F --> G[Add cdbProxyMetadata]
    G --> H[Forward to Cosmos DB]
    C --> H
    E --> H
    H --> I{Response has JSON body?}
    I -->|No| J[Stream response as-is]
    I -->|Yes| K[Decrypt 'content' field<br/>Strip cdbProxyMetadata]
    K --> L[Return to caller]
    J --> L
Loading

Interception rules

Condition Action
POST/PUT and path contains /docs and body has no query property Encrypt content field (AES-256-GCM), add cdbProxyMetadata, forward
POST to /docs with query property Cosmos SQL query — pass through unchanged
JSON response from Cosmos Decrypt content field, strip cdbProxyMetadata
Everything else Pass through unchanged (headers, body, auth tokens)

Encryption details

  • Algorithm: AES-256-GCM
  • Key: 32-byte key provided via ENCRYPTION_KEY environment variable (base64-encoded)
  • Envelope format: ENC + type byte (0x01 = base64 string, 0x02 = JSON), then the plaintext
  • Stored as: base64( nonce[12] + tag[16] + ciphertext )
  • Decryption handles both the envelope format and a legacy fallback

Components

graph TD
    P[Program.cs<br/>Entry point & DI setup] --> H[CosmosProxyHandler.cs<br/>Proxy logic, encrypt/decrypt]
    P --> PS[AiFoundryPingService.cs<br/>Background health-check]
    PS --> TC[ThreadContextCache.cs<br/>Thread → Tenant/User mapping]
    H --> TC
Loading

The Web App runs on a Linux App Service Plan (B1) with HTTPS enforced and always-on enabled. It reaches Cosmos DB over the public endpoint — no VNET, private endpoint, or private DNS zone is required.

Project structure

File Purpose
src/Program.cs Entry point — configures DI, HTTP client, routing, and the catch-all proxy route
src/CosmosProxyHandler.cs Core proxy handler — request forwarding, AES-256-GCM encrypt/decrypt, metadata stamping
src/AiFoundryPingService.cs BackgroundService that creates an AI Foundry agent and pings it every 60 s
src/ThreadContextCache.cs In-memory cache (IMemoryCache) mapping AI Foundry thread IDs to tenant/user pairs
src/CosmosDBProxy.csproj .NET 8 project — depends on Azure.AI.Agents.Persistent and Azure.Identity
infra/main.arm.json ARM template — Cosmos DB, Web App, AI Foundry project, Storage, AI Search, RBAC
infra/deploy.ps1 PowerShell deployment script — build, zip, ARM deploy, code deploy
monitoring/validation-queries.kql KQL queries for Application Insights — ping health, proxy success rate, encryption counts, error tracking

Background ping service

AiFoundryPingService runs as a hosted BackgroundService:

  1. Connects to AI Foundry using DefaultAzureCredential
  2. Creates (or finds) an agent named cosmos-proxy-ping
  3. Every 60 seconds: creates a thread, sends a health-check message, polls for the agent reply, then deletes the thread
  4. Stores thread → tenant/user mappings in ThreadContextCache so the proxy can resolve tenant context on intercepted writes

Requires PROJECT_ENDPOINT and optionally MODEL_DEPLOYMENT_NAME (defaults to gpt-4o-mini).

Environment variables

Variable Required Description
COSMOS_ENDPOINT Yes Upstream Cosmos DB endpoint (e.g. https://<account>.documents.azure.com)
ENCRYPTION_KEY Yes Base64-encoded AES-256 key (must decode to ≥ 32 bytes)
PROJECT_ENDPOINT No AI Foundry project endpoint — enables the background ping service
MODEL_DEPLOYMENT_NAME No Model deployment for the ping agent (default: gpt-4o-mini)

Deployment

The infra/deploy.ps1 script handles the full deployment:

# Full deployment (infrastructure + code)
.\infra\deploy.ps1 -ResourceGroupName "my-rg" -Location "eastus"

# Code-only deployment (skip ARM template)
.\infra\deploy.ps1 -ResourceGroupName "my-rg" -AppOnly

Steps: dotnet publish → zip → ARM template deploy → az webapp deploy.

Running locally

cd src
export COSMOS_ENDPOINT="https://<your-account>.documents.azure.com"
export ENCRYPTION_KEY="<base64-encoded-32-byte-key>"
dotnet run

Requests to http://localhost:5000/dbs/mydb/colls/mycoll/docs will be proxied to the real Cosmos endpoint.

Monitoring

The monitoring/validation-queries.kql file contains Application Insights (KQL) queries for:

  • Agent ping success count and time-series trends
  • Proxy request throughput and success rate
  • Encryption/decryption operation counts
  • Error and exception tracking
  • Tenant context resolution verification

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors