Last active 1698355949

Github webhook proxy server (only Issues implemented)

onyx_online's Avatar onyx_online revised this gist 1698355949. Go to revision

1 file changed, 1 insertion, 1 deletion

__main__.py

@@ -42,7 +42,7 @@ def github_payload():
42 42 signature = request.headers.get("X-Hub-Signature")
43 43 data = request.data
44 44 if not verify_hmac_hash(data, signature):
45 - app.logger.debug("failed to verify signature!")
45 + app.logger.debug("failed to verify signature... aborting request")
46 46 abort(403)
47 47
48 48 payload = request.get_json()

onyx_online's Avatar onyx_online revised this gist 1698162587. Go to revision

1 file changed, 1 insertion, 1 deletion

__main__.py

@@ -70,7 +70,7 @@ def issues_handler(payload):
70 70 "username": "Github-OpenGist",
71 71 "embeds": [embed],
72 72 }
73 - send_discord_webhook(app.config["DISCORD_WEBHOOK"], data=data)
73 + send_discord_webhook(app.config["DISCORD_WEBHOOK"], data)
74 74
75 75
76 76 def send_discord_webhook(webhook_url, data):

onyx_online's Avatar onyx_online revised this gist 1698162130. Go to revision

1 file changed, 1 insertion, 1 deletion

__main__.py

@@ -52,7 +52,7 @@ def github_payload():
52 52 case "issues":
53 53 issues_handler(payload)
54 54 case _:
55 - app.logger.debug(f"no action defined for event {event_type}... continuing")
55 + app.logger.debug(f"no handler defined for event {event_type}... continuing")
56 56 return ("", 200, None)
57 57
58 58

onyx_online's Avatar onyx_online revised this gist 1698160889. Go to revision

1 file changed, 1 insertion, 1 deletion

__main__.py

@@ -34,7 +34,7 @@ def verify_hmac_hash(data, signature):
34 34
35 35 @app.route("/github-payload", methods=["POST"])
36 36 def github_payload():
37 - src_ip = ip_address(request.headers.get("X-Real-IP", , request.access_route[0]))
37 + src_ip = ip_address(request.headers.get("X-Real-IP", request.access_route[0]))
38 38 if not verify_src_ip(src_ip):
39 39 app.logger.debug(f"invalid source ip: {src_ip}... aborting request")
40 40 abort(403)

onyx_online's Avatar onyx_online revised this gist 1698160879. Go to revision

1 file changed, 1 insertion, 1 deletion

__main__.py

@@ -34,7 +34,7 @@ def verify_hmac_hash(data, signature):
34 34
35 35 @app.route("/github-payload", methods=["POST"])
36 36 def github_payload():
37 - src_ip = ip_address(request.headers.get("X-Real-IP"))
37 + src_ip = ip_address(request.headers.get("X-Real-IP", , request.access_route[0]))
38 38 if not verify_src_ip(src_ip):
39 39 app.logger.debug(f"invalid source ip: {src_ip}... aborting request")
40 40 abort(403)

onyx_online's Avatar onyx_online revised this gist 1698159059. Go to revision

1 file changed, 81 insertions

__main__.py(file created)

@@ -0,0 +1,81 @@
1 + import hashlib
2 + import hmac
3 + import json
4 + import os
5 + from ipaddress import ip_address, ip_network
6 +
7 + import requests
8 + from dotenv import load_dotenv
9 + from flask import Flask, abort, request
10 +
11 +
12 + def create_app():
13 + app = Flask(__name__)
14 + load_dotenv()
15 + app.config["GITHUB_SECRET"] = os.getenv("GITHUB_SECRET")
16 + app.config["DISCORD_WEBHOOK"] = os.getenv("DISCORD_WEBHOOK")
17 +
18 + return app
19 +
20 +
21 + app = create_app()
22 +
23 +
24 + def verify_src_ip(src_ip):
25 + allowed_ips = requests.get("https://api.github.com/meta").json()["hooks"]
26 + return any(src_ip in ip_network(valid_ip) for valid_ip in allowed_ips)
27 +
28 +
29 + def verify_hmac_hash(data, signature):
30 + github_secret = bytes(app.config["GITHUB_SECRET"], "ascii")
31 + mac = hmac.new(github_secret, msg=data, digestmod=hashlib.sha1)
32 + return hmac.compare_digest("sha1=" + mac.hexdigest(), signature)
33 +
34 +
35 + @app.route("/github-payload", methods=["POST"])
36 + def github_payload():
37 + src_ip = ip_address(request.headers.get("X-Real-IP"))
38 + if not verify_src_ip(src_ip):
39 + app.logger.debug(f"invalid source ip: {src_ip}... aborting request")
40 + abort(403)
41 +
42 + signature = request.headers.get("X-Hub-Signature")
43 + data = request.data
44 + if not verify_hmac_hash(data, signature):
45 + app.logger.debug("failed to verify signature!")
46 + abort(403)
47 +
48 + payload = request.get_json()
49 + match event_type := request.headers.get("X-GitHub-Event"):
50 + case "ping":
51 + return json.dumps({"msg": "pong"})
52 + case "issues":
53 + issues_handler(payload)
54 + case _:
55 + app.logger.debug(f"no action defined for event {event_type}... continuing")
56 + return ("", 200, None)
57 +
58 +
59 + def issues_handler(payload):
60 + embed = {
61 + "author": {
62 + "name": payload["sender"]["login"],
63 + "icon_url": payload["sender"]["avatar_url"],
64 + },
65 + "title": f"[{payload['repository']['full_name']}] Issue {payload['action'].capitalize()}: #{payload['issue']['number']} {payload['issue']['title']}",
66 + "url": payload["issue"]["html_url"],
67 + "description": payload["issue"].get("body"),
68 + }
69 + data = {
70 + "username": "Github-OpenGist",
71 + "embeds": [embed],
72 + }
73 + send_discord_webhook(app.config["DISCORD_WEBHOOK"], data=data)
74 +
75 +
76 + def send_discord_webhook(webhook_url, data):
77 + requests.post(webhook_url, json=data)
78 +
79 +
80 + if __name__ == "__main__":
81 + app.run(debug=True, port=5000)
Newer Older