webhook.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package sender
  15. import (
  16. "context"
  17. "crypto/hmac"
  18. "crypto/sha256"
  19. "encoding/hex"
  20. "net/http"
  21. "strings"
  22. "yunion.io/x/cloudmux/pkg/cloudprovider"
  23. "yunion.io/x/jsonutils"
  24. "yunion.io/x/pkg/errors"
  25. "yunion.io/x/pkg/util/httputils"
  26. api "yunion.io/x/onecloud/pkg/apis/notify"
  27. "yunion.io/x/onecloud/pkg/notify/models"
  28. )
  29. type SWebhookSender struct {
  30. config map[string]api.SNotifyConfigContent
  31. }
  32. func (self *SWebhookSender) GetSenderType() string {
  33. return api.WEBHOOK_ROBOT
  34. }
  35. func GenerateHMACSignature(payload []byte, secret string) string {
  36. // 创建HMAC哈希器
  37. h := hmac.New(sha256.New, []byte(secret))
  38. // 写入要签名的数据
  39. h.Write(payload)
  40. // 计算哈希值并转为16进制字符串
  41. return hex.EncodeToString(h.Sum(nil))
  42. }
  43. func (self *SWebhookSender) Send(ctx context.Context, args api.SendParams) error {
  44. dict := jsonutils.NewDict()
  45. header := http.Header{}
  46. if len(args.Event) == 0 {
  47. if len(args.MsgKey) == 0 {
  48. dict.Set("Msg", jsonutils.NewString(args.Message))
  49. } else {
  50. dict.Set(args.MsgKey, jsonutils.NewString(args.Message))
  51. }
  52. if args.Body != nil {
  53. jsonutils.Update(dict, args.Body)
  54. }
  55. } else {
  56. body, err := jsonutils.ParseString(args.Message)
  57. if err != nil {
  58. return errors.Wrapf(err, "unable to parse %q", args.Message)
  59. }
  60. jsonutils.Update(dict, body)
  61. if len(args.MsgKey) == 0 {
  62. dict.Set("Msg", jsonutils.NewString(args.Message))
  63. } else {
  64. dict.Set(args.MsgKey, jsonutils.NewString(args.Message))
  65. }
  66. if args.Body != nil {
  67. jsonutils.Update(dict, args.Body)
  68. }
  69. event := strings.ToUpper(args.Event)
  70. header.Set(EVENT_HEADER, event)
  71. }
  72. if args.Header != nil {
  73. resmap, _ := args.Header.GetMap()
  74. for k, v := range resmap {
  75. vStr, err := v.GetString()
  76. if err != nil {
  77. continue
  78. }
  79. header.Set(k, vStr)
  80. }
  81. }
  82. if len(args.SecretKey) > 0 {
  83. signature := GenerateHMACSignature([]byte(jsonutils.Marshal(dict).String()), args.SecretKey)
  84. header.Set(api.WEBHOOK_SIGNATURE_HEADER, signature)
  85. }
  86. _, _, err := httputils.JSONRequest(cli, ctx, httputils.POST, args.Receivers.Contact, header, dict, false)
  87. return errors.Wrap(err, "webhook send")
  88. }
  89. func (websender *SWebhookSender) ValidateConfig(ctx context.Context, config api.NotifyConfig) (string, error) {
  90. return "", cloudprovider.ErrNotImplemented
  91. }
  92. func (websender *SWebhookSender) UpdateConfig(config api.NotifyConfig) error {
  93. return cloudprovider.ErrNotImplemented
  94. }
  95. func (websender *SWebhookSender) AddConfig(config api.NotifyConfig) error {
  96. return cloudprovider.ErrNotImplemented
  97. }
  98. func (websender *SWebhookSender) DeleteConfig(config api.NotifyConfig) error {
  99. return cloudprovider.ErrNotImplemented
  100. }
  101. func (websender *SWebhookSender) ContactByMobile(ctx context.Context, mobile, domainId string) (string, error) {
  102. return "", cloudprovider.ErrNotImplemented
  103. }
  104. func (websender *SWebhookSender) IsPersonal() bool {
  105. return true
  106. }
  107. func (websender *SWebhookSender) IsRobot() bool {
  108. return true
  109. }
  110. func (websender *SWebhookSender) IsValid() bool {
  111. return len(websender.config) > 0
  112. }
  113. func (websender *SWebhookSender) IsPullType() bool {
  114. return true
  115. }
  116. func (websender *SWebhookSender) IsSystemConfigContactType() bool {
  117. return true
  118. }
  119. func (websender *SWebhookSender) GetAccessToken(ctx context.Context, key string) error {
  120. return nil
  121. }
  122. func (websender *SWebhookSender) RegisterConfig(config models.SConfig) {
  123. }
  124. func init() {
  125. models.Register(&SWebhookSender{
  126. config: map[string]api.SNotifyConfigContent{},
  127. })
  128. }