使用nginx的lua验证GitHub Webhooks和删除cron-lock-file
2016-5-5 22:31:15
收藏:0
阅读:62
评论:2
我有什么:
- GNU/Linux主机
- nginx已运行
- 定时任务计划在特定文件被删除后立即运行(类似于run-crons)
- 当有人向存储库推送时,GitHub会发送Webhook
我想要什么:
我现在想要运行Lua或任何类似于解析GitHub请求并验证它,然后删除文件(如果请求是有效的)的内容。
最好所有这些都可以在不需要维护额外的PHP安装(当前没有)或使用fcgiwrap或类似工具的情况下完成。
模板:
在nginx方面,我有等效于
location /deploy {
# 在这里执行lua(或等效物)
}
点赞
用户4716629
要读取 GH Webhook 的 JSON 体,您需要使用 JSON4Lua 库,并使用 luacrypto 验证 HMAC 签名。
预配置
安装所需模块
$ sudo luarocks install JSON4Lua
$ sudo luarocks install luacrypto
在 Nginx 中定义部署位置
location /deploy {
client_body_buffer_size 3M;
client_max_body_size 3M;
content_by_lua_file /path/to/handler.lua;
}
max_body_size 和 body_buffer_size 应该相等以防止错误
request body in temp file not supported
https://github.com/openresty/lua-nginx-module/issues/521
处理 Webhook
获取请求有效数据,并检查正确性
ngx.req.read_body()
local data = ngx.req.get_body_data()
if not data then
ngx.log(ngx.ERR, "failed to get request body")
return ngx.exit (ngx.HTTP_BAD_REQUEST)
end
使用 luacrypto 验证 GH 签名
local function verify_signature (hub_sign, data)
local sign = 'sha1=' .. crypto.hmac.digest('sha1', data, secret)
-- this is simple comparison, but it's better to use a constant time comparison
return hub_sign == sign
end
-- validate GH signature
if not verify_signature(headers['X-Hub-Signature'], data) then
ngx.log(ngx.ERR, "wrong webhook signature")
return ngx.exit (ngx.HTTP_FORBIDDEN)
end
解析数据为 JSON 并检查是否为主分支,以进行部署
data = json.decode(data)
-- on master branch
if data['ref'] ~= branch then
ngx.say("Skip branch ", data['ref'])
return ngx.exit (ngx.HTTP_OK)
end
如果一切正确,则调用部署功能
local function deploy ()
-- run command for deploy
local handle = io.popen("cd /path/to/repo && sudo -u username git pull")
local result = handle:read("*a")
handle:close()
ngx.say (result)
return ngx.exit (ngx.HTTP_OK)
end
示例
示例常量时间字符串比较
local function const_eq (a, b)
-- Check is string equals, constant time exec
getmetatable('').__index = function (str, i)
return string.sub(str, i, i)
end
local diff = string.len(a) == string.len(b)
for i = 1, math.min(string.len(a), string.len(b)) do
diff = (a[i] == b[i]) and diff
end
return diff
end
我在 GitHub Gist 中使用它的完整示例 https://gist.github.com/Samael500/5dbdf6d55838f841a08eb7847ad1c926。
2017-03-31 17:43:21
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
这个解决方案没有针对GitHub的hooks实现验证,假设您已安装了lua扩展和cjson模块:
location = /location { default_type 'text/plain'; content_by_lua_block { local cjson = require "cjson.safe" ngx.req.read_body() local data = ngx.req.get_body_data() if data then local obj = cjson.decode(data) if # 哈希校验应该在这里进行 (obj and obj.repository and obj.repository.full_name) == "user/reponame" then local file = io.open("<your file>","w") if file then file:close() ngx.say("success") else ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end else ngx.exit(ngx.HTTP_UNAUTHORIZED) end else ngx.exit(ngx.HTTP_NOT_ALLOWED) end } }