fix(litellm): restrict UI login to database users

This commit is contained in:
Codex
2026-10-08 20:56:30 -07:00
parent aaff6db668
commit 9a4020b7ec
5 changed files with 13 additions and 5 deletions
-2
View File
@@ -3,8 +3,6 @@ LITELLM_PORT=4000
POSTGRES_PASSWORD=
LITELLM_MASTER_KEY=
LITELLM_SALT_KEY=
UI_USERNAME=admin
UI_PASSWORD=
ZENMUX_SUBSCRIPTION_API_KEY=
ZENMUX_PAYG_API_KEY=
OPENROUTER_API_KEY=
+8 -1
View File
@@ -61,7 +61,14 @@ Google AI Studio 预留独立 key 与模型表;取得有效 key 后查询目
真实 `.env` 权限 `0600`,不提交 Git;模板见 `.env.example`。
ZenMux subscription/PAYG 的 key 需要明确确认用途,不能按外观推断。
数据库密码使用无特殊 URL 字符的随机值,避免 `DATABASE_URL` 编码问题。
`LITELLM_MASTER_KEY` 以 `sk-` 开头,salt 与 UI 密码独立随机生成。
`LITELLM_MASTER_KEY` 以 `sk-` 开头,salt 独立随机生成。
UI 使用数据库管理员 `kai@litellm.local`(只是登录标识,不发送邮件),
设置 `disable_env_credential_login: true`,禁用 UI_PASSWORD 以及 master key 的网页登录。
临时密码保存在 .145 的 `.secrets/tools-litellm-ui-login.env`(0600);
首次登录必须修改,修改后该文件的临时密码不再有效。数据库保存密码哈希。
master key 仍能管理 API,用于恢复权限,不再充当网页登录密码。
不能直接用这份配置初始化空库后期待默认 admin 登录:必须预先通过
`/user/new` 建立管理员,再 `/user/update` 设置临时密码,随后启用限制。
日常客户端应使用管理界面创建的应用专属 virtual key,不共享 master key。
不要开启输出请求全文的 debug 日志。
-2
View File
@@ -34,8 +34,6 @@ services:
DATABASE_URL: postgresql://litellm:${POSTGRES_PASSWORD:?required}@postgres:5432/litellm
LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY:?required}
LITELLM_SALT_KEY: ${LITELLM_SALT_KEY:?required}
UI_USERNAME: ${UI_USERNAME:-admin}
UI_PASSWORD: ${UI_PASSWORD:?required}
ZENMUX_SUBSCRIPTION_API_KEY: ${ZENMUX_SUBSCRIPTION_API_KEY:-}
ZENMUX_PAYG_API_KEY: ${ZENMUX_PAYG_API_KEY:-}
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
@@ -39,6 +39,7 @@ def build_config(catalog, env, exists):
'master_key': 'os.environ/LITELLM_MASTER_KEY',
'database_url': 'os.environ/DATABASE_URL',
'store_model_in_db': False,
'disable_env_credential_login': True,
},
'litellm_settings': {'drop_params': False, 'set_verbose': False},
# No cross-provider or subscription-to-PAYG fallback without an explicit decision.
+4
View File
@@ -14,6 +14,10 @@ class ConfigTests(unittest.TestCase):
def test_missing_credentials_exclude_routes(self):
self.assertEqual(build_config(self.catalog, {}, lambda _: False)['model_list'], [])
def test_env_ui_login_disabled(self):
settings = build_config(self.catalog, {}, lambda _: False)['general_settings']
self.assertTrue(settings['disable_env_credential_login'])
def test_subscription_preserves_vendor_prefix(self):
routes = build_config(self.catalog, {'ZENMUX_SUBSCRIPTION_API_KEY': 'secret'}, lambda _: False)['model_list']
self.assertEqual(routes[0]['litellm_params']['model'], 'anthropic/anthropic/claude-sonnet-5.5')