0%

Nightingale(二)——改造

Nightingale改造

修改说明

1、新增tools工具类:

nightingale-6.2.0/toolUtils

该工具类实现了DES加解密功能、私密数据模糊功能

2、修改user相关类:

以DecryptUserGetsByIds为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func DecryptUserGetsByIds(ctx *ctx.Context, ids []int64) ([]User, error) {
if len(ids) == 0 {
return []User{}, nil
}

var lst []User
err := DB(ctx).Where("id in ?", ids).Order("username").Find(&lst).Error
if err == nil {
for i := 0; i < len(lst); i++ {
lst[i].RolesLst = strings.Fields(lst[i].Roles)
lst[i].Admin = lst[i].IsAdmin()
//对显示的邮箱等数据进行脱敏并模糊显示
encryptedEmail, err := toolUtils.Decrypt(lst[i].Email, deskey)
if err != nil {
return lst, errors.WithMessage(err, "email encrypted wrong!")
}
lst[0].Email = toolUtils.DesEmail(encryptedEmail, "1")
//对显示的手机等数据进行脱敏并模糊显示
encryptedTelephone, err := toolUtils.Decrypt(lst[i].Phone, deskey)
if err != nil {
return lst, errors.WithMessage(err, "telephone encrypted wrong!")
}
lst[i].Phone = toolUtils.DesMobile(encryptedTelephone, "1")
}
}

return lst, err
}

同时修改前端调用后端接口。将其指向加密后函数(decrypt、encrypt开头函数)

目前采用的是通知脚本的形式去对接基础服务的相关api:通知脚本更方便修改publickey和sysid。要是写死在代码中,不方便配置和修改。

记得配置预警模板,否则发送内容将显示错误。

相关文件说明

前端调取后端接口文件:nightingale-6.2.0/center/router/router.go

添加同步数据库对外暴露http接口

1
2
//添加同步数据库http接口
pages.POST("/users/sync", rt.syncMySQL)

相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package router

import (
"github.com/ccfos/nightingale/v6/models"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"net/http"
"strings"
)

// 入参为一个list对象
type userAddForms []userAddForm

func (rt *Router) syncMySQL(c *gin.Context) {
var forms userAddForms
if err := c.BindJSON(&forms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to bind data."})
return
}
//获得当前登录人信息
var errorsList []string

for _, form := range forms {
password, err := models.CryptoPass(rt.Ctx, form.Password)
if err != nil {
errorsList = append(errorsList, "Failed to encrypt password for user "+form.Username+": "+err.Error())
continue
}

if len(form.Roles) == 0 {
errorsList = append(errorsList, "Roles empty for user "+form.Username)
continue
}

user := &models.User{
Username: form.Username,
Password: password,
Nickname: form.Nickname,
Phone: form.Phone,
Email: form.Email,
Portrait: form.Portrait,
Roles: strings.Join(form.Roles, " "),
Contacts: form.Contacts,
CreateBy: "sync",
UpdateBy: "sync",
}

// Check if user exists
existingUser, err := models.UserGetByUsername(rt.Ctx, form.Username)
if err != nil {
errorsList = append(errorsList, "Failed to fetch user "+form.Username+": "+err.Error())
continue
}

if existingUser != nil {
// Update user
user.Id = existingUser.Id
if err := user.UpdateAllFields(rt.Ctx); err != nil {
errorsList = append(errorsList, "Failed to update user "+form.Username+": "+err.Error())
}
} else {
// Add new user
if err := user.Add(rt.Ctx); err != nil {
errorsList = append(errorsList, "Failed to add user "+form.Username+": "+err.Error())
}
}
}

if len(errorsList) > 0 {
c.JSON(http.StatusInternalServerError, gin.H{"errors": errorsList})
return
}

c.JSON(http.StatusOK, gin.H{"message": "All users processed successfully."})
}

前端静态文件本地存储

原方式

