Skip to content

Commit bb0af5d

Browse files
author
Anuj Shrivastava
committed
fix: remove auth bypass - server locked until API key generated
- Remove first-run open-access bypass in APIKeyMiddleware - No API keys = HTTP 503 with hint to generate via /admin/keys - Add Dockerfile for multi-arch container build - Add requirements.txt and run.py - Add GitHub Actions workflow for linux/amd64 + linux/arm64 build+push
1 parent 1e8d93d commit bb0af5d

5 files changed

Lines changed: 118 additions & 5 deletions

File tree

.github/workflows/build-push.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Build & Push Multi-Arch Container
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
workflow_dispatch:
7+
8+
jobs:
9+
build-push:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
packages: write
14+
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Set up QEMU (for cross-arch builds)
20+
uses: docker/setup-qemu-action@v3
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
25+
- name: Login to GHCR
26+
uses: docker/login-action@v3
27+
with:
28+
registry: ghcr.io
29+
username: ${{ github.actor }}
30+
password: ${{ secrets.GITHUB_TOKEN }}
31+
32+
- name: Build and push
33+
uses: docker/build-push-action@v5
34+
with:
35+
context: .
36+
platforms: linux/amd64,linux/arm64
37+
push: true
38+
tags: ghcr.io/ibm/verify-mcp-server:latest
39+
cache-from: type=gha
40+
cache-to: type=gha,mode=max

Dockerfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM python:3.12-slim
2+
3+
WORKDIR /app
4+
5+
# Install dependencies
6+
COPY requirements.txt .
7+
RUN pip install --no-cache-dir -r requirements.txt
8+
9+
# Copy source
10+
COPY src/ ./src/
11+
COPY run.py .
12+
13+
# Data volume for keystore persistence
14+
VOLUME ["/data"]
15+
16+
ENV MCP_TRANSPORT=sse
17+
ENV MCP_PORT=8004
18+
ENV KEYSTORE_PATH=/data/keys.json
19+
20+
EXPOSE 8004
21+
22+
CMD ["python", "-m", "src"]

requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mcp[cli]>=1.0.0
2+
httpx>=0.25.0
3+
uvicorn>=0.30.0
4+
starlette>=0.38.0
5+
python-dotenv>=1.0.0

run.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""WXO STDIO entry point for Verify MCP Server."""
2+
import os
3+
4+
# Force STDIO transport
5+
os.environ["MCP_TRANSPORT"] = "stdio"
6+
7+
# Map WXO connection env vars to the bare names expected by config.py
8+
# WXO injects: WXO_CONNECTION_<app_id>_<field> = value
9+
# Our code reads: <field>
10+
_APP_ID = "verify_creds"
11+
_ENV_KEYS = [
12+
"VERIFY_TENANT",
13+
"API_CLIENT_ID",
14+
"API_CLIENT_SECRET",
15+
"OIDC_CLIENT_ID",
16+
"OIDC_CLIENT_SECRET",
17+
"VERIFY_SSL",
18+
]
19+
for key in _ENV_KEYS:
20+
wxo_key = f"WXO_CONNECTION_{_APP_ID}_{key}"
21+
val = os.environ.get(wxo_key)
22+
if val and not os.environ.get(key):
23+
os.environ[key] = val
24+
25+
from src.server import main
26+
27+
if __name__ == "__main__":
28+
main()

src/server.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,26 @@ async def dispatch(self, request: Request, call_next):
7474
# Everything else requires a valid API key
7575
ks = _get_key_store()
7676

77-
# If no keys have been generated yet, allow open access
78-
# (first-run experience — admin should generate a key immediately)
77+
# If no keys have been generated yet, block ALL requests.
78+
# The admin MUST generate at least one key before the server
79+
# will accept connections. Use:
80+
# docker exec <container> curl -s -X POST \
81+
# http://localhost:8004/admin/keys \
82+
# -H 'Content-Type: application/json' \
83+
# -d '{"user":"admin"}'
7984
if not ks.has_any_keys():
80-
return await call_next(request)
85+
return JSONResponse(
86+
{
87+
"error": "Server is locked — no API keys have been configured.",
88+
"hint": (
89+
"Generate a key: docker exec <container> curl -s -X POST "
90+
"http://localhost:8004/admin/keys "
91+
"-H 'Content-Type: application/json' "
92+
"-d '{\"user\":\"admin\"}'"
93+
),
94+
},
95+
status_code=503,
96+
)
8197

8298
auth_header = request.headers.get("Authorization", "")
8399
if not auth_header:
@@ -251,8 +267,10 @@ def main() -> None:
251267
logger.info("API key authentication ENABLED (%d key(s) loaded)", len(ks.list_keys()))
252268
else:
253269
logger.warning(
254-
"No API keys configured — SSE endpoint is OPEN. "
255-
"Generate a key: curl -X POST http://localhost:%d/admin/keys -H 'Content-Type: application/json' -d '{\"user\":\"admin@ibm.com\"}'",
270+
"LOCKED — No API keys configured. ALL requests will be rejected with HTTP 503 "
271+
"until you generate a key: "
272+
"docker exec <container> curl -s -X POST http://localhost:%d/admin/keys "
273+
"-H 'Content-Type: application/json' -d '{\"user\":\"admin\"}'",
256274
SSE_PORT,
257275
)
258276

0 commit comments

Comments
 (0)