Stop persisting DeepSeek secrets into bucket config
Browse files- app/config.py +70 -11
- start_hf.py +15 -44
app/config.py
CHANGED
|
@@ -5,29 +5,88 @@ import os
|
|
| 5 |
logger = logging.getLogger(__name__)
|
| 6 |
|
| 7 |
CONFIG_PATH = os.getenv("CONFIG_PATH", "config.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
|
| 10 |
def load_config():
|
| 11 |
"""从 config.json 加载配置,出错则返回空 dict"""
|
| 12 |
try:
|
| 13 |
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
|
| 14 |
-
return json.load(f)
|
| 15 |
except Exception as e:
|
| 16 |
logger.warning(f"[load_config] 无法读取配置文件: {e}")
|
| 17 |
-
return {}
|
| 18 |
|
| 19 |
|
| 20 |
def save_config(cfg):
|
| 21 |
-
"""将配置写回 config.json
|
| 22 |
try:
|
| 23 |
-
|
| 24 |
-
def clean(obj):
|
| 25 |
-
if isinstance(obj, dict):
|
| 26 |
-
return {k: clean(v) for k, v in obj.items() if not k.startswith("_")}
|
| 27 |
-
elif isinstance(obj, list):
|
| 28 |
-
return [clean(item) for item in obj]
|
| 29 |
-
return obj
|
| 30 |
-
cfg_clean = clean(cfg)
|
| 31 |
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
|
| 32 |
json.dump(cfg_clean, f, ensure_ascii=False, indent=2)
|
| 33 |
except Exception as e:
|
|
|
|
| 5 |
logger = logging.getLogger(__name__)
|
| 6 |
|
| 7 |
CONFIG_PATH = os.getenv("CONFIG_PATH", "config.json")
|
| 8 |
+
SENSITIVE_ACCOUNT_FIELDS = {"password", "token", "hif_dliq", "hif_leim"}
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def _account_from_env() -> dict:
|
| 12 |
+
account = os.getenv("DEEPSEEK_ACCOUNT", "").strip()
|
| 13 |
+
password = os.getenv("DEEPSEEK_PASSWORD", "").strip()
|
| 14 |
+
if not account or not password:
|
| 15 |
+
return {}
|
| 16 |
+
env_account = {"password": password, "token": ""}
|
| 17 |
+
if "@" in account:
|
| 18 |
+
env_account["email"] = account
|
| 19 |
+
else:
|
| 20 |
+
env_account["mobile"] = account
|
| 21 |
+
return env_account
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def _merge_env_secrets(config: dict) -> dict:
|
| 25 |
+
merged = dict(config) if isinstance(config, dict) else {}
|
| 26 |
+
|
| 27 |
+
api_key = os.getenv("DEEPSEEK_API_KEY", "").strip()
|
| 28 |
+
if api_key:
|
| 29 |
+
merged["keys"] = [api_key]
|
| 30 |
+
|
| 31 |
+
env_account = _account_from_env()
|
| 32 |
+
if env_account:
|
| 33 |
+
accounts = merged.get("accounts")
|
| 34 |
+
if not isinstance(accounts, list):
|
| 35 |
+
accounts = []
|
| 36 |
+
desired_identity = env_account.get("email") or env_account.get("mobile")
|
| 37 |
+
identity_key = "email" if "email" in env_account else "mobile"
|
| 38 |
+
replaced = False
|
| 39 |
+
merged_accounts = []
|
| 40 |
+
for account in accounts:
|
| 41 |
+
if not isinstance(account, dict):
|
| 42 |
+
continue
|
| 43 |
+
current_identity = account.get("email") or account.get("mobile")
|
| 44 |
+
if current_identity == desired_identity:
|
| 45 |
+
updated = dict(account)
|
| 46 |
+
updated[identity_key] = desired_identity
|
| 47 |
+
updated["password"] = env_account["password"]
|
| 48 |
+
merged_accounts.append(updated)
|
| 49 |
+
replaced = True
|
| 50 |
+
else:
|
| 51 |
+
merged_accounts.append(account)
|
| 52 |
+
if not replaced:
|
| 53 |
+
merged_accounts.append(env_account)
|
| 54 |
+
merged["accounts"] = merged_accounts
|
| 55 |
+
|
| 56 |
+
return merged
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def _sanitize_for_persistence(obj):
|
| 60 |
+
if isinstance(obj, dict):
|
| 61 |
+
sanitized = {}
|
| 62 |
+
for key, value in obj.items():
|
| 63 |
+
if key.startswith("_"):
|
| 64 |
+
continue
|
| 65 |
+
if key == "keys":
|
| 66 |
+
continue
|
| 67 |
+
if key in SENSITIVE_ACCOUNT_FIELDS:
|
| 68 |
+
continue
|
| 69 |
+
sanitized[key] = _sanitize_for_persistence(value)
|
| 70 |
+
return sanitized
|
| 71 |
+
if isinstance(obj, list):
|
| 72 |
+
return [_sanitize_for_persistence(item) for item in obj]
|
| 73 |
+
return obj
|
| 74 |
|
| 75 |
|
| 76 |
def load_config():
|
| 77 |
"""从 config.json 加载配置,出错则返回空 dict"""
|
| 78 |
try:
|
| 79 |
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
|
| 80 |
+
return _merge_env_secrets(json.load(f))
|
| 81 |
except Exception as e:
|
| 82 |
logger.warning(f"[load_config] 无法读取配置文件: {e}")
|
| 83 |
+
return _merge_env_secrets({})
|
| 84 |
|
| 85 |
|
| 86 |
def save_config(cfg):
|
| 87 |
+
"""将配置写回 config.json,但不持久化密钥、密码或会话令牌。"""
|
| 88 |
try:
|
| 89 |
+
cfg_clean = _sanitize_for_persistence(cfg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
|
| 91 |
json.dump(cfg_clean, f, ensure_ascii=False, indent=2)
|
| 92 |
except Exception as e:
|
start_hf.py
CHANGED
|
@@ -5,40 +5,22 @@ import sys
|
|
| 5 |
from pathlib import Path
|
| 6 |
|
| 7 |
|
| 8 |
-
|
| 9 |
-
account = os.getenv("DEEPSEEK_ACCOUNT", "").strip()
|
| 10 |
-
password = os.getenv("DEEPSEEK_PASSWORD", "").strip()
|
| 11 |
-
if not account or not password:
|
| 12 |
-
return {}
|
| 13 |
-
account_config = {"password": password, "token": ""}
|
| 14 |
-
if "@" in account:
|
| 15 |
-
account_config["email"] = account
|
| 16 |
-
else:
|
| 17 |
-
account_config["mobile"] = account
|
| 18 |
-
return account_config
|
| 19 |
|
| 20 |
|
| 21 |
-
def
|
| 22 |
-
if
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
updated.setdefault("token", "")
|
| 35 |
-
merged.append(updated)
|
| 36 |
-
replaced = True
|
| 37 |
-
else:
|
| 38 |
-
merged.append(account)
|
| 39 |
-
if not replaced:
|
| 40 |
-
merged.append(desired_account)
|
| 41 |
-
return merged
|
| 42 |
|
| 43 |
|
| 44 |
def prepare_runtime_files() -> None:
|
|
@@ -57,19 +39,8 @@ def prepare_runtime_files() -> None:
|
|
| 57 |
except Exception:
|
| 58 |
config = {}
|
| 59 |
|
| 60 |
-
api_key = os.getenv("DEEPSEEK_API_KEY", "").strip()
|
| 61 |
-
if api_key:
|
| 62 |
-
config["keys"] = [api_key]
|
| 63 |
-
else:
|
| 64 |
-
config.setdefault("keys", [])
|
| 65 |
-
|
| 66 |
-
existing_accounts = config.get("accounts")
|
| 67 |
-
if not isinstance(existing_accounts, list):
|
| 68 |
-
existing_accounts = []
|
| 69 |
-
config["accounts"] = _merge_account(existing_accounts, _account_from_env())
|
| 70 |
-
|
| 71 |
config_path.write_text(
|
| 72 |
-
json.dumps(config, ensure_ascii=False, indent=2),
|
| 73 |
encoding="utf-8",
|
| 74 |
)
|
| 75 |
db_path.touch(exist_ok=True)
|
|
|
|
| 5 |
from pathlib import Path
|
| 6 |
|
| 7 |
|
| 8 |
+
SENSITIVE_FIELDS = {"keys", "password", "token", "hif_dliq", "hif_leim"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
|
| 11 |
+
def _sanitize_for_persistence(obj):
|
| 12 |
+
if isinstance(obj, dict):
|
| 13 |
+
sanitized = {}
|
| 14 |
+
for key, value in obj.items():
|
| 15 |
+
if key.startswith("_"):
|
| 16 |
+
continue
|
| 17 |
+
if key in SENSITIVE_FIELDS:
|
| 18 |
+
continue
|
| 19 |
+
sanitized[key] = _sanitize_for_persistence(value)
|
| 20 |
+
return sanitized
|
| 21 |
+
if isinstance(obj, list):
|
| 22 |
+
return [_sanitize_for_persistence(item) for item in obj]
|
| 23 |
+
return obj
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
|
| 26 |
def prepare_runtime_files() -> None:
|
|
|
|
| 39 |
except Exception:
|
| 40 |
config = {}
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
config_path.write_text(
|
| 43 |
+
json.dumps(_sanitize_for_persistence(config), ensure_ascii=False, indent=2),
|
| 44 |
encoding="utf-8",
|
| 45 |
)
|
| 46 |
db_path.touch(exist_ok=True)
|