后端二进制部署的时候会跑bash脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash

cp -f ./docker/initsql/a-n9e.sql n9e.sql

if [ ! -d "./pub" ]; then
TAG=$(curl -sX GET https://api.github.com/repos/n9e/fe/releases/latest | awk '/tag_name/{print $4;exit}' FS='[""]')

if ! curl -o n9e-fe-${TAG}.tar.gz -L https://github.com/n9e/fe/releases/download/${TAG}/n9e-fe-${TAG}.tar.gz; then
echo "failed to download n9e-fe-${TAG}.tar.gz!"
exit 1
fi

if ! tar zxf n9e-fe-${TAG}.tar.gz; then
echo "failed to untar n9e-fe-${TAG}.tar.gz!"
exit 2
fi
fi

GOPATH=$(go env GOPATH)
GOPATH=${GOPATH:-/home/runner/go}

# Embed files into a go binary
if ! $GOPATH/bin/statik -src=./pub -dest=./front; then
echo "failed to embed files into a go binary!"
exit 4
fi
  1. 复制 SQL 文件
    • 使用 cp 命令,它将 ./docker/initsql/a-n9e.sql 文件复制到当前目录并重命名为 n9e.sql
  2. 检查目录存在性
    • 检查当前目录中是否存在名为 ./pub 的目录。如果不存在,它会执行以下步骤。
  3. 获取最新的发布标签
    • 通过 curl 命令从 GitHub API 获取 n9e/fe 仓库的最新发布信息,并通过 awk 命令解析出标签名(TAG)。
  4. 下载发布的文件
    • 使用 curl 命令下载与最新发布标签对应的 n9e-fe-${TAG}.tar.gz 文件。如果下载失败,它会打印错误消息并退出脚本。
  5. 解压缩文件
    • 使用 tar 命令解压缩刚刚下载的 .tar.gz 文件。如果解压缩失败,它会打印错误消息并退出脚本。
  6. 设置 GOPATH
    • 通过 go env GOPATH 命令获取 Go 语言的工作目录路径,如果未设置 GOPATH 环境变量,则使用默认路径 /home/runner/go
  7. 嵌入文件到 Go 二进制
    • 使用 statik 工具将 ./pub 目录中的文件嵌入到 ./front 目录的 Go 二进制中。如果失败,它会打印错误消息并退出脚本。

现在处理:

直接下载fe代码放在pub文件夹下

用statik嵌入本地代码front文件夹中

Nightingale使用规范

项目二进制部署

进入cmd\enter\main.go文件夹

1
go build -ldflags "-w -s" -o n9e main.go

1、二进制部署的时候,记得服务器安装python3.x。

2、脚本相关依赖库安装:

1
pip install cryptography
1
pip install pyDes
1
pip install requests

相关日志查看命令:

journalctl -u n9e –since “10 minutes ago” > n9e.log

3、在前端界面中进入:系统配置——通知配置——通知媒介。点击添加按钮:标识固定填写sms、jxccEmail。

image-20231026080808995

4、进入系统配置——通知模板。自定义通知模板内容。通知模板标识为sms、jxccEmail。

image-20231026080922497

5、人员组织配置中只可查看,不可新增

用户数据同步

相关http接口:

1
http://127.0.0.1:17000/api/n9e/users/sync

数据类型:

1
2
3
4
5
6
7
8
9
10
11
[
{
"username": "raohonbin",
"nickname": "raohonbin",
"password": "123456",
"roles": [
"Standard"],
"email": "kwdIDYOrLJ4xOW5rY0NzaQ==",
"phone": "H5m/U+nwqnP511nBTGvqjg=="
}
]

Nightingale返回格式

{
‘event’ :
{
‘id’ : 179,
‘cluster’ : ‘Default’,
‘group_id’ : 1,
‘hash’ : ‘7b22c43787c64e7c410f33be0eac1ddc’,
‘rule_id’ : 1,
‘rule_name’ : ‘cpu使用率告警’,
‘rule_note’ : ‘当CPU使用率超出50%后告警’,
‘severity’ : 2,
‘prom_for_duration’ : 60,
‘prom_ql’ : ‘cpu_usage_active{cpu=”cpu-total”}>=50’,
‘prom_eval_interval’ : 15,
‘callbacks’ : [],
‘runbook_url’ : ‘’,
‘notify_recovered’ : 1,
‘notify_channels’ : [ ‘email’, ‘wecom’, ‘sms’ ],
‘notify_groups’ : [ ‘1’ ],
‘notify_groups_obj’ :
[{ ‘id’ : 1,
‘name’ : ‘demo-root-group’,
‘note’ : ‘’,
‘create_at’ : 1638845941,
‘create_by’ : ‘root’,
‘update_at’ : 1638845941,
‘update_by’ : ‘root’ }
],
‘notify_repeat_next’ : 1639136081,
‘target_ident’ : ‘sinoc’,
‘target_note’ : ‘bgs_clickhouse’,
‘trigger_time’ : 1639132481,
‘trigger_value’ : ‘77.95272’,
‘tags’ : [ ‘name=cpu_usage_active’, ‘cpu=cpu-total’, ‘ident=sinoc’ ],
‘is_recovered’ : FALSE,
‘notify_users_obj’ :
[
{ ‘id’ : 1,
‘username’ : ‘root’,
‘nickname’ : ‘超管’,
‘phone’ : ‘13811345679’,
‘email’ : ‘cjd@i314.net.cn‘,
‘portrait’ : ‘’,
‘roles’ : [ ‘Admin’ ],
‘contacts’ : { ‘wecom_user_id’ : ‘ChaiJinDong’ },
‘create_at’ : 1638845941,
‘create_by’ : ‘system’,
‘update_at’ : 1639043948,
‘update_by’ : ‘root’,
‘admin’ : FALSE }
],
‘last_eval_time’ : 1639132481
},
‘tpls’ : {
‘dingtalk.tpl’ : ‘级别状态: S2 Triggered\n规则名称: cpu使用率告警\n规则备注: 当CPU使用率超出50%后告警\n监控指标: [name=cpu_usage_active cpu=cpu-total ident=sinoc]\n触发时间: 2021-12-10 18:34:41\n触发时值: 77.95272’,
‘feishu.tpl’ : ‘游戏项目: bgs_clickhouse\n告警级别: S2\n当前状态: 进程异常\n告警信息: cpu使用率告警\n规则备注: 当CPU使用率超出50%后告警\n监控指标: [name=cpu_usage_active cpu=cpu-total ident=sinoc]\n触发时间: 2021-12-10 18:34:41\n触发时值: 77.95272\n’,
‘mailbody.tpl’ : ‘\n\n\n \n \n 夜莺告警通知\n \n\n\n

\n
\n
\n

cpu使用率告警

\n

\n
\n\n
\n\n
\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
级别状态:S2 告警
策略备注:当CPU使用率超出50%后告警
设备备注:bgs_clickhouse
监控指标:[name=cpu_usage_active cpu=cpu-total ident=sinoc]
触发时值:77.95272
触发时间:\n 2021-12-10 18:34:41\n
PromQL:\n cpu_usage_active{cpu=&#34;cpu-total&#34;}>=50\n
\n\n
\n\n
\n \n
\n
\n
\n
\n\n\n’,
‘subject.tpl’: ‘告警: cpu使用率告警 [name=cpu_usage_active cpu=cpu-total ident=sinoc]\n’,
‘wecom.tpl’: ‘级别状态: S2 Triggered\n规则标题: cpu使用率告警\n规则备注: 当CPU使用率超出50%后告警\n监控指标: [name=cpu_usage_active cpu=cpu-total ident=sinoc]\n触发时间: 2021-12-10 18:34:41\n触发时值: 77.95272’
}
}