Skip to content
Merged
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
29 changes: 0 additions & 29 deletions containers/api-proxy/providers/gemini.js

This file was deleted.

14 changes: 13 additions & 1 deletion containers/api-proxy/providers/google-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,16 @@ function makeGoogleProviderFactory(providerKey) {
return (env, deps = {}) => createGoogleProviderAdapter(providerKey, env, deps);
}

module.exports = { createGoogleApiKeyAdapter, createGoogleProviderAdapter, makeGoogleProviderFactory };
const GOOGLE_PROVIDER_ADAPTER_FACTORIES = Object.fromEntries(
Object.keys(GOOGLE_PROVIDER_SPECS).map((providerKey) => [
providerKey,
makeGoogleProviderFactory(providerKey),
]),
);

module.exports = {
createGoogleApiKeyAdapter,
createGoogleProviderAdapter,
makeGoogleProviderFactory,
GOOGLE_PROVIDER_ADAPTER_FACTORIES,
};
30 changes: 21 additions & 9 deletions containers/api-proxy/providers/google-adapter.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use strict';

const { createGoogleProviderAdapter, makeGoogleProviderFactory } = require('./google-adapter');
const {
createGoogleProviderAdapter,
makeGoogleProviderFactory,
GOOGLE_PROVIDER_ADAPTER_FACTORIES,
} = require('./google-adapter');
const { GOOGLE_PROVIDER_SPECS } = require('./google-provider-specs');
const { createGeminiAdapter } = require('./gemini');
const { createVertexAdapter } = require('./vertex');

