Skip to content

Commit

Permalink
Merge pull request #344 from Zhang21/feat-dingdingSign
Browse files Browse the repository at this point in the history
feat: 钉钉加签
  • Loading branch information
feiyu563 committed Nov 15, 2023
2 parents 08d0d7d + 4aeb8e1 commit c75472e
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 13 deletions.
3 changes: 2 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ make docker/docker-push/docker-test
# 本地测试运行
make clean && make build
copy conf/app-example.conf conf/app.conf
build/bin/PrometheusAlert
./PrometheusAlert

# 测试应用健康
curl http://localhost:8080/health
Expand Down Expand Up @@ -136,6 +136,7 @@ feiyu563/prometheus-alert:latest
- 增加支持飞书机器人应用。
- 增加告警组,可以将通知媒介写到告警组里面,便于配置和修改。
- 增加热加载配置接口
- 增加钉钉加签

-------------------------------------

Expand Down
3 changes: 3 additions & 0 deletions conf/app-example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ open-dingding=1
ddurl=https://oapi.dingtalk.com/robot/send?access_token=xxxxx
#是否开启 @所有人(0为关闭,1为开启)
dd_isatall=1
#是否开启钉钉机器人加签,0为关闭,1为开启
# 使用方法:https://oapi.dingtalk.com/robot/send?access_token=XXXXXX&secret=mysecret
open-dingding-secret=0

