From 6c3707e9877c8a6837e1a5a9b911d25fb8d852dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E6=B8=8A?= <101690169+666666g@users.noreply.github.com> Date: Sat, 4 Jul 2026 13:05:37 +0800 Subject: [PATCH] Refactor admin config to use centralized config package - Import and use internal/config.Load() in telesrv-admin instead of manual env parsing - Remove envOr() helper function (now consolidated in config package) - Add comprehensive .env.example documentation for Admin API/UI settings including: - TELESRV_ADMIN_API_TOKEN - TELESRV_ADMIN_UI_PASSWORD and TELESRV_ADMIN_UI_TOKEN - TELESRV_ADMIN_SESSION_KEY with security guidance - Optional address configuration parameters - Improve config validation error handling --- .env.example | 19 ++++++++++++++ cmd/telesrv-admin/main.go | 54 ++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/.env.example b/.env.example index dcd0d73c..f809baaa 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,25 @@ TELESRV_ADVERTISE_IP=127.0.0.1 TELESRV_DC=2 TELESRV_DEV_AUTH_CODE=12345 +# Admin API / Admin UI 配置 +# +# TELESRV_ADMIN_API_TOKEN 是主服务 (cmd/telesrv) 暴露 Admin REST API 的鉴权 token, +# 也是 Admin UI (cmd/telesrv-admin) 调用 Admin API 时使用的凭证。 +# 重要:主服务与 Admin UI 必须使用完全相同的 TELESRV_ADMIN_API_TOKEN,否则管理后台无法执行写操作。 +TELESRV_ADMIN_API_TOKEN=change-me-to-a-strong-random-token + +# TELESRV_ADMIN_UI_PASSWORD 是登录管理后台的密码; +# 也可改用 TELESRV_ADMIN_UI_TOKEN,二者至少填一个。 +TELESRV_ADMIN_UI_PASSWORD=abc123456 + +# TELESRV_ADMIN_SESSION_KEY 用于加密 Admin UI 的登录 session cookie。 +# 生产环境请使用至少 32 字节的强随机字符串,修改后会导致已登录会话失效。 +TELESRV_ADMIN_SESSION_KEY=change-me-to-a-strong-random-key-at-least-32-chars + +# 以下两项为可选,默认值通常无需修改: +# TELESRV_ADMIN_API_ADDR=127.0.0.1:2399 # 主服务 Admin API 监听地址 +# TELESRV_ADMIN_UI_ADDR=127.0.0.1:2400 # Admin UI 监听地址 + TELESRV_POSTGRES_DSN=postgres://telesrv:telesrv@127.0.0.1:5432/telesrv?sslmode=disable TELESRV_REDIS_ADDR=127.0.0.1:6399 TELESRV_REDIS_PASSWORD= diff --git a/cmd/telesrv-admin/main.go b/cmd/telesrv-admin/main.go index cae58e1e..c40ecf4d 100644 --- a/cmd/telesrv-admin/main.go +++ b/cmd/telesrv-admin/main.go @@ -15,6 +15,8 @@ import ( "time" "github.com/jackc/pgx/v5/pgxpool" + + "telesrv/internal/config" ) func main() { @@ -69,28 +71,39 @@ type uiConfig struct { SessionKey []byte } +// loadConfig 通过 internal/config.Load() 加载 .env 配置文件与环境变量, +// 并转换为 telesrv-admin 需要的 uiConfig。环境变量优先级高于 .env 文件。 func loadConfig() (uiConfig, error) { - cfg := uiConfig{ - Addr: envOr("TELESRV_ADMIN_UI_ADDR", "127.0.0.1:2400"), - PostgresDSN: envOr("TELESRV_POSTGRES_DSN", "postgres://telesrv:telesrv@127.0.0.1:5432/telesrv?sslmode=disable"), - AdminAPIURL: adminAPIURL(envOr("TELESRV_ADMIN_API_ADDR", "127.0.0.1:2399")), - AdminAPIToken: os.Getenv("TELESRV_ADMIN_API_TOKEN"), - Password: os.Getenv("TELESRV_ADMIN_UI_PASSWORD"), - Token: os.Getenv("TELESRV_ADMIN_UI_TOKEN"), + appCfg, err := config.Load() + if err != nil { + return uiConfig{}, fmt.Errorf("load config: %w", err) } - if cfg.Password == "" && cfg.Token == "" { - return cfg, fmt.Errorf("TELESRV_ADMIN_UI_PASSWORD or TELESRV_ADMIN_UI_TOKEN is required") + + adminAPIAddr := appCfg.AdminAPIAddr + if strings.TrimSpace(adminAPIAddr) == "" { + adminAPIAddr = "127.0.0.1:2399" } - if strings.TrimSpace(cfg.AdminAPIToken) == "" { - return cfg, fmt.Errorf("TELESRV_ADMIN_API_TOKEN is required for admin write actions") + + if appCfg.AdminUIPassword == "" && appCfg.AdminUIToken == "" { + return uiConfig{}, fmt.Errorf("TELESRV_ADMIN_UI_PASSWORD or TELESRV_ADMIN_UI_TOKEN is required") } - rawKey := os.Getenv("TELESRV_ADMIN_SESSION_KEY") - if rawKey == "" { - return cfg, fmt.Errorf("TELESRV_ADMIN_SESSION_KEY is required") + if strings.TrimSpace(appCfg.AdminAPIToken) == "" { + return uiConfig{}, fmt.Errorf("TELESRV_ADMIN_API_TOKEN is required for admin write actions") } - sum := sha256.Sum256([]byte(rawKey)) - cfg.SessionKey = sum[:] - return cfg, nil + if appCfg.AdminSessionKey == "" { + return uiConfig{}, fmt.Errorf("TELESRV_ADMIN_SESSION_KEY is required") + } + sum := sha256.Sum256([]byte(appCfg.AdminSessionKey)) + + return uiConfig{ + Addr: appCfg.AdminUIAddr, + PostgresDSN: appCfg.PostgresDSN, + AdminAPIURL: adminAPIURL(adminAPIAddr), + AdminAPIToken: appCfg.AdminAPIToken, + Password: appCfg.AdminUIPassword, + Token: appCfg.AdminUIToken, + SessionKey: sum[:], + }, nil } func adminAPIURL(addr string) string { @@ -104,13 +117,6 @@ func adminAPIURL(addr string) string { return "http://" + addr } -func envOr(key, def string) string { - if v := os.Getenv(key); v != "" { - return v - } - return def -} - func newCommandID(prefix string) string { var b [6]byte _, _ = rand.Read(b[:])