describe('createGoogleProviderAdapter', () => {
it('throws for an unknown provider key', () => {
Expand All @@ -17,6 +19,16 @@ describe('createGoogleProviderAdapter', () => {
});
});

it('exports factories for every declared Google provider', () => {
expect(Object.keys(GOOGLE_PROVIDER_ADAPTER_FACTORIES)).toEqual(Object.keys(GOOGLE_PROVIDER_SPECS));
expect(GOOGLE_PROVIDER_ADAPTER_FACTORIES.gemini({ GEMINI_API_KEY: 'key' }).getAuthHeaders()).toEqual({
'x-goog-api-key': 'key',
});
expect(GOOGLE_PROVIDER_ADAPTER_FACTORIES.vertex({ GOOGLE_API_KEY: 'key' }).getAuthHeaders()).toEqual({
'x-goog-api-key': 'key',
});
});

it('derives gemini ports, targets and messages from the spec', () => {
const adapter = createGoogleProviderAdapter('gemini', {});
expect(adapter.name).toBe('gemini');
Expand Down Expand Up @@ -47,15 +59,15 @@ describe('createGoogleProviderAdapter', () => {
});

it('applies the gemini URL transform and omits it for vertex', () => {
const gemini = createGeminiAdapter({ GEMINI_API_KEY: 'k' });
const vertex = createVertexAdapter({ GOOGLE_API_KEY: 'k' });
const gemini = GOOGLE_PROVIDER_ADAPTER_FACTORIES.gemini({ GEMINI_API_KEY: 'k' });
const vertex = GOOGLE_PROVIDER_ADAPTER_FACTORIES.vertex({ GOOGLE_API_KEY: 'k' });
expect(gemini.transformRequestUrl('/v1beta/models?key=secret')).toBe('/v1beta/models');
expect(vertex.transformRequestUrl).toBeUndefined();
});

it('exposes a models fetch config only when the spec defines a models path', () => {
const gemini = createGeminiAdapter({ GEMINI_API_KEY: 'k' });
const vertex = createVertexAdapter({ GOOGLE_API_KEY: 'k' });
const gemini = GOOGLE_PROVIDER_ADAPTER_FACTORIES.gemini({ GEMINI_API_KEY: 'k' });
const vertex = GOOGLE_PROVIDER_ADAPTER_FACTORIES.vertex({ GOOGLE_API_KEY: 'k' });
expect(gemini.getModelsFetchConfig()).toMatchObject({
url: 'https://generativelanguage.googleapis.com/v1beta/models',
});
Expand All @@ -64,7 +76,7 @@ describe('createGoogleProviderAdapter', () => {
});

it('authenticates both providers with the x-goog-api-key header', () => {
expect(createGeminiAdapter({ GEMINI_API_KEY: 'g' }).getAuthHeaders()).toEqual({ 'x-goog-api-key': 'g' });
expect(createVertexAdapter({ GOOGLE_API_KEY: 'v' }).getAuthHeaders()).toEqual({ 'x-goog-api-key': 'v' });
expect(GOOGLE_PROVIDER_ADAPTER_FACTORIES.gemini({ GEMINI_API_KEY: 'g' }).getAuthHeaders()).toEqual({ 'x-goog-api-key': 'g' });
expect(GOOGLE_PROVIDER_ADAPTER_FACTORIES.vertex({ GOOGLE_API_KEY: 'v' }).getAuthHeaders()).toEqual({ 'x-goog-api-key': 'v' });
});
});
7 changes: 3 additions & 4 deletions containers/api-proxy/providers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
const { createOpenAIAdapter } = require('./openai');
const { createAnthropicAdapter } = require('./anthropic');
const { createCopilotAdapter } = require('./copilot');
const { createGeminiAdapter } = require('./gemini');
const { createVertexAdapter } = require('./vertex');
const { GOOGLE_PROVIDER_ADAPTER_FACTORIES } = require('./google-adapter');

/**
* @typedef {Object} ProbeConfig
Expand Down Expand Up @@ -104,8 +103,8 @@ function createAllAdapters(env, deps = {}) {
const openai = createOpenAIAdapter(env, { bodyTransform: deps.openaiBodyTransform || null });
const anthropic = createAnthropicAdapter(env, { bodyTransform: deps.anthropicBodyTransform || null });
const copilot = createCopilotAdapter(env, { bodyTransform: deps.copilotBodyTransform || null });
const gemini = createGeminiAdapter(env, { bodyTransform: deps.geminiBodyTransform || null });
const vertex = createVertexAdapter(env, { bodyTransform: deps.vertexBodyTransform || null });
const gemini = GOOGLE_PROVIDER_ADAPTER_FACTORIES.gemini(env, { bodyTransform: deps.geminiBodyTransform || null });
const vertex = GOOGLE_PROVIDER_ADAPTER_FACTORIES.vertex(env, { bodyTransform: deps.vertexBodyTransform || null });

return [openai, anthropic, copilot, gemini, vertex];
}
Expand Down
31 changes: 0 additions & 31 deletions containers/api-proxy/providers/vertex.js

This file was deleted.

4 changes: 2 additions & 2 deletions containers/api-proxy/server.auth-matrix.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
const { createOpenAIAdapter } = require('./providers/openai');
const { createAnthropicAdapter } = require('./providers/anthropic');
const { createCopilotAdapter } = require('./providers/copilot');
const { createGeminiAdapter } = require('./providers/gemini');
const { createVertexAdapter } = require('./providers/vertex');
const { GOOGLE_PROVIDER_ADAPTER_FACTORIES } = require('./providers/google-adapter');
const { gemini: createGeminiAdapter, vertex: createVertexAdapter } = GOOGLE_PROVIDER_ADAPTER_FACTORIES;

// ---------------------------------------------------------------------------
// Helpers
Expand Down
10 changes: 5 additions & 5 deletions docs/auth-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ Selecting `AWF_AUTH_PROVIDER=aws` signs Copilot-adapter HTTP requests at final d
## Provider: Google Gemini

**Port:** 10003
**Implementation:** `containers/api-proxy/providers/gemini.js`
**Implementation:** `containers/api-proxy/providers/google-adapter.js` (Gemini factory from the declarative `google-provider-specs.js` registry)

### Static API Key

Expand Down Expand Up @@ -277,7 +277,7 @@ Google says the Gemini API will reject standard API keys beginning in September
## Provider: Google Vertex AI

**Port:** 10004
**Implementation:** `containers/api-proxy/providers/vertex.js` (shares `createGoogleApiKeyAdapter` with the Gemini adapter via `google-adapter.js`)
**Implementation:** `containers/api-proxy/providers/google-adapter.js` (Vertex factory from the declarative `google-provider-specs.js` registry)

### Static API Key

Expand Down Expand Up @@ -461,10 +461,10 @@ Adds `x-session-id` header automatically in BYOK mode unless already present.
| Copilot | AWS Bedrock OIDC + SigV4 | — | ✅ | `aws-oidc-token-provider.js`, `server.auth-matrix.test.js` |
| Copilot | GCP OIDC | — | ✅ | `gcp-oidc-token-provider.js`, `server.auth-matrix.test.js` |
| Copilot | GHES + BYOK | GHES | ✅ | `server.auth-matrix.test.js` |
| Gemini | Static key | — | ✅ | `gemini.js`, `google-adapter.js` |
| Gemini | Static key | — | ✅ | `google-adapter.js`, `google-provider-specs.js` |
| Gemini | GCP WIF | — | ❌ not impl | Use the OpenAI adapter with GCP OIDC pointed at a Vertex endpoint instead (see [Google Gemini](#provider-google-gemini)) |
| Vertex AI | Static key | — | ✅ | `vertex.js`, `google-adapter.js` |
| Vertex AI | GCP WIF | — | ❌ not impl | No OIDC support in `vertex.js`; see [Provider: Google Vertex AI](#provider-google-vertex-ai) |
| Vertex AI | Static key | — | ✅ | `google-adapter.js`, `google-provider-specs.js` |
| Vertex AI | GCP WIF | — | ❌ not impl | No OIDC support in the shared Google adapter; see [Provider: Google Vertex AI](#provider-google-vertex-ai) |

:::note
"Implementation" column lists source files, not line numbers — line references go stale quickly as the code evolves. Use your editor's search to locate the relevant logic within each file.
Expand Down
2 changes: 1 addition & 1 deletion docs/authentication-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ OIDC authentication is configured via `apiProxy.auth` in the AWF config file or
| `containers/api-proxy/providers/openai.js` | OpenAI adapter — selects OIDC provider based on `AWF_AUTH_PROVIDER` |
| `containers/api-proxy/providers/anthropic.js` | Anthropic adapter — static `x-api-key` or WIF `Authorization: Bearer` |
| `containers/api-proxy/providers/copilot.js`, `copilot-auth.js`, `copilot-byok.js` | Copilot adapter — GitHub token, BYOK, and OIDC handling, `token`/`Bearer` prefix logic |
| `containers/api-proxy/providers/gemini.js`, `vertex.js`, `google-adapter.js`, `google-provider-specs.js` | Gemini and Vertex AI adapters (declarative specs) — static `x-goog-api-key` only, no OIDC |
| `containers/api-proxy/providers/google-adapter.js`, `google-provider-specs.js` | Gemini and Vertex AI adapters (declarative specs) — static `x-goog-api-key` only, no OIDC |
| `containers/agent/setup-iptables.sh` | iptables rules for api-proxy routing |
| `containers/agent/entrypoint.sh` | Entrypoint token cleanup, capability drop |
| `containers/agent/api-proxy-health-check.sh` | Pre-flight credential isolation verification |
Expand Down
Loading