Skip to content

feat: add API key authentication to REST API (#507)#508

Merged
cjimti merged 2 commits into
masterfrom
feat/api-key-auth
May 29, 2026
Merged

feat: add API key authentication to REST API (#507)#508
cjimti merged 2 commits into
masterfrom
feat/api-key-auth

Conversation

@cjimti
Copy link
Copy Markdown
Member

@cjimti cjimti commented May 28, 2026

Summary

Adds Bearer-token authentication to the kubefwd REST API. Previously the API (pkg/fwdapi) served every endpoint — including Kubernetes context enumeration, pod log reads, and port-forward creation — with no authentication. Since kubefwd runs as root via sudo -E, any local process could drive it against the victim's kubeconfig.

This PR closes #507 and addresses the concern raised in advisory GHSA-vwjh-p4vp-9rp2.

How it works

  • On startup, the API key is resolved from the KUBEFWD_API_KEY environment variable. If unset, a random 32-character hex key is generated.
  • The key is needed for all endpoints except /api/health (kept open for liveness probes).
  • Requests authenticate via the Authorization: Bearer <key> header. Missing or invalid keys get 401 Unauthorized.
  • Only the last 4 characters of the key are printed to the console on startup (never the full secret).
  • Token comparison uses crypto/subtle.ConstantTimeCompare to avoid timing side channels.

Deterministic keys for automation

Setting KUBEFWD_API_KEY lets automation/CI use a fixed, known key instead of scraping a generated one from logs:

export KUBEFWD_API_KEY=my-known-key
sudo -E kubefwd --api

MCP bridge

The kubefwd mcp HTTP client now reads KUBEFWD_API_KEY automatically and sends the Bearer header on every request. A new --api-key flag overrides the env var:

kubefwd mcp --api-key my-known-key

Changes

File Change
pkg/fwdapi/middleware/middleware.go New APIKeyAuth middleware (constant-time compare, 401 on failure)
pkg/fwdapi/server.go /api/health stays public; all other routes go through auth
pkg/fwdapi/manager.go resolveAPIKey() (env or random), APIKey() accessor, masked startup log
pkg/fwdmcp/httpclient.go HTTPClient carries an API key; all verbs send the Bearer header
cmd/kubefwd/mcp/mcp.go --api-key flag (overrides KUBEFWD_API_KEY)

Test plan

  • make verify passes (lint, race tests, build, SHA-pin validation)
  • Unit tests for APIKeyAuth: valid key, no header, wrong key, missing Bearer prefix, empty bearer
  • Unit tests for resolveAPIKey: from env var, generated, length/uniqueness
  • middleware package retains 100% coverage
  • Manual: sudo -E kubefwd --api, confirm 401 without key and 200 with key
  • Manual: kubefwd mcp against an authenticated API

Notes / follow-ups

  • The OpenAPI spec (/docs) still describes the API as unauthenticated; updating it can follow in a separate docs pass.
  • When a key is auto-generated (no env var), the MCP bridge has no way to discover it since /api/health is unauthenticated — it will connect but tool calls 401. Recommend setting KUBEFWD_API_KEY when using the MCP bridge. A fail-fast probe is a possible follow-up.

Require Bearer token auth on all API endpoints except /api/health.
On startup the key is read from KUBEFWD_API_KEY env var; if unset a
random 32-char hex key is generated and the last 4 chars are printed
to the console.

Token comparison uses crypto/subtle.ConstantTimeCompare to prevent
timing side-channel attacks.

MCP HTTP client and `kubefwd mcp --api-key` flag updated to propagate
the key automatically.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

❌ Patch coverage is 72.85714% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.07%. Comparing base (26fb9a4) to head (281a502).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
pkg/fwdmcp/httpclient.go 52.00% 7 Missing and 5 partials ⚠️
pkg/fwdapi/manager.go 66.66% 2 Missing and 2 partials ⚠️
cmd/kubefwd/mcp/mcp.go 25.00% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #508      +/-   ##
==========================================
- Coverage   81.14%   81.07%   -0.07%     
==========================================
  Files          71       71              
  Lines       12779    12843      +64     
==========================================
+ Hits        10370    10413      +43     
- Misses       2005     2018      +13     
- Partials      404      412       +8     
Files with missing lines Coverage Δ
pkg/fwdapi/middleware/middleware.go 100.00% <100.00%> (ø)
pkg/fwdapi/server.go 96.38% <100.00%> (+0.08%) ⬆️
cmd/kubefwd/mcp/mcp.go 17.46% <25.00%> (+0.51%) ⬆️
pkg/fwdapi/manager.go 62.11% <66.66%> (+0.25%) ⬆️
pkg/fwdmcp/httpclient.go 74.24% <52.00%> (-0.79%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread pkg/fwdapi/manager.go Fixed
The last-4-chars log was flagged by CodeQL go/clear-text-logging yet was
useless for authenticating. Print the full key instead so users can copy
it into API/MCP clients (localhost-only dev tool, same security context
as the launching user), and annotate the line with an lgtm suppression
plus justification.
Comment thread pkg/fwdapi/manager.go Dismissed
@cjimti cjimti merged commit db01139 into master May 29, 2026
11 checks passed
@cjimti cjimti deleted the feat/api-key-auth branch May 29, 2026 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add API key authentication to REST API

2 participants