feat(auth): support per-deploy login password key override
Deployment Config CI / Deployment Config (push) Successful in 27s
Backend CI / Backend (push) Successful in 15m4s

Multi-replica deployments need every Pod/container to share one RSA private key, otherwise public keys handed to the browser may not match the key that decrypts the resulting ciphertext. Introduce a `*.local.yaml` override layer that ops-config and tenant-config both load on top of the base config, ship example overrides plus compose/k3s wiring, and tolerate PEM bodies that arrive folded or escaped from Secrets.
This commit is contained in:
2026-05-14 11:54:40 +08:00
parent 2bc192b3c7
commit b939cfa2fa
16 changed files with 310 additions and 10 deletions
+11
View File
@@ -36,11 +36,22 @@ sudo k3s ctr images import images.tar
- `SCHEDULER_INTERNAL_METRICS_TOKEN`
- `BROWSER_FETCH_TOKEN`
- `POSTGRES_PASSWORD` / `RABBITMQ_DEFAULT_PASS` / `MINIO_ROOT_*`
- `config.local.yaml` 里的 `auth.password_cipher.private_key_pem`
- `ops-config.local.yaml` 里的 `auth.password_cipher.private_key_pem`
- `config/config.yaml` 里的 LLM / SiliconFlow API key
- `config.local.yaml` 里对应的数据库、RabbitMQ、MinIO、JWT 配置
注意:应用运行时通过 `pgbouncer` / `monitoring-pgbouncer` 访问数据库;`migrate` 任务仍然直连 `postgres` / `monitoring-postgres`。数据库密码统一来自 `POSTGRES_PASSWORD` secret,应用配置和 PgBouncer 都会跟随这个 secret。
登录密码加密使用 RSA-OAEP-SHA256。多 Pod 部署时,同一类服务的所有副本必须读取同一把私钥和同一个 `key_id`,否则某个 Pod 下发的公钥对应密文可能被另一个 Pod 解不开。建议租户端和 ops 端分别生成不同私钥:
```bash
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out login-password-rsa.pem
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ops-login-password-rsa.pem
```
然后把完整 PEM 分别粘贴到 `deploy/k3s/secrets.yaml``config.local.yaml``ops-config.local.yaml`
## 3. 部署
```bash
+5
View File
@@ -556,6 +556,11 @@ spec:
items:
- key: ops-config.yaml
path: ops-config.yaml
- secret:
name: geo-rankly-app-secret
items:
- key: ops-config.local.yaml
path: ops-config.local.yaml
---
apiVersion: v1
kind: Service
+62 -2
View File
@@ -1,6 +1,11 @@
server:
port: 8080
mode: release
# 生产环境请配置为真实前端域名,例如 https://app.example.com。
# 留空时沿用开发环境 CORS 放开策略。
allowed_origins: []
security_headers:
enabled: true
trusted_proxies:
- 127.0.0.1
- ::1
@@ -30,6 +35,47 @@ monitoring_database:
rabbitmq:
url: amqp://geo:geo_dev@rabbitmq:5672/geo
monitor_result_exchange: monitor.result
monitor_result_routing_key: monitor.result.ingest
monitor_result_queue: monitor.result.ingest
monitor_result_dlx: monitor.result.dlx
monitor_result_dlq: monitor.result.ingest.dlq
monitor_result_dlq_routing_key: monitor.result.ingest.dlq
monitor_projection_exchange: monitor.projection
monitor_projection_routing_key: monitor.projection.rebuild
monitor_projection_queue: monitor.projection.rebuild
monitor_projection_dlx: monitor.projection.dlx
monitor_projection_dlq: monitor.projection.rebuild.dlq
monitor_projection_dlq_routing_key: monitor.projection.rebuild.dlq
generation_exchange: generation.task
generation_routing_key: generation.task.run
generation_queue: generation.task.run
generation_dlx: generation.task.dlx
generation_dlq: generation.task.run.dlq
generation_dlq_routing_key: generation.task.run.dlq
generation_event_exchange: generation.event
desktop_task_event_exchange: desktop.task.event
desktop_dispatch_exchange: desktop.task.dispatch
desktop_dispatch_publish_prefix: publish
desktop_dispatch_monitor_prefix: monitor
desktop_account_health_exchange: desktop.account.health
desktop_account_health_routing_key: desktop.account.health.report
desktop_account_health_queue: desktop.account.health.report
desktop_account_health_dlx: desktop.account.health.dlx
desktop_account_health_dlq: desktop.account.health.report.dlq
desktop_account_health_dlq_routing_key: desktop.account.health.report.dlq
template_assist_exchange: template.assist
template_assist_routing_key: template.assist.run
template_assist_queue: template.assist.run
template_assist_dlx: template.assist.dlx
template_assist_dlq: template.assist.run.dlq
template_assist_dlq_routing_key: template.assist.run.dlq
kol_assist_exchange: kol.assist
kol_assist_routing_key: kol.assist.run
kol_assist_queue: kol.assist.run
kol_assist_dlx: kol.assist.dlx
kol_assist_dlq: kol.assist.run.dlq
kol_assist_dlq_routing_key: kol.assist.run.dlq
compliance_review_exchange: compliance.review
compliance_review_routing_key: compliance.review.run
compliance_review_queue: compliance.review.run
@@ -53,6 +99,9 @@ monitoring_workers:
result_ingest_concurrency: 4
projection_rebuild_concurrency: 2
monitoring_dispatch:
desktop_tasks_rollout_percentage: 5
membership:
default_plan_code: free
plans:
@@ -96,7 +145,6 @@ brand_library:
max_keywords: 5
max_questions_per_keyword: 5
redis:
addr: redis:6379
db: 0
@@ -126,6 +174,16 @@ jwt:
access_ttl: 15m
refresh_ttl: 720h
auth:
login_guard:
enabled: true
password_cipher:
# 留空 private_key_pem 时会在单进程内生成临时密钥;生产多 Pod 请在
# geo-rankly-app-secret/config.local.yaml 中配置同一把私钥。
enabled: true
key_id: login-password-rsa-oaep-v1
private_key_pem: ""
log:
level: info,warn,error
format: json
@@ -182,14 +240,16 @@ browser_fetch:
enabled: true
provider: lightpanda
service_url: http://browser-fetch:8082
token: dev-browser-fetch-token
queue_size: 64
worker_concurrency: 2
worker_concurrency: 3
request_timeout: 45s
cache_ttl: 6h
allowed_domains:
- zhuanlan.zhihu.com
- zhihu.com
- baidu.com
- weixin.sogou.com
trigger_status:
- 403
- 429
+13
View File
@@ -1,6 +1,11 @@
server:
port: 8090
mode: release
# 生产环境请配置为真实运维后台域名,例如 https://ops.example.com。
# 留空时沿用开发环境 CORS 放开策略。
allowed_origins: []
security_headers:
enabled: true
trusted_proxies:
- 127.0.0.1
- ::1
@@ -43,6 +48,14 @@ jwt:
secret: "geo-ops-15645415841"
access_ttl: 8h
auth:
password_cipher:
# 留空 private_key_pem 时会在单进程内生成临时密钥;生产多 Pod 请在
# geo-rankly-app-secret/ops-config.local.yaml 中配置同一把私钥。
enabled: true
key_id: ops-password-rsa-oaep-v1
private_key_pem: ""
default_admin:
username: admin
display_name: system-admin
+22
View File
@@ -35,3 +35,25 @@ stringData:
browser_fetch:
token: ${BROWSER_FETCH_TOKEN:geo-browser-fetch-change-me}
auth:
password_cipher:
enabled: true
key_id: login-password-rsa-oaep-v1
# 多 Pod 必须使用同一把私钥;上线前用 `openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048`
# 生成后粘贴完整 PEM。不要把生产私钥提交到代码仓库。
private_key_pem: |
-----BEGIN PRIVATE KEY-----
REPLACE_WITH_TENANT_LOGIN_PASSWORD_RSA_PRIVATE_KEY
-----END PRIVATE KEY-----
ops-config.local.yaml: |
auth:
password_cipher:
enabled: true
key_id: ops-password-rsa-oaep-v1
# 建议与租户端使用不同私钥;所有 ops-api Pod 必须挂载同一份 Secret。
private_key_pem: |
-----BEGIN PRIVATE KEY-----
REPLACE_WITH_OPS_LOGIN_PASSWORD_RSA_PRIVATE_KEY
-----END PRIVATE KEY-----