fix(opax-mcp): legg til identity token auth i _opax_get/_opax_post mot opax.vauco.no

This commit is contained in:
chrischristiansen-glitch 2026-06-17 18:39:12 +02:00
parent 9627da37ae
commit 0ab044417e

View File

@ -5,6 +5,8 @@ Auth: Cloud Run IAM (Authorization header) + X-MCP-Secret header for tool-level
import os import os
import httpx import httpx
import base64 import base64
import google.auth
import google.auth.transport.requests
from fastapi import FastAPI, HTTPException, Header from fastapi import FastAPI, HTTPException, Header
from pydantic import BaseModel from pydantic import BaseModel
from typing import Optional, Any from typing import Optional, Any
@ -27,6 +29,30 @@ def _auth_check(x_mcp_secret: Optional[str]):
raise HTTPException(status_code=401, detail="Unauthorized") raise HTTPException(status_code=401, detail="Unauthorized")
def _opax_identity_token() -> str:
"""Hent identity token for opax.vauco.no (Cloud Run IAP/IAM)."""
metadata_url = (
"http://metadata.google.internal/computeMetadata/v1/instance"
f"/service-accounts/default/identity?audience={OPAX_BASE_URL}&format=full"
)
try:
resp = httpx.get(metadata_url, headers={"Metadata-Flavor": "Google"}, timeout=5)
if resp.status_code == 200 and resp.text.strip():
return resp.text.strip()
except Exception:
pass
credentials, _ = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
return credentials.token
def _opax_headers() -> dict:
return {
"Authorization": f"Bearer {_opax_identity_token()}",
"Content-Type": "application/json",
}
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Health # Health
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -70,14 +96,14 @@ async def list_tools(x_mcp_secret: Optional[str] = Header(default=None)):
async def _opax_get(path: str) -> Any: async def _opax_get(path: str) -> Any:
async with httpx.AsyncClient(timeout=30) as client: async with httpx.AsyncClient(timeout=30) as client:
r = await client.get(f"{OPAX_BASE_URL}{path}") r = await client.get(f"{OPAX_BASE_URL}{path}", headers=_opax_headers())
r.raise_for_status() r.raise_for_status()
return r.json() return r.json()
async def _opax_post(path: str, body: dict) -> Any: async def _opax_post(path: str, body: dict) -> Any:
async with httpx.AsyncClient(timeout=30) as client: async with httpx.AsyncClient(timeout=30) as client:
r = await client.post(f"{OPAX_BASE_URL}{path}", json=body) r = await client.post(f"{OPAX_BASE_URL}{path}", json=body, headers=_opax_headers())
r.raise_for_status() r.raise_for_status()
return r.json() return r.json()