Skip to content

Commit 037b250

Browse files
OhYeeclaude
andcommitted
refactor(credential): STS 刷新中间件默认启用,去掉 FC 环境特殊判断
之前默认仅在 FC 环境(FC_REGION 存在)才启用。按需求改为**默认启用**,不再 特殊判断 FC 环境;仅在环境变量 AGENTRUN_STS_REFRESH_ENABLED 设为假值 (0/false/no/off)或构造参数 enabled=False 时关闭。中间件在 x-fc-* 头不齐全 时本就透传、无副作用,故默认开是安全的。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: OhYee <oyohyee@oyohyee.com>
1 parent e0e460b commit 037b250

3 files changed

Lines changed: 55 additions & 27 deletions

File tree

agentrun/server/server.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,10 @@ def __init__(
124124
"""
125125
self.app = FastAPI(title="AgentRun Server")
126126

127-
# 注入 STS 刷新中间件:从每次请求的 FC 头解析最新 STS 临时凭证,写入
127+
# 注入 STS 刷新中间件:从每次请求的 x-fc-* 头解析最新 STS 临时凭证,写入
128128
# 请求级 overlay,使本次请求内所有 Config/client 静默使用最新凭证。
129-
# 无条件启用:未携带相关头时(本地/非 FC)中间件不产生任何副作用。
129+
# 默认启用;未携带相关头时不产生任何副作用。如需关闭设环境变量
130+
# AGENTRUN_STS_REFRESH_ENABLED=false。
130131
self.app.add_middleware(StsRefreshMiddleware)
131132

132133
# 如果启用了 memory,包装 invoke_agent

agentrun/server/sts_middleware.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
头名可配置 / Configurable header names:
1515
构造参数 > 环境变量 > 默认值(``x-fc-*``)。头名大小写不敏感。
1616
17+
启用开关 / Enable switch:
18+
中间件**默认启用**。仅在特定情况下关闭:构造参数 ``enabled=False``,或
19+
环境变量 ``AGENTRUN_STS_REFRESH_ENABLED`` 设为假值(``0`` / ``false`` /
20+
``no`` / ``off``)。
21+
1722
信任边界 / Trust boundary:
18-
overlay 会覆盖运维方在环境变量里配置的凭证,因此只在**可信来源**提供
19-
``x-fc-*`` 头时才能启用。函数计算(FC)拥有该头命名空间并会剥离客户端伪造的
20-
同名头,故默认仅在检测到 FC 环境(``FC_REGION`` 存在)时生效;非 FC 环境
21-
(如裸 uvicorn / 自有网关)默认关闭,避免不可信客户端注入 ``x-fc-*`` 头冒用
22-
身份。可用构造参数 ``enabled`` 或环境变量 ``AGENTRUN_STS_REFRESH_ENABLED``
23-
显式开关(开启前请确保已有前置鉴权或网关剥离这些头)。
23+
overlay 仅在 ``x-fc-*`` 头**齐全**时注入(覆盖运维方 env 凭证),否则透传。
24+
函数计算(FC)拥有该头命名空间并会剥离客户端伪造的同名头,FC 内安全。
25+
**注意**:若部署在非 FC 环境(裸 uvicorn / 自有网关)且服务可被不可信客户端
26+
直达,攻击者可注入 ``x-fc-*`` 头冒用身份——此类场景请前置鉴权 / 由网关剥离
27+
这些头,或按上面的开关关闭本中间件。
2428
"""
2529

2630
from __future__ import annotations
@@ -37,12 +41,15 @@
3741

3842

3943
def _detect_enabled() -> bool:
40-
"""决定是否启用 overlay:显式环境变量优先,否则按是否在 FC 环境自动判断。"""
44+
"""是否启用 overlay:**默认启用**,仅环境变量显式设为假值时关闭。
45+
46+
``AGENTRUN_STS_REFRESH_ENABLED`` 未设置 -> 启用;设为
47+
``0`` / ``false`` / ``no`` / ``off`` -> 关闭;其余真值 -> 启用。
48+
"""
4149
flag = os.getenv("AGENTRUN_STS_REFRESH_ENABLED")
42-
if flag is not None:
43-
return flag.strip().lower() in ("1", "true", "yes", "on")
44-
# FC 环境下 FC_REGION 必然存在;非 FC 默认关闭以防 x-fc-* 头注入。
45-
return os.getenv("FC_REGION") is not None
50+
if flag is None:
51+
return True
52+
return flag.strip().lower() in ("1", "true", "yes", "on")
4653

4754

4855
class StsRefreshMiddleware(BaseHTTPMiddleware):
@@ -58,7 +65,8 @@ def __init__(
5865
security_token_header: Optional[str] = None,
5966
) -> None:
6067
super().__init__(app)
61-
# enabled=None 时自动探测(FC 环境或显式环境变量开关)。
68+
# enabled=None 时按环境变量决定(默认启用,
69+
# AGENTRUN_STS_REFRESH_ENABLED 设为假值时关闭)。
6270
self._enabled = _detect_enabled() if enabled is None else enabled
6371
# 头名解析(参数 > 环境变量 > 默认)交由 sts_from_headers 处理,这里只存原值。
6472
self._ak_header = access_key_id_header

tests/unittests/test_sts_refresh.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def _build_app():
173173
from agentrun.server.sts_middleware import StsRefreshMiddleware
174174

175175
app = FastAPI()
176-
# 测试环境无 FC_REGION,需显式启用(非 FC 默认关闭以防头注入)
176+
# 显式启用,避免受 dev 环境 AGENTRUN_STS_REFRESH_ENABLED 影响
177177
app.add_middleware(StsRefreshMiddleware, enabled=True)
178178

179179
@app.get("/async")
@@ -334,49 +334,68 @@ def test_middleware_partial_headers_ignored(monkeypatch):
334334
assert resp == {"ak": "ENV_AK", "sts": ""}
335335

336336

337-
def test_middleware_disabled_off_fc(monkeypatch):
338-
"""H2:非 FC(无 FC_REGION、未显式 enable)时不应应用 overlay。"""
337+
def test_middleware_enabled_by_default(monkeypatch):
338+
"""默认启用(不看 FC 环境,无需任何开关)。"""
339339
from fastapi import FastAPI
340340
from fastapi.testclient import TestClient
341341

342342
from agentrun.server.sts_middleware import StsRefreshMiddleware
343343

344344
monkeypatch.delenv("FC_REGION", raising=False)
345345
monkeypatch.delenv("AGENTRUN_STS_REFRESH_ENABLED", raising=False)
346+
347+
app = FastAPI()
348+
app.add_middleware(StsRefreshMiddleware) # enabled=None → 默认启用
349+
350+
@app.get("/x")
351+
async def _x():
352+
return {"ak": Config().get_access_key_id()}
353+
354+
client = TestClient(app)
355+
# 默认开:携带完整 x-fc-* 头即生效。
356+
assert client.get("/x", headers=_HEADERS).json() == {"ak": "H_AK"}
357+
358+
359+
def test_middleware_disabled_via_env(monkeypatch):
360+
"""仅在 AGENTRUN_STS_REFRESH_ENABLED 设为假值时关闭。"""
361+
from fastapi import FastAPI
362+
from fastapi.testclient import TestClient
363+
364+
from agentrun.server.sts_middleware import StsRefreshMiddleware
365+
366+
monkeypatch.setenv("AGENTRUN_STS_REFRESH_ENABLED", "false")
346367
monkeypatch.setenv("AGENTRUN_ACCESS_KEY_ID", "ENV_AK")
347368

348369
app = FastAPI()
349-
app.add_middleware(StsRefreshMiddleware) # enabled=None → auto-detect
370+
app.add_middleware(StsRefreshMiddleware) # enabled=None → 读环境变量 -> 关闭
350371

351372
@app.get("/x")
352373
async def _x():
353374
return {"ak": Config().get_access_key_id()}
354375

355376
client = TestClient(app)
356-
# 即便携带完整 x-fc-* 头,非 FC 环境也不应覆盖 env 凭证(防注入)。
357-
resp = client.get("/x", headers=_HEADERS).json()
358-
assert resp == {"ak": "ENV_AK"}
377+
# 已关闭:即便携带完整 x-fc-* 头也不覆盖 env 凭证。
378+
assert client.get("/x", headers=_HEADERS).json() == {"ak": "ENV_AK"}
359379

360380

361-
def test_middleware_enabled_on_fc(monkeypatch):
362-
"""H2:检测到 FC_REGION 时自动启用。"""
381+
def test_middleware_disabled_via_constructor(monkeypatch):
382+
"""构造参数 enabled=False 显式关闭。"""
363383
from fastapi import FastAPI
364384
from fastapi.testclient import TestClient
365385

366386
from agentrun.server.sts_middleware import StsRefreshMiddleware
367387

368-
monkeypatch.setenv("FC_REGION", "cn-hangzhou")
369-
monkeypatch.delenv("AGENTRUN_STS_REFRESH_ENABLED", raising=False)
388+
monkeypatch.setenv("AGENTRUN_ACCESS_KEY_ID", "ENV_AK")
370389

371390
app = FastAPI()
372-
app.add_middleware(StsRefreshMiddleware) # enabled=None → auto-detect FC
391+
app.add_middleware(StsRefreshMiddleware, enabled=False)
373392

374393
@app.get("/x")
375394
async def _x():
376395
return {"ak": Config().get_access_key_id()}
377396

378397
client = TestClient(app)
379-
assert client.get("/x", headers=_HEADERS).json() == {"ak": "H_AK"}
398+
assert client.get("/x", headers=_HEADERS).json() == {"ak": "ENV_AK"}
380399

381400

382401
def test_invoker_sync_path_sees_overlay():

0 commit comments

Comments
 (0)