Skip to content

fix(api-proxy): add Azure/AWS/GCP OIDC support to Copilot adapter#4407

Merged
zarenner merged 5 commits into
mainfrom
copilot/smoke-copilot-byok-aoai-entra
Jun 5, 2026
Merged

fix(api-proxy): add Azure/AWS/GCP OIDC support to Copilot adapter#4407
zarenner merged 5 commits into
mainfrom
copilot/smoke-copilot-byok-aoai-entra

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 5, 2026

The smoke-copilot-byok-aoai-entra agent job was failing with repeated 503 Credentials for GitHub Copilot (port 10002) are not configured errors. The new workflow exercises Copilot CLI BYOK against Azure OpenAI via GitHub OIDC → Entra federation, but the api-proxy's Copilot adapter only knew about static COPILOT_GITHUB_TOKEN / COPILOT_PROVIDER_API_KEY credentials — there was no path to mint an Azure AD token from the OIDC env vars.

Since src/services/api-proxy-credential-env.ts rewrites COPILOT_PROVIDER_BASE_URL to the port-10002 sidecar whenever any Copilot env is set, Copilot CLI traffic always lands on this adapter regardless of upstream, so the gap had to be closed there.

Changes

  • containers/api-proxy/providers/copilot.js — mirror the openai.js OIDC pattern:

    • Construct an OidcTokenProvider (Azure), AwsOidcTokenProvider, or GcpOidcTokenProvider when AWF_AUTH_TYPE=github-oidc and no static credential is set; static keys still win.
    • Expose getOidcProvider() / getAwsOidcProvider() so startup.js awaits .initialize() before serving traffic.
    • OIDC-aware isEnabled(), getAuthHeaders() (****** from the cached AAD token), getValidationProbe() / getModelsFetchConfig() (skipped in OIDC mode — tokens aren't synchronously available at construct time), and getUnconfigured{Response,HealthResponse} (OIDC-specific 503 message).
    • The /models GitHub-OAuth special case and BYOK extra-header/body-field gating on the static API key are preserved unchanged.
  • containers/api-proxy/server.auth.test.js — 7 new tests covering: provider exposure, ****** injection when ready, empty headers before readiness, isEnabled lifecycle, OIDC-specific 503 body, default (no-OIDC) behavior, and static-key precedence over OIDC.

  • .github/workflows/smoke-copilot-byok-aoai-entra.{md,lock.yml} — allow login.microsoftonline.com in the smoke workflow's network.allowed list. The api-proxy sidecar and agent share an egress allowlist via Squid, so the Entra token endpoint must be reachable for the GitHub OIDC → Azure AD exchange to succeed.

  • src/constants/placeholders.test.ts — point the assertion at copilot-byok.js (where COPILOT_PLACEHOLDER_TOKEN now lives after main's refactor) and parse the 'ghu_' + 'a'.repeat(36) expression form.

Out of scope

  • Anthropic OIDC routing through the Copilot adapter (separate provider; only Azure/AWS/GCP are wired here, matching the openai adapter).

@zarenner
Copy link
Copy Markdown
Collaborator

zarenner commented Jun 5, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 96.51% 96.55% 📈 +0.04%
Statements 96.42% 96.46% 📈 +0.04%
Functions 98.72% 98.72% ➡️ +0.00%
Branches 90.69% 90.73% 📈 +0.04%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/config-writer.ts 89.3% → 90.9% (+1.65%) 89.3% → 90.9% (+1.65%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 5, 2026

@copilot suggest title to fix https://github.com/github/gh-aw-firewall/actions/runs/27034176751/job/79793952153

Suggested title:

ci: add Entra-auth variant of AOAI BYOK Copilot smoke workflow

The pr-title check failed because the title is missing a conventional-commit prefix. ci: matches the allowed types and fits since this PR adds a smoke workflow under .github/workflows/. feat: or test: would also satisfy the check if you'd prefer those.

Copilot AI requested a review from zarenner June 5, 2026 18:59
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@zarenner
Copy link
Copy Markdown
Collaborator

zarenner commented Jun 5, 2026

@copilot resolve the merge conflicts in this pull request

…-byok-aoai-entra

# Conflicts:
#	src/constants/placeholders.test.ts
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 5, 2026

@copilot resolve the merge conflicts in this pull request

Merged main and resolved the conflict in src/constants/placeholders.test.ts (took main's wording + Number(...) form; behavior unchanged). All 915 api-proxy tests and the placeholders unit test pass. See 629444c.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Claude Engine Smoke Test

Result: PASS

💥 [THE END] — Illustrated by Smoke Claude

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

🔬 Smoke Test Results

Test Status
GitHub MCP connectivity
GitHub.com HTTP (200)
File write/read

PR: fix(api-proxy): add Azure/AWS/GCP OIDC support to Copilot adapter
Author: @Copilot | Assignees: @zarenner, @Copilot

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Smoke test results:

  • fix(test): update placeholder test to find token in copilot-byok.js
  • [awf] Close ARC/DinD zero-config gaps for chroot identity, DinD staging, and MCP Docker host propagation
  • GitHub MCP Testing: ✅
  • Safe Inputs GH CLI Testing: ✅
  • Playwright Testing: ✅
  • File Writing Testing: ✅
  • Discussion Interaction Testing: ✅
  • Build AWF: ✅
  • Overall: PASS

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "registry.npmjs.org"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Chroot Smoke Test Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3 ❌ NO
Node.js v24.16.0 v22.22.3 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: ❌ FAILED — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

🔑 Copilot BYOK (Direct) Smoke Test — PASS

Running in direct BYOK mode (COPILOT_PROVIDER_API_KEY) via api-proxy → api.githubcopilot.com

  • ✅ GitHub MCP · ✅ GitHub.com (HTTP 200) · ✅ File write/read · ✅ BYOK inference (agent sees only dummy placeholder credential)

Last 2 merged PRs:

cc author @Copilot · assignees @zarenner, @Copilot

🔑 BYOK report filed by Smoke Copilot BYOK

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color 1/1 passed ✅ PASS
Go env 1/1 passed ✅ PASS
Go uuid 1/1 passed ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx All passed ✅ PASS
Node.js execa All passed ✅ PASS
Node.js p-limit All passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — ✅ PASS

Generated by Build Test Suite for issue #4407 · sonnet46 3.9M ·

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Smoke Test Results

Check Result
Redis PING ❌ timeout (no response)
PostgreSQL pg_isready no response
PostgreSQL SELECT 1 ❌ connection failed

Overall: FAILhost.docker.internal is unreachable from this runner environment. Service containers are not accessible.

🔌 Service connectivity validated by Smoke Services

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Smoke Test: API Proxy OpenTelemetry Tracing

Scenario Result Notes
S1: Module Loading otel.js loads; exports startRequestSpan, setTokenAttributes, endSpan, endSpanError, shutdown, isEnabled + test helpers
S2: Test Suite 35/35 tests passed, 0 failed (otel.test.js, 617 lines)
S3: Env Var Forwarding api-proxy-service-config.ts forwards OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, GITHUB_AW_OTEL_TRACE_ID, GITHUB_AW_OTEL_PARENT_SPAN_ID, OTEL_SERVICE_NAME
S4: Token Tracker Integration onUsage callback exists in token-tracker-http.js (line 268); onSpanEnd hook also present (lines 190/247/310)
S5: OTEL Diagnostics Graceful degradation confirmed — falls back to local NDJSON (/var/log/api-proxy/otel.jsonl) when OTEL_EXPORTER_OTLP_ENDPOINT is unset; no network export attempted

All scenarios pass. OTEL tracing integration is complete and working.

📡 OTel tracing validated by Smoke OTel Tracing

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Smoke Test Results

  • GitHub MCP: ✅
  • GitHub.com Connectivity: ✅ (200)
  • File Write/Read Test: ✅ (content confirmed)
  • BYOK Inference Test: ✅

Running in direct BYOK mode (AWF_AUTH_TYPE=github-oidc + AWF_AUTH_AZURE_* + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw) authenticated via Microsoft Entra

Overall Status: PASS

cc: @Copilot @zarenner

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • api.openai.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.openai.com"

See Network Configuration for more information.

🪪 BYOK (AOAI Entra) report filed by Smoke Copilot BYOK AOAI (Entra)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Smoke Test Results (Direct BYOK AOAI api-key)

  • fix(api-proxy): add Azure/AWS/GCP OIDC support to Copilot adapter
    1. MCP pull requests: ✅ (fetched 2 merged PRs)
    1. github.com HTTP response: ✅ (200)
    1. file write/read test: ✅ (file exists)
    1. direct BYOK inference test: ✅

Running in direct BYOK mode (COPILOT_PROVIDER_API_KEY + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw)
Overall: PASS

Thanks @Copilot and @zarenner for review.

🔑 BYOK (AOAI api-key) report filed by Smoke Copilot BYOK AOAI (api-key)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Gemini Smoke Test started.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • localhost

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "localhost"

See Network Configuration for more information.

💎 Faceted by Smoke Gemini

@zarenner zarenner marked this pull request as ready for review June 5, 2026 21:27
Copilot AI review requested due to automatic review settings June 5, 2026 21:27
@zarenner zarenner merged commit c3cf52e into main Jun 5, 2026
77 checks passed
@zarenner zarenner deleted the copilot/smoke-copilot-byok-aoai-entra branch June 5, 2026 21:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the api-proxy sidecar’s Copilot provider adapter (port 10002) to support GitHub Actions OIDC-based auth (Azure/AWS/GCP) for direct-BYOK scenarios (notably Azure OpenAI via Entra), and adds a dedicated smoke workflow to validate the end-to-end OIDC→Entra token exchange path.

Changes:

  • Add OIDC-aware auth handling to the Copilot adapter, including Azure/GCP Bearer token injection and AWS credential-provider plumbing.
  • Add Copilot-adapter Azure OIDC unit tests covering provider exposure, header injection, enablement gating, and OIDC-specific 503 messaging.
  • Add a new smoke workflow (and lock file) and allow login.microsoftonline.com egress for Entra token exchange.
Show a summary per file
File Description
containers/api-proxy/providers/copilot.js Adds OIDC provider construction (Azure/AWS/GCP), readiness-based enablement, and OIDC-specific responses/validation behavior.
containers/api-proxy/server.auth.test.js Adds unit tests validating Azure OIDC behavior for the Copilot adapter.
.github/workflows/smoke-copilot-byok-aoai-entra.md Introduces a new smoke workflow for Copilot CLI direct BYOK to Azure OpenAI via Entra (GitHub OIDC).
.github/workflows/smoke-copilot-byok-aoai-entra.lock.yml Generated lockfile for the new smoke workflow, including allowed domain updates.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 4

Comment on lines +117 to +121
// authToken is consumed by the existing validation/models-fetch/auth-header paths.
// For OIDC mode the token isn't available synchronously at construction time, so
// we surface a non-empty marker here to keep alwaysBind/isEnabled probes happy and
// resolve the real token lazily inside getAuthHeaders.
const authToken = staticAuthToken;
Comment on lines +87 to +89
# strict-mode compilation. AWF still forwards these values exclusively to the
# api-proxy sidecar (see src/services/api-proxy-service-config.ts); they are
# never written into the agent container's env.
Comment on lines +70 to +74
if (authProvider === 'aws') {
const roleArn = env.AWF_AUTH_AWS_ROLE_ARN;
const region = env.AWF_AUTH_AWS_REGION;
if (roleArn && region) {
const { AwsOidcTokenProvider } = require('../aws-oidc-token-provider');
Comment on lines +84 to +88
} else if (authProvider === 'gcp') {
const workloadIdentityProvider = env.AWF_AUTH_GCP_WORKLOAD_IDENTITY_PROVIDER;
if (workloadIdentityProvider) {
const { GcpOidcTokenProvider } = require('../gcp-oidc-token-provider');
oidcProvider = new GcpOidcTokenProvider({
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants