webhook 也是一种 api,你需要设计api 然后发起对应的http请求来实现对应的功能需求,本文是基于https://github.com/adnanh/webhook (以下简称wehook
)一个用 Go 编写的轻量级应用、你可以轻松的使用它来 运行shell命令 、实现版本发布等一切需求。
大概执行过程
- 接收请求;
- 解析headers, payload and query variables;
- 检查是否满足指定规则,
- 最后将参数或环境变量传递给配置的shell.
Webhook安全性
webhook
在安全也可以配置很多策略,经过测试可以配置但不仅如下限于策略
# https://github.com/adnanh/webhook/blob/master/docs/Hook-Rules.md#match-value
1. 请求方式限制
2. ip限制
3. 请求Header (Token、CORS Headers)
4. https认证
6. 检查指定的请求参数
环境和服务安装
使用的是 webhook 2.8.0 、go1.16.5 和CentOS Linux release 7.4.1708
。
GO安装
1. rm -rf /usr/local/go && tar -C /usr/local -xzf go1.16.5.linux-amd64.tar.gz
2. export PATH=$PATH:/usr/local/go/bin
3. go version
4. vim /etc/export #可以添加至`/etc/export`
5. export PATH=$PATH:/usr/local/go/bin
6. source /etc/export
编译webhook 2.8.0
部署到服务器时,只需要编译出来的webhook
可执行文件即可。
1. unzip webhook-master.zip
2. cd webhook-master
3. go build .
4. ldd webhook #检查
服务器部署
部署的结构如下,都可以自定义,启动命令指定与配置保持一致即可。目录结构如下:
└── webhook
├── hooks.yaml
├── logs
│ └── webhook.log
├── scripts #api具体调用脚本目录
│ └── redeploy-go-webhook.sh
├── webhook_install.sh #实现webhook start 和reload
├── webhook.service #添加至开机启动
├── webhook #可执行
└── webhook.pid
----
cd webhook
1. 执行文件 chmod +x webhook
2. 配置文件 hooks.yaml
3. 使用脚本目录 chmod +x scripts/*
4. 日志目录 mkdir logs
配置文件hooks.yaml
配置文件可以是 JSON
or YAML
格式,可以参照详细的 参数定义,还提供了一些常用的例子和测试用例,如对接gitlab
、github
等 。
下面是一个简单的测试配置
- id: webhook-install #任务id
execute-command: "/etc/webhook/scripts/webhook_install.sh" #shell命令或shell脚本
command-working-directory: / #执行目录
response-message: success #成功返回值
include-command-output-in-response: true #返回werbook返回值
trigger-rule-mismatch-http-response-code: 400 #不满足trigger-rule 规则返回码
http-methods: #允许的 HTTP 方法列表
- "GET "
- "Post "
pass-arguments-to-command: #请求参数
- source: url
name: action
trigger-rule:
and:
- match:
parameter:
source: header
name: webhook-token
type: value
value: XXXXXXXXXXXXX #验证token
- match:
type: ip-whitelist #访问限制
ip-range: 10.0.0.0/8 #只允许10.0.0.0/8访问
接收参数的四种方式
-
pass-arguments-to-command
常用的一种方式,可以是header
、url parameters
、Request parameters
、Payload (JSON or form-value encoded)
、XML Payload
、还有服务端自定义string 简单的字符串-e 123123”
-
pass-file-to-command
文件内容传递给execute-command
-
pass-environment-to-command
环境变量传递给execute-command
-
parse-parameters-as-json
payload=<JSON_STRING>
解析字符串传递给execute-command
请求规则限制
Hook-Rules支持and
、or
、not
组合逻辑匹配、支持正则方式,hash,可以对请求的验证(如token/parameters),还支持ip-whitelist
服务启动
具体启动参数可以参照 官方配置。
#可以使用绝对路径启动,ip、debug、ssl都是可选的
./webhook \
-hooks hooks.yaml \ #指定配置文件
-port 5432\ #指定端口
-ip "127.0.0.1" \
-debug \
-key ssl/server.key.pem \ #指定私钥
-cert ssl/server.crt.pem \ #指定公钥
-urlprefix redeploy \ #指定rul前缀
-secure \ #使用HTTPS
-logfile logs/webhook.log \ #指定日志文件
-pidfile webhook.pid #指定pid文件
#简单的启动方式
./webhook -hooks hooks.yaml -verbose
服务reload
[ -e /var/run/webhook.pid ] && kill -USR1 `cat /var/run/webhook.pid`
也可以使用:
kill -USR1 webhookpid
kill -HUP webhookpid
怎么调用
服务启动开启了5432
端口,使用http访问。
curl -v -X POST -k -E ./ssl/server.crt.pem --key ./ssl/server.key.pem \
'https://127.0.0.1:5432/redeploy/webhook-install?action=install' \
-H 'webhook-token: XXXXXXXXXXXXX' \
# https://127.0.0.1:5432/redeploy/ 为固定路径
# webhook-install id名称
# action=install 传递给后端脚本参数
常见错误
- Error occurred while executing the hook's command. Please check your logs for more details.
脚本执行错误返回400错误。
- Hook rules were not satisfied 。
规则不匹配,一般是webhook-token不对,或者是ip不在白名单里面
- Hook not found。
ID 不存在返回 404,
例:实现Gitlab Webhook 自动发布
1. Gitlab-webhooks配置
官方文档webhooks.md,并授权服务器可以clone权限
web位置:项目 > Settings > Webhook Settings
> URL:https://webhook地址/gitlab/redeploy
> Secret token:3a9bdeaa2bcd9 #token 验证
> Trigger:勾选Push events #触发事件
> Push events:master #只在master分支
2. 配置文件hooks.yaml
- id: redeploy
execute-command: "/webhook-path/scripts/redeploy-go-webhook.sh"
command-working-directory: /webhook-path/
response-message: Executing redeploy script
include-command-output-in-response: true
trigger-rule-mismatch-http-response-code: 400
http-methods:
- "Post "
pass-arguments-to-command:
- source: string
name: -N
- source: payload
name: project.namespace
- source: string
name: -P
- source: payload
name: project.path_with_namespace
- source: string
name: -G
- source: payload
name: project.git_ssh_url
trigger-rule:
and:
- match:
type: value
value: 3a9bdeaa2bcd9
parameter:
source: header
name: X-Gitlab-Token
3. redeploy-go-webhook.sh
#!/bin/bash
set -e -u
set -o pipefail
declare -r LOCAL_GIT_DIR='/export/gitlab_data' #Git文件存放地址
function git_clone() {
mkdir -p ${git_file_dir}
cd ${git_file_dir}
/usr/bin/env git clone -q ${SPACE_URL} . || rm -rf ${git_file_dir}
}
function git_pull() {
cd ${git_file_dir}
/usr/bin/env git checkout -q master
/usr/bin/env git fetch -p -q --all
/usr/bin/env git reset -q --hard origin/master
}
function main() {
while getopts ":N:P:G:" opt; do
case "${opt}" in
N) SPACE_NAME=${OPTARG}; ;;
P) SPACE_PATH=${OPTARG}; ;;
G) SPACE_URL=${OPTARG}; ;;
h|*) echo "use -N, -P, -G, option, not null"; ;;
esac
done
shift "$((OPTIND-1))"
git_use_dir=${LOCAL_GIT_DIR}/${SPACE_NAME}
git_file_dir=${LOCAL_GIT_DIR}/${SPACE_PATH}
mkdir -p ${git_use_dir}
if [ ! -d "${git_file_dir}" ]; then
git_clone
git_pull
else
git_pull
fi
}
main "${@:-""}"
echo "${*:-""} success"
4. 启动
nohup ./webhook \
-hooks hooks.yaml \
-port 80 \
-ip "0.0.0.0" \
-urlprefix gitlab \
-logfile logs/webhook.log \
-pidfile webhook.pid >/dev/null 2>&1 &
5. gitlab master 提交测试
When GitLab sends a webhook, it expects a response in 10 seconds by default.
If the endpoint doesn’t send an HTTP response in those 10 seconds,
GitLab may assume the webhook failed and retry it.