fix: remove hardcoded secrets from embedded config and add JWT algorithm verification

Replace hardcoded JWT secret, DB passwords, OSS credentials, and API
keys in embedded config.yaml with empty strings. Add JWT secret validation
at startup. Add HMAC algorithm verification in ParseToken to prevent
JWT algorithm confusion attacks.
pull/727/head
saaa99999999 4 months ago
parent 2f55b4b5d7
commit c3ceb17f19

@ -5,7 +5,9 @@
package conf package conf
import ( import (
"fmt"
"log" "log"
"os"
"time" "time"
"github.com/alimy/tryst/cfg" "github.com/alimy/tryst/cfg"
@ -141,6 +143,14 @@ func setupSetting(suite []string, noDefault bool) error {
RedisCacheIndexSetting.ExpireInSecond *= time.Second RedisCacheIndexSetting.ExpireInSecond *= time.Second
redisSetting.ConnWriteTimeout *= time.Second redisSetting.ConnWriteTimeout *= time.Second
// Validate critical security settings
if JWTSetting.Secret == "" {
fmt.Fprintf(os.Stderr, "fatal: JWT Secret is not set. Generate one with: openssl rand -base64 32
Set it in custom/config.yaml under JWT.Secret
")
os.Exit(1)
}
return nil return nil
} }

@ -102,7 +102,7 @@ SmsJuhe:
Alipay: Alipay:
AppID: "paopao-ce-app-id" AppID: "paopao-ce-app-id"
InProduction: True InProduction: True
PrivateKey: "MIICXAIBAAKBgQCzXV/spaX9+eOjM5f12W6eDTtszU9f9rgpXG4EQwzZI3WM5+Fe+9Bn6NQQILfF1o3Z+3BEzHMMcYwxrQw/toq2o6JPchbUK7eArKc6pl/GV3uIefZdKncz5bZvCFMgiJrpy75lYKhJgotQFEfQd+ks2t0gtC007uOjmY9QDB2EVQIDAQABAoGAMruhi0UbW2gYHCxWuiJDKI9jlJXJ8sHNO126fJgehTiDYlSgKYaeXxW7DcjDUkEqpFJ7YepWTFm9prtksIzIVQFNNjstI6cvowVF2t+lWf7mIB4w0ugarVd+SXssQK830Og3kjtZ84a3BbC6uf3a/qcgoIO8Sj1VnzOJ8fEYl+0CQQDeG6JhauGDOC8oCTwbFs9QPpjwGnp7UkYAJNg7jn4uBSVeg4lwb5uj9TshLSp49geNkPcWeCythuiz1jvoTqEjAkEAzrwIBxUPT1WmcDUXAkVPaQNADDbhMZLdw5nHZEUVwmO3o1FkJky4MLjLjT977400mhsnsQCy4sAWUZs6aEyoJwJARK3U2zy6eOHhqwaYAGRgPJbuoaf+Ya3CGX9LIbdhCwfqUzxnPk40mVFWNF8L+BVTppHB5b/JSOsjf6BqK95McwJBAL+kvUhbdHrV6lmgTXkUaV3u3mO0SCPdgui9WIKSLG6sY+LpI48BlcnMtR12WVyjKL0nKS9Dd5EOAmKaJJXlYgcCQGWbWCn9KUDUqpm4o3wr5nwXzlS74XYZo65UAM7TSzHRpcovfv5uiQ0VRLImWeiSXKK2aTOBGn5eKbevRTxN07k=" PrivateKey: "" # REQUIRED: Set Alipay merchant private key
RootCertFile: "custom/alipay/RootCert.crt" RootCertFile: "custom/alipay/RootCert.crt"
PublicCertFile: "custom/alipay/CertPublicKey_RSA2.crt" PublicCertFile: "custom/alipay/CertPublicKey_RSA2.crt"
AppPublicCertFile: "custom/alipay/AppCertPublicKey.crt" AppPublicCertFile: "custom/alipay/AppCertPublicKey.crt"
@ -142,12 +142,12 @@ LoggerZinc: # 使用Zinc写日志
Host: zinc:4080 Host: zinc:4080
Index: paopao-log Index: paopao-log
User: admin User: admin
Password: admin Password: "" # REQUIRED: Set Zinc password
Secure: False Secure: False
LoggerMeili: # 使用Meili写日志 LoggerMeili: # 使用Meili写日志
Host: meili:7700 Host: meili:7700
Index: paopao-log Index: paopao-log
ApiKey: paopao-meilisearch ApiKey: "" # REQUIRED: Set Meilisearch API key
Secure: False Secure: False
MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5
MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100
@ -156,20 +156,20 @@ LoggerOpenObserve: # 使用OpenObserve写日志
Organization: paopao-ce Organization: paopao-ce
Stream: default Stream: default
User: root@paopao.info User: root@paopao.info
Password: tiFEI8UeJWuYA7kN Password: "" # REQUIRED: Set OpenObserve password
Secure: False Secure: False
MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5
MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100
LoggerOtlp: # 使用OpenTelemetry写日志 LoggerOtlp: # 使用OpenTelemetry写日志
Endpoint: openobserve:5081 Endpoint: openobserve:5081
Authorization: Basic ls8icEBvcGVub2JzFXJ2ZS6haCpZTU4ybGdBUFlXcjA0UdNk Authorization: "" # REQUIRED: Set OTLP auth token
Organization: paopao-ce Organization: paopao-ce
TraceStream: paopao-trace TraceStream: paopao-trace
MetricStream: paopao-metric MetricStream: paopao-metric
LogStream: paopao-log LogStream: paopao-log
Insecure: true Insecure: true
JWT: # 鉴权加密 JWT: # 鉴权加密
Secret: 18a6413dc4fe394c66345ebe501b2f26 Secret: "" # REQUIRED: Set a strong random secret (openssl rand -base64 32)
Issuer: paopao-api Issuer: paopao-api
Expire: 86400 Expire: 86400
AdminSettings: AdminSettings:
@ -181,12 +181,12 @@ Zinc: # Zinc搜索配置
Host: zinc:4080 Host: zinc:4080
Index: paopao-data Index: paopao-data
User: admin User: admin
Password: admin Password: "" # REQUIRED: Set Zinc admin password
Secure: False Secure: False
Meili: # Meili搜索配置 Meili: # Meili搜索配置
Host: meili:7700 Host: meili:7700
Index: paopao-data Index: paopao-data
ApiKey: paopao-meilisearch ApiKey: "" # REQUIRED: Set Meilisearch API key
Secure: False Secure: False
ObjectStorage: # 对象存储通用配置 ObjectStorage: # 对象存储通用配置
RetainInDays: 2 # 临时对象过期时间多少天 RetainInDays: 2 # 临时对象过期时间多少天
@ -210,15 +210,15 @@ HuaweiOBS: # 华为云OBS存储配置
Bucket: paopao Bucket: paopao
Domain: Domain:
MinIO: # MinIO 存储配置 MinIO: # MinIO 存储配置
AccessKey: Q3AM3UQ867SPQQA43P2F AccessKey: "" # REQUIRED: Set MinIO access key
SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG SecretKey: "" # REQUIRED: Set MinIO secret key
Secure: False Secure: False
Endpoint: minio:9000 Endpoint: minio:9000
Bucket: paopao Bucket: paopao
Domain: 127.0.0.1:9000 Domain: 127.0.0.1:9000
S3: # Amazon S3 存储配置 S3: # Amazon S3 存储配置
AccessKey: "YOUR-ACCESSKEYID" AccessKey: "" # REQUIRED: Set AWS access key
SecretKey: "YOUR-SECRETACCESSKEY" SecretKey: "" # REQUIRED: Set AWS secret key
Secure: True Secure: True
Endpoint: s3.amazonaws.com Endpoint: s3.amazonaws.com
Bucket: paopao Bucket: paopao
@ -233,7 +233,7 @@ Database: # Database通用配置
TablePrefix: p_ # 表名前缀 TablePrefix: p_ # 表名前缀
MySQL: # MySQL数据库 MySQL: # MySQL数据库
Username: paopao Username: paopao
Password: paopao Password: "" # REQUIRED: Set the MySQL password
Host: db:3306 Host: db:3306
DBName: paopao DBName: paopao
Charset: utf8mb4 Charset: utf8mb4
@ -242,7 +242,7 @@ MySQL: # MySQL数据库
MaxOpenConns: 30 MaxOpenConns: 30
Postgres: # PostgreSQL数据库 Postgres: # PostgreSQL数据库
User: paopao User: paopao
Password: paopao Password: "" # REQUIRED: Set the Postgres password
DBName: paopao DBName: paopao
Schema: public Schema: public
Host: localhost Host: localhost

@ -7,6 +7,7 @@ package app
import ( import (
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"fmt"
"time" "time"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
@ -42,7 +43,10 @@ func GenerateToken(user *ms.User) (string, error) {
func ParseToken(token string) (res *Claims, err error) { func ParseToken(token string) (res *Claims, err error) {
var tokenClaims *jwt.Token var tokenClaims *jwt.Token
tokenClaims, err = jwt.ParseWithClaims(token, &Claims{}, func(_ *jwt.Token) (any, error) { tokenClaims, err = jwt.ParseWithClaims(token, &Claims{}, func(t *jwt.Token) (any, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
}
return GetJWTSecret(), nil return GetJWTSecret(), nil
}) })
if err == nil && tokenClaims != nil && tokenClaims.Valid { if err == nil && tokenClaims != nil && tokenClaims.Valid {

Loading…
Cancel
Save