#是否开启微信告警通道,可同时开始多个通道0为关闭,1为开启
open-weixin=1
Expand Down
57 changes: 53 additions & 4 deletions controllers/dingding.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package controllers
import (
"PrometheusAlert/models"
"bytes"
"crypto/hmac"
"crypto/sha256"
"crypto/tls"
"encoding/base64"
"encoding/json"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"io/ioutil"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"

"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)

type DDMessage struct {
Expand All @@ -31,6 +37,11 @@ func PostToDingDing(title, text, Ddurl, AtSomeOne, logsign string) string {
logs.Info(logsign, "[dingding]", "钉钉接口未配置未开启状态,请先配置open-dingding为1")
return "钉钉接口未配置未开启状态,请先配置open-dingding为1"
}
// dingding sign
if openSecret := beego.AppConfig.String("open-dingding-secret"); openSecret == "1" {
Ddurl = dingdingSign(Ddurl)
}

Isatall, _ := beego.AppConfig.Int("dd_isatall")
Atall := true
if Isatall == 0 {
Expand Down Expand Up @@ -82,7 +93,7 @@ func PostToDingDing(title, text, Ddurl, AtSomeOne, logsign string) string {
logs.Error(logsign, "[dingding]", err.Error())
}
defer res.Body.Close()
result, err := ioutil.ReadAll(res.Body)
result, err := io.ReadAll(res.Body)
if err != nil {
logs.Error(logsign, "[dingding]", err.Error())
}
Expand All @@ -91,3 +102,41 @@ func PostToDingDing(title, text, Ddurl, AtSomeOne, logsign string) string {
logs.Info(logsign, "[dingding]", string(result))
return string(result)
}

// dingdingSign adds sign and timestamp parms to dingding webhook url
// docs: https://open.dingtalk.com/document/orgapp/custom-bot-creation-and-installation
func dingdingSign(ddurl string) string {
timestamp := time.Now()
timestampMs := timestamp.UnixNano() / int64(time.Millisecond)
tsMsStr := strconv.FormatInt(timestampMs, 10)
// parse ddurl parms
u, err := url.Parse(ddurl)
if err != nil {
logs.Info("[dingdingSign]", "配置文件已开启钉钉加签,钉钉机器人地址解析加签参数 secret 失败,将使用不加签的地址!")
return ddurl
}
// get parm secret
queryParams := u.Query()
secret := queryParams.Get("secret")
if len(secret) == 0 {
logs.Info("[dingdingSign]", "配置文件已开启钉钉加签,钉钉机器人地址解析加签参数 secret 为空,将使用不加签的地址!")
return ddurl
}
// sign string
signStr := tsMsStr + "\n" + secret
// HmacSHA256
key := []byte(secret)
h := hmac.New(sha256.New, key)
h.Write([]byte(signStr))
signature := h.Sum(nil)
// Base64
sign := base64.StdEncoding.EncodeToString(signature)
// splice url
delete(queryParams, "secret")
queryParams.Add("timestamp", tsMsStr)
queryParams.Add("sign", sign)
u.RawQuery = queryParams.Encode()
signURL := u.String()

return signURL
}
42 changes: 42 additions & 0 deletions controllers/dingding_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package controllers

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
)

func TestDDMesage(t *testing.T) {
// A sample dingding message json payload
payload := `
{
"msgtype": "markdown",
"markdown": {
"title": "AlertPrometheus告警测试",
"text": "**测试告警信息**\n"
},
"at": {
"atMobiles": ["139xxxxxxxx", "159xxxxxxxx"],
"isAtAll": false
}
}`
message := DDMessage{}
err := json.Unmarshal([]byte(payload), &message)
assert.Nil(t, err)
}

func TestDingdingSign(t *testing.T) {
var want, result string

// url without parm secret
withoutURL := "https://oapi.dingtalk.com/robot/send?access_token=XXX"
want = withoutURL
result = dingdingSign(withoutURL)
assert.Equal(t, want, result)

// url with parm secret
withURL := "https://oapi.dingtalk.com/robot/send?access_token=XXX&secret=mysecret"
result = dingdingSign(withURL)
t.Logf("一个示例的加签的地址:%s", result)
}
54 changes: 46 additions & 8 deletions doc/readme/conf-dingding.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# PrometheusAlert全家桶钉钉配置说明

-----------------

**开启钉钉机器人**
## 开启钉钉机器人

打开钉钉,进入钉钉群中,选择群设置-->智能群助手-->添加机器人-->自定义,可参下图:

![ding](../images/dingding1.png)

![ding2](../images/dingding2.png)

<br/>

新版本的钉钉加了安全设置,只需选择安全设置中的 自定义关键词 即可,并将关键词设置为 Prometheus或者app.conf中设置的title值均可,参考下图

![ding3](../images/dingding3.png)
Expand All @@ -18,12 +18,15 @@

复制图中的Webhook地址,并填入PrometheusAlert配置文件app.conf中对应配置项即可。

<br/>

**PS: 钉钉机器人目前已经支持 `@某人` ,使用该功能需要取得对应用户的钉钉关联手机号码,如下图:**

![ding4](../images/dingding5.png)

钉钉目前支持只支持markdown语法的子集,具体支持的元素如下:

```
```md
标题
# 一级标题
## 二级标题
Expand Down Expand Up @@ -54,9 +57,38 @@
2. item2
```

钉钉相关配置:
<br/>
<br/>

## 钉钉加签配置

增加钉钉加签的配置。创建自定义机器人的时候,选择加签,并复制加签内容组装到到机器人地址参数(webhook url parm secret)。程序会获取这个 `secret` 参数,进行加签处理之后生成对应的加签地址。

如果配置文件中启用了钉钉加签认证,但 webhook url 并没有传递 parm secret,那么程序将返回不加签的地址。也就是说,PrometheusAlert 配置中启用钉钉加签并不会影响不加签的机器人。

示例如下:

```conf
# 默认的钉钉机器人地址 webhook url 格式
https://oapi.dingtalk.com/robot/send?access_token=XXX
# 假如机器人加签内容为:mysecret
# 带上加签参数: secret=mysecret
https://oapi.dingtalk.com/robot/send?access_token=XXX&secret=mysecret
# 程序加签处理后生成的加签地址
https://oapi.dingtalk.com/robot/send?access_token=XXXXXX&timestamp=XXX&sign=XXX
# 如果配置文件中启用了钉钉加签认证,但 webhook url 并没有传递 parm secret,那么程序将返回不加签的地址
https://oapi.dingtalk.com/robot/send?access_token=XXX
```

<br/>
<br/>

## 钉钉相关配置

```ini
#---------------------↓全局配置-----------------------
#告警消息标题
title=PrometheusAlert
Expand All @@ -72,15 +104,21 @@ open-dingding=1
ddurl=https://oapi.dingtalk.com/robot/send?access_token=xxxxx
#是否开启 @所有人(0为关闭,1为开启)
dd_isatall=1
#是否开启钉钉机器人加签,0为关闭,1为开启
# 使用方法:https://oapi.dingtalk.com/robot/send?access_token=XXXXXX&secret=mysecret
open-dingding-secret=0
```

**如何使用**
<br/>
<br/>

## 如何使用

以Prometheus配合自定义模板为例:

Prometheus配置参考:

```
```yml
global:
resolve_timeout: 5m
route:
Expand All @@ -93,4 +131,4 @@ receivers:
- name: 'web.hook.prometheusalert'
webhook_configs:
- url: 'http://[prometheusalert_url]:8080/prometheusalert?type=dd&tpl=prometheus-dd&ddurl=钉钉机器人地址,钉钉机器人地址2&at=18888888888,18888888889'
```
```

0 comments on commit c75472e

Please sign in to comment.