fix(notify): support webhook sign (#24183)

This commit is contained in:
屈轩
2026-02-02 12:54:01 +08:00
committed by GitHub
parent 69c374f573
commit 4fe2a11223
7 changed files with 53 additions and 21 deletions
+1
View File
@@ -162,6 +162,7 @@ type SendParams struct {
Header jsonutils.JSONObject
Body jsonutils.JSONObject
MsgKey string
SecretKey string `json:"secret_key"`
DomainId string
RemoteTemplateParam SRemoteTemplateParam
GroupKey string
+10 -4
View File
@@ -21,6 +21,10 @@ import (
"yunion.io/x/onecloud/pkg/apis"
)
const (
WEBHOOK_SIGNATURE_HEADER = "X-Auth-Token"
)
type RobotCreateInput struct {
apis.SharableVirtualResourceCreateInput
apis.EnabledBaseResourceCreateInput
@@ -37,6 +41,7 @@ type RobotCreateInput struct {
Header jsonutils.JSONObject `json:"header"`
Body jsonutils.JSONObject `json:"body"`
MsgKey string `json:"msg_key"`
SecretKey string `json:"secret_key"`
UseTemplate tristate.TriState `json:"use_template"`
}
@@ -63,8 +68,9 @@ type RobotUpdateInput struct {
Address string `json:"address"`
// description: Language preference
// example: en
Lang string `json:"lang"`
Header jsonutils.JSONObject `json:"header"`
Body jsonutils.JSONObject `json:"body"`
MsgKey string `json:"msg_key"`
Lang string `json:"lang"`
Header jsonutils.JSONObject `json:"header"`
Body jsonutils.JSONObject `json:"body"`
MsgKey string `json:"msg_key"`
SecretKey string `json:"secret_key"`
}
+2
View File
@@ -41,6 +41,7 @@ type RobotCreateOptions struct {
Header string
Body string
MsgKey string
SecretKey string
UseTemplate bool `help:"just for webhook"`
}
@@ -90,6 +91,7 @@ type SrobotUpdateOptions struct {
Header *string
Body *string
MsgKey string
SecretKey string
UseTemplate tristate.TriState
}
+1
View File
@@ -365,6 +365,7 @@ func (nm *SNotificationManager) PerformContactNotify(ctx context.Context, userCr
params.Header = robot.Header
params.Body = robot.Body
params.MsgKey = robot.MsgKey
params.SecretKey = robot.SecretKey
params.Receivers = api.SNotifyReceiver{
Contact: robot.Address,
}
+21 -17
View File
@@ -60,13 +60,15 @@ type SRobot struct {
db.SSharableVirtualResourceBase
db.SEnabledResourceBase
Type string `width:"16" nullable:"false" create:"required" get:"user" list:"user" index:"true"`
Address string `nullable:"false" create:"required" update:"user" get:"user" list:"user"`
Lang string `width:"16" nullable:"false" create:"required" update:"user" get:"user" list:"user"`
Header jsonutils.JSONObject `length:"long" charset:"utf8" nullable:"true" list:"user" create:"optional" update:"user"`
Body jsonutils.JSONObject `length:"long" charset:"utf8" nullable:"true" list:"user" create:"optional" update:"user"`
MsgKey string `width:"16" nullable:"true" update:"user" get:"user" list:"user"`
UseTemplate tristate.TriState `default:"false" list:"domain" update:"user" create:"admin_optional"`
Type string `width:"16" nullable:"false" create:"required" get:"user" list:"user" index:"true"`
Address string `nullable:"false" create:"required" update:"user" get:"user" list:"user"`
Lang string `width:"16" nullable:"false" create:"required" update:"user" get:"user" list:"user"`
Header jsonutils.JSONObject `length:"long" charset:"utf8" nullable:"true" list:"user" create:"optional" update:"user"`
Body jsonutils.JSONObject `length:"long" charset:"utf8" nullable:"true" list:"user" create:"optional" update:"user"`
MsgKey string `width:"16" nullable:"true" update:"user" get:"user" list:"user"`
// webhook 签名加密
SecretKey string `width:"128" nullable:"true" update:"user"`
UseTemplate tristate.TriState `default:"false" list:"domain" update:"user" create:"admin_optional"`
}
var RobotList = []string{api.FEISHU_ROBOT, api.DINGTALK_ROBOT, api.WORKWX_ROBOT, api.WEBHOOK, api.WEBHOOK_ROBOT}
@@ -98,11 +100,12 @@ func (rm *SRobotManager) ValidateCreateData(ctx context.Context, userCred mcclie
Contact: input.Address,
DomainId: input.ProjectDomainId,
},
Header: input.Header,
Body: input.Body,
MsgKey: input.MsgKey,
Title: "Validate",
Message: "This is a verification message, please ignore.",
Header: input.Header,
Body: input.Body,
MsgKey: input.MsgKey,
SecretKey: input.SecretKey,
Title: "Validate",
Message: "This is a verification message, please ignore.",
})
if err != nil {
if errors.ErrConnectRefused == errors.Cause(err) {
@@ -158,11 +161,12 @@ func (r *SRobot) ValidateUpdateData(ctx context.Context, userCred mcclient.Token
// check Address
dirver := GetDriver(fmt.Sprintf("%s-robot", r.Type))
err := dirver.Send(ctx, api.SendParams{
Header: input.Header,
Body: input.Body,
MsgKey: input.MsgKey,
Title: "Validate",
Message: "This is a verification message, please ignore.",
Header: input.Header,
Body: input.Body,
MsgKey: input.MsgKey,
SecretKey: input.SecretKey,
Title: "Validate",
Message: "This is a verification message, please ignore.",
Receivers: api.SNotifyReceiver{
Contact: input.Address,
},
+17
View File
@@ -15,6 +15,9 @@ package sender
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"net/http"
"strings"
@@ -35,6 +38,15 @@ func (self *SWebhookSender) GetSenderType() string {
return api.WEBHOOK_ROBOT
}
func GenerateHMACSignature(payload []byte, secret string) string {
// 创建HMAC哈希器
h := hmac.New(sha256.New, []byte(secret))
// 写入要签名的数据
h.Write(payload)
// 计算哈希值并转为16进制字符串
return hex.EncodeToString(h.Sum(nil))
}
func (self *SWebhookSender) Send(ctx context.Context, args api.SendParams) error {
dict := jsonutils.NewDict()
header := http.Header{}
@@ -75,6 +87,11 @@ func (self *SWebhookSender) Send(ctx context.Context, args api.SendParams) error
}
}
if len(args.SecretKey) > 0 {
signature := GenerateHMACSignature([]byte(jsonutils.Marshal(dict).String()), args.SecretKey)
header.Set(api.WEBHOOK_SIGNATURE_HEADER, signature)
}
_, _, err := httputils.JSONRequest(cli, ctx, httputils.POST, args.Receivers.Contact, header, dict, false)
return errors.Wrap(err, "webhook send")
}
@@ -265,6 +265,7 @@ func (notificationSendTask *NotificationSendTask) batchSend(ctx context.Context,
params.Header = robot.Header
params.Body = robot.Body
params.MsgKey = robot.MsgKey
params.SecretKey = robot.SecretKey
params.GroupTimes = uint(receivers[i].rNotificaion.GroupTimes)
err = driver.Send(ctx, params)
if err != nil {