Skip to content

Commit 0956330

Browse files
Mossakaclaude
andauthored
docs: convert API proxy docs to Starlight format (#941)
- Add Starlight frontmatter (title, description) to both docs - Convert GitHub blockquotes to Starlight admonitions - Fix OPENAI_BASE_URL to include /v1 suffix - Fix ANTHROPIC_BASE_URL to use IP address - Remove inaccurate Squid config section - Fix NO_PROXY value to match actual code - Replace stale line number references - Add health check and body limit documentation - Add cross-references between related docs Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4a64568 commit 0956330

2 files changed

Lines changed: 254 additions & 265 deletions

File tree

docs/api-proxy-sidecar.md

Lines changed: 116 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
# API Proxy Sidecar for Credential Management
1+
---
2+
title: API Proxy Sidecar
3+
description: Secure LLM API credential management using an isolated proxy sidecar container.
4+
---
25

36
The AWF firewall supports an optional Node.js-based API proxy sidecar that securely holds LLM API credentials and automatically injects authentication headers while routing all traffic through Squid to respect domain whitelisting.
47

5-
> [!NOTE]
6-
> For a comprehensive deep dive into how AWF handles authentication tokens and credential isolation, see the [Authentication Architecture](authentication-architecture.md) guide.
8+
:::note
9+
For a deep dive into how AWF handles authentication tokens and credential isolation, see the [Authentication Architecture](./authentication-architecture.md) guide.
10+
:::
711

812
## Overview
913

1014
When enabled, the API proxy sidecar:
11-
- **Isolates credentials**: API keys never exposed to agent container
15+
- **Isolates credentials**: API keys are never exposed to the agent container
1216
- **Auto-authentication**: Automatically injects Bearer tokens and API keys
1317
- **Dual provider support**: Supports both OpenAI (Codex) and Anthropic (Claude) APIs
14-
- **Transparent proxying**: Agent code uses standard environment variables
18+
- **Transparent proxying**: Agent code uses standard SDK environment variables
1519
- **Squid routing**: All traffic routes through Squid to respect domain whitelisting
1620

1721
## Architecture
@@ -29,9 +33,9 @@ When enabled, the API proxy sidecar:
2933
│ │ │ Agent Container │ │
3034
│ │ │ 172.30.0.20 │ │
3135
│ │ │ OPENAI_BASE_URL= │ │
32-
│ │ │ http://api-proxy:10000 │────┘
36+
│ │ │ http://172.30.0.30:10000/v1│────┘
3337
│ │ │ ANTHROPIC_BASE_URL= │
34-
│ │ │ http://api-proxy:10001
38+
│ │ │ http://172.30.0.30:10001 │
3539
│ │ └──────────────────────────────┘
3640
│ │
3741
└─────────┼─────────────────────────────────────┘
@@ -40,153 +44,175 @@ When enabled, the API proxy sidecar:
4044
api.openai.com or api.anthropic.com
4145
```
4246

43-
**Traffic Flow:**
44-
1. Agent makes request to `api-proxy:10000` or `api-proxy:10001`
45-
2. API proxy injects authentication headers
46-
3. API proxy routes through Squid via HTTP_PROXY/HTTPS_PROXY
47-
4. Squid enforces domain whitelist (only allowed domains pass)
48-
5. Request reaches api.openai.com or api.anthropic.com
47+
**Traffic flow:**
48+
1. Agent makes a request to `172.30.0.30:10000` (OpenAI) or `172.30.0.30:10001` (Anthropic)
49+
2. API proxy strips any client-supplied auth headers and injects the real credentials
50+
3. API proxy routes the request through Squid via `HTTP_PROXY`/`HTTPS_PROXY`
51+
4. Squid enforces the domain whitelist (only allowed domains pass)
52+
5. Request reaches `api.openai.com` or `api.anthropic.com`
4953

5054
## Usage
5155

52-
### Basic Usage
56+
### Basic usage
5357

5458
```bash
5559
# Set API keys in environment
5660
export OPENAI_API_KEY="sk-..."
5761
export ANTHROPIC_API_KEY="sk-ant-..."
5862

5963
# Enable API proxy sidecar
60-
awf --enable-api-proxy \
64+
sudo awf --enable-api-proxy \
6165
--allow-domains api.openai.com,api.anthropic.com \
6266
-- your-command
6367
```
6468

65-
### Codex (OpenAI) Example
69+
### Codex (OpenAI) example
6670

6771
```bash
6872
export OPENAI_API_KEY="sk-..."
6973

70-
awf --enable-api-proxy \
74+
sudo awf --enable-api-proxy \
7175
--allow-domains api.openai.com \
7276
-- npx @openai/codex -p "write a hello world function"
7377
```
7478

75-
The agent container will automatically use `http://api-proxy:10000` as the base URL.
79+
The agent container automatically uses `http://172.30.0.30:10000/v1` as the OpenAI base URL.
7680

77-
### Claude Code Example
81+
### Claude Code example
7882

7983
```bash
8084
export ANTHROPIC_API_KEY="sk-ant-..."
8185

82-
awf --enable-api-proxy \
86+
sudo awf --enable-api-proxy \
8387
--allow-domains api.anthropic.com \
8488
-- claude-code "write a hello world function"
8589
```
8690

87-
The agent container will automatically use `http://api-proxy:10001` as the base URL.
91+
The agent container automatically uses `http://172.30.0.30:10001` as the Anthropic base URL.
8892

89-
### Both Providers
93+
### Both providers
9094

9195
```bash
9296
export OPENAI_API_KEY="sk-..."
9397
export ANTHROPIC_API_KEY="sk-ant-..."
9498

95-
awf --enable-api-proxy \
99+
sudo awf --enable-api-proxy \
96100
--allow-domains api.openai.com,api.anthropic.com \
97101
-- your-multi-llm-tool
98102
```
99103

100-
## Environment Variables
104+
## Environment variables
101105

102-
When API keys are provided, the sidecar sets these environment variables in the agent container:
106+
When API keys are provided, AWF sets these environment variables in the agent container:
103107

104-
| Variable | Value | When Set | Description |
108+
| Variable | Value | When set | Description |
105109
|----------|-------|----------|-------------|
106-
| `OPENAI_BASE_URL` | `http://api-proxy:10000` | When `OPENAI_API_KEY` is provided | OpenAI API proxy endpoint |
107-
| `ANTHROPIC_BASE_URL` | `http://api-proxy:10001` | When `ANTHROPIC_API_KEY` is provided | Anthropic API proxy endpoint |
110+
| `OPENAI_BASE_URL` | `http://172.30.0.30:10000/v1` | `OPENAI_API_KEY` is set | OpenAI API proxy endpoint |
111+
| `ANTHROPIC_BASE_URL` | `http://172.30.0.30:10001` | `ANTHROPIC_API_KEY` is set | Anthropic API proxy endpoint |
108112

109113
These are standard environment variables recognized by:
110-
- OpenAI Python SDK
111-
- OpenAI Node.js SDK
112-
- Anthropic Python SDK
113-
- Anthropic TypeScript SDK
114-
- Codex CLI tools
114+
- OpenAI Python SDK (`openai`)
115+
- OpenAI Node.js SDK (`openai`)
116+
- Anthropic Python SDK (`anthropic`)
117+
- Anthropic TypeScript SDK (`@anthropic-ai/sdk`)
118+
- Codex CLI
115119
- Claude Code CLI
116120

117-
## Security Benefits
121+
:::tip
122+
You don't need to change any agent code. The SDKs automatically read `*_BASE_URL` environment variables and redirect API calls through the proxy.
123+
:::
118124

119-
### Credential Isolation
125+
## Security benefits
126+
127+
### Credential isolation
120128

121129
API keys are held in the sidecar container, not the agent:
122-
- Agent code cannot read API keys from environment
123-
- Compromised agent cannot exfiltrate credentials
124-
- Keys are not exposed to the agent container’s stdout/stderr logs
125-
- Keys are stored in sidecar and deployment configuration on disk; protect host filesystem and config accordingly (only non-sensitive key prefixes may be logged for debugging)
130+
- Agent code cannot read API keys from environment variables
131+
- A compromised agent cannot exfiltrate credentials
132+
- Keys are not exposed in the agent container's stdout/stderr logs
133+
134+
:::danger[Protect host credentials]
135+
API keys are stored in the sidecar container's environment and in the Docker Compose configuration on disk. Protect the host filesystem and configuration accordingly. Only non-sensitive key prefixes are logged for debugging.
136+
:::
126137

127-
### Network Isolation
138+
### Network isolation
128139

129140
The proxy enforces domain-level egress control:
130-
- Agent can only reach `api-proxy` hostname
131-
- Sidecar routes ALL traffic through Squid proxy
132-
- Squid enforces domain whitelist (L7 filtering)
133-
- No firewall exemption needed for sidecar
141+
- The agent can only reach the API proxy IP (`172.30.0.30`) for API calls
142+
- The sidecar routes all traffic through Squid proxy
143+
- Squid enforces the domain whitelist (L7 filtering)
144+
- iptables rules prevent the agent from bypassing the proxy
134145

135-
### Resource Limits
146+
### Resource limits
136147

137148
The sidecar has strict resource constraints:
138-
- 512MB memory limit
149+
- 512 MB memory limit
139150
- 100 process limit
140-
- All unnecessary capabilities dropped
151+
- All capabilities dropped
141152
- `no-new-privileges` security option
142153

143-
## How It Works
154+
## How it works
144155

145-
### 1. Container Startup
156+
### 1. Container startup
146157

147-
When `--enable-api-proxy` is set:
148-
1. Node.js API proxy starts at 172.30.0.30
149-
2. API keys passed via environment variables
150-
3. HTTP_PROXY/HTTPS_PROXY configured to route through Squid
151-
4. Agent container waits for sidecar health check
158+
When you pass `--enable-api-proxy`:
159+
1. AWF starts a Node.js API proxy at `172.30.0.30`
160+
2. API keys are passed to the sidecar via environment variables
161+
3. `HTTP_PROXY`/`HTTPS_PROXY` in the sidecar are configured to route through Squid
162+
4. The agent container waits for the sidecar health check to pass
152163

153-
### 2. Request Flow
164+
### 2. Request flow
154165

155166
```
156167
Agent Code
157-
↓ (makes HTTP request to api-proxy:10000)
168+
↓ (HTTP request to 172.30.0.30:10000/v1)
158169
Node.js API Proxy
170+
↓ (strips client auth headers)
159171
↓ (injects Authorization: Bearer $OPENAI_API_KEY)
160-
↓ (routes via HTTP_PROXY to Squid)
172+
↓ (routes via HTTPS_PROXY to Squid)
161173
Squid Proxy
162174
↓ (enforces domain whitelist)
163175
↓ (TLS connection to api.openai.com)
164176
OpenAI API
165177
```
166178

167-
### 3. Header Injection
179+
### 3. Header injection
180+
181+
The Node.js proxy automatically:
182+
- **Strips** any client-supplied `Authorization`, `x-api-key`, `Proxy-Authorization`, and `X-Forwarded-*` headers
183+
- **Injects** the correct authentication headers:
184+
- **OpenAI**: `Authorization: Bearer $OPENAI_API_KEY`
185+
- **Anthropic**: `x-api-key: $ANTHROPIC_API_KEY` and `anthropic-version: 2023-06-01` (if not already set by the client)
186+
187+
:::caution
188+
The proxy enforces a 10 MB request body size limit to prevent denial-of-service via large payloads.
189+
:::
168190

169-
The Node.js proxy automatically adds:
170-
- **OpenAI**: `Authorization: Bearer $OPENAI_API_KEY`
171-
- **Anthropic**: `x-api-key: $ANTHROPIC_API_KEY` and `anthropic-version: 2023-06-01`
191+
### 4. Pre-flight health check
172192

173-
## Configuration Reference
193+
Before running the user command, the agent container runs a health check script (`api-proxy-health-check.sh`) that verifies:
194+
- API keys are **not** present in the agent environment (credential isolation working)
195+
- The API proxy is reachable and responding (connectivity established)
174196

175-
### CLI Options
197+
If either check fails, the agent exits immediately without running the user command.
198+
199+
## Configuration reference
200+
201+
### CLI options
176202

177203
```bash
178-
awf --enable-api-proxy [OPTIONS] -- COMMAND
204+
sudo awf --enable-api-proxy [OPTIONS] -- COMMAND
179205
```
180206

181207
**Required environment variables** (at least one):
182-
- `OPENAI_API_KEY` - OpenAI API key
183-
- `ANTHROPIC_API_KEY` - Anthropic API key
208+
- `OPENAI_API_KEY` OpenAI API key
209+
- `ANTHROPIC_API_KEY` Anthropic API key
184210

185211
**Recommended domain whitelist**:
186-
- `api.openai.com` - For OpenAI/Codex
187-
- `api.anthropic.com` - For Anthropic/Claude
212+
- `api.openai.com` — for OpenAI/Codex
213+
- `api.anthropic.com` — for Anthropic/Claude
188214

189-
### Container Configuration
215+
### Container configuration
190216

191217
The sidecar container:
192218
- **Image**: `ghcr.io/github/gh-aw-firewall/api-proxy:latest`
@@ -195,9 +221,9 @@ The sidecar container:
195221
- **Ports**: 10000 (OpenAI), 10001 (Anthropic)
196222
- **Proxy**: Routes via Squid at `http://172.30.0.10:3128`
197223

198-
### Health Check
224+
### Health check
199225

200-
API proxy healthcheck on `/health` endpoint:
226+
Docker healthcheck on the `/health` endpoint (port 10000):
201227
- **Interval**: 5s
202228
- **Timeout**: 3s
203229
- **Retries**: 5
@@ -213,6 +239,7 @@ API proxy healthcheck on `/health` endpoint:
213239
```
214240

215241
**Solution**: Export API keys before running awf:
242+
216243
```bash
217244
export OPENAI_API_KEY="sk-..."
218245
# or
@@ -221,40 +248,45 @@ export ANTHROPIC_API_KEY="sk-ant-..."
221248

222249
### Sidecar health check failing
223250

224-
Check if API proxy container started:
251+
Check if the API proxy container started:
252+
225253
```bash
226254
docker ps | grep awf-api-proxy
227255
```
228256

229257
View API proxy logs:
258+
230259
```bash
231260
docker logs awf-api-proxy
232261
```
233262

234263
### API requests timing out
235264

236-
Ensure domains are whitelisted:
265+
Ensure the API domains are whitelisted:
266+
237267
```bash
238-
--allow-domains api.openai.com,api.anthropic.com
268+
sudo awf --enable-api-proxy \
269+
--allow-domains api.openai.com,api.anthropic.com \
270+
-- your-command
239271
```
240272

241-
Check Squid logs for denials:
273+
Check Squid logs for denied requests:
274+
242275
```bash
243276
docker exec awf-squid cat /var/log/squid/access.log | grep DENIED
244277
```
245278

246279
## Limitations
247280

248281
- Only supports OpenAI and Anthropic APIs
249-
- Keys must be in environment (not file-based)
282+
- Keys must be set as environment variables (not file-based)
250283
- No support for Azure OpenAI endpoints
251-
- No request/response logging (by design for security)
284+
- No request/response logging (by design, for security)
252285

253-
## Future Enhancements
286+
## Related documentation
254287

255-
Potential improvements:
256-
- Support for additional LLM providers
257-
- Request rate limiting
258-
- Token usage tracking
259-
- Key rotation support
260-
- Vault integration for key storage
288+
- [Authentication Architecture](./authentication-architecture.md) — detailed credential isolation internals
289+
- [Security](./security.md) — overall security model
290+
- [Environment Variables](./environment.md) — environment variable configuration
291+
- [Troubleshooting](./troubleshooting.md) — common issues and solutions
292+
- [Architecture](./architecture.md) — overall system architecture

0 commit comments

Comments
 (0)