增加短信渠道

This commit is contained in:
Yvan
2026-09-29 18:15:35 +08:00
parent a16b8f8e89
commit 89cc7761b5
38 changed files with 1469 additions and 39 deletions
+3 -1
View File
@@ -87,7 +87,9 @@ func AccessLog(runtime *config.Store, logger *slog.Logger, version string) gin.H
paymentCallback := bodyPolicy == routecatalog.BodyPolicyPaymentCallback
paymentConfigWrite := bodyPolicy == routecatalog.BodyPolicyPaymentConfig
requestText := ""
if paymentCallback {
if bodyPolicy == routecatalog.BodyPolicySMS {
requestText = "[短信发送参数已隐藏]"
} else if paymentCallback {
requestText = paymentCallbackSummary(requestBody, c.GetHeader("Content-Type"))
} else if paymentConfigWrite {
requestText = paymentConfigSummary(requestBody)
+3
View File
@@ -101,6 +101,9 @@ func OperationAudit(runtime *config.Store, recorder *systemservice.AuditRecorder
if !capturedBody && routecatalog.BodyPolicyFor(c.Request.Method, path) == routecatalog.BodyPolicyPaymentConfig {
operationBody = paymentConfigSummary(requestBody)
}
if routecatalog.BodyPolicyFor(c.Request.Method, path) == routecatalog.BodyPolicySMS {
operationBody = "[短信发送参数已隐藏]"
}
if err := recorder.RecordOperationRequest(c.Request.Context(), &dto.OperationRecordRequest{IP: c.ClientIP(), Method: c.Request.Method, Path: path, Status: status, LatencyMS: time.Since(started).Milliseconds(), Agent: c.Request.UserAgent(), ErrorMessage: errorMessage, Body: operationBody, Response: responseBody, UserID: userID, RequestID: stringValue(requestID), TraceID: stringValueFromContext(c, "trace_id"), DeviceID: c.GetHeader("X-Device-Id")}); err != nil {
// Preserve the business response, but expose audit persistence failures
// to the global access/error logging pipeline.
+1
View File
@@ -20,6 +20,7 @@ var sensitivePayloadKeys = map[string]struct{}{
"passwd": {}, "pwd": {}, "token": {}, "accesstoken": {}, "refreshtoken": {},
"secret": {}, "clientsecret": {}, "apikey": {}, "privatekey": {}, "idcard": {},
"key": {}, "signingkey": {}, "secretkey": {},
"accesskeysecret": {}, "secretid": {},
"appkey": {}, "mchkey": {}, "apiv3key": {}, "clientcert": {}, "clientkey": {},
"platformcert": {}, "platformserialno": {}, "publiccert": {}, "credentialcode": {}, "certfile": {},
"keyfile": {}, "publickey": {}, "rootcert": {}, "appcert": {}, "webhookid": {},
@@ -0,0 +1,46 @@
package middleware
import (
"bytes"
"github.com/gin-gonic/gin"
"kra/internal/config"
"kra/internal/routecatalog"
"log/slog"
"net/http/httptest"
"strings"
"testing"
)
func TestSMSAuditHidesPhoneAndTemplateParameters(t *testing.T) {
gin.SetMode(gin.TestMode)
var output bytes.Buffer
engine := gin.New()
engine.Use(AccessLog(config.NewStore(&config.Config{Admin: &config.Admin{}}), slog.New(slog.NewJSONHandler(&output, nil)), "test"))
engine.POST("/api/integration/sms/:provider/send", func(c *gin.Context) {
if body, _ := c.Get(ctxReqBodyKey); body != "[短信发送参数已隐藏]" {
t.Fatalf("unsafe audit body: %v", body)
}
c.JSON(200, gin.H{"code": 0})
})
path := "/api/integration/sms/aliyun/send"
request := httptest.NewRequest("POST", path, strings.NewReader(`{"phone":"+8613800138000","params":{"code":"987654"}}`))
request.Header.Set("Content-Type", "application/json")
engine.ServeHTTP(httptest.NewRecorder(), request)
for _, value := range []string{"13800138000", "987654"} {
if strings.Contains(output.String(), value) {
t.Fatal("SMS content leaked into access log")
}
}
if !routecatalog.ShouldAudit("POST", path) {
t.Fatal("send route is not audited")
}
}
func TestSMSConfigSecretsAreRedacted(t *testing.T) {
text := redactJSON([]byte(`{"config":{"access_key_secret":"ali-value","secret_id":"tc-id-value","secret_key":"tc-value"}}`), "application/json", 4096)
for _, secret := range []string{"ali-value", "tc-id-value", "tc-value"} {
if strings.Contains(text, secret) {
t.Fatalf("secret leaked: %s", text)
}
}
}