verify the HMAC that GitHub sends
This commit is contained in:
parent
5e4cc8e8ae
commit
1a695451f3
3 changed files with 23 additions and 23 deletions
|
@ -22,7 +22,8 @@
|
|||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#==============================================================================
|
||||
import sys, os, os.path, subprocess
|
||||
import configparser, itertools, json, re
|
||||
import configparser, itertools, re
|
||||
import hmac, hashlib
|
||||
import email.mime.text, email.utils, smtplib
|
||||
|
||||
mail_sender = "null@localhost"
|
||||
|
@ -76,21 +77,13 @@ def send_mail(subject, text, recipients, sender, replyTo = None):
|
|||
s.sendmail(sender, recipients, msg.as_string())
|
||||
s.quit()
|
||||
|
||||
def get_github_payload():
|
||||
'''Reeturn the github-style JSON encoded payload (as if we were called as a github webhook)'''
|
||||
try:
|
||||
data = sys.stdin.buffer.read()
|
||||
data = json.loads(data.decode('utf-8'))
|
||||
return data
|
||||
except:
|
||||
return {} # nothing read
|
||||
|
||||
class Repo:
|
||||
def __init__(self, name, conf):
|
||||
'''Creates a repository from a section of the git-mirror configuration file'''
|
||||
self.name = name
|
||||
self.local = conf['local']
|
||||
self.owner = conf['owner'] # email address to notify in case of problems
|
||||
self.hmac_secret = conf['hmac-secret'].encode('utf-8')
|
||||
self.deploy_key = conf['deploy-key'] # the SSH ky used for authenticating against remote hosts
|
||||
self.mirrors = {} # maps mirrors to their URLs
|
||||
mirror_prefix = 'mirror-'
|
||||
|
@ -101,6 +94,11 @@ class Repo:
|
|||
def mail_owner(self, msg):
|
||||
global mail_sender
|
||||
send_mail("git-mirror {0}".format(self.name), msg, recipients = [self.owner], sender = mail_sender)
|
||||
|
||||
def compute_hmac(self, data):
|
||||
h = hmac.new(self.hmac_secret, digestmod = hashlib.sha1)
|
||||
h.update(data)
|
||||
return h.hexdigest()
|
||||
|
||||
def find_mirror_by_url(self, match_urls):
|
||||
for mirror, url in self.mirrors.items():
|
||||
|
|
|
@ -24,9 +24,22 @@
|
|||
#==============================================================================
|
||||
|
||||
# This is the hook called by GitHub as webhook. It updats the local repository, and then all the other mirrors.
|
||||
import sys, traceback
|
||||
import sys, traceback, json
|
||||
from git_mirror import *
|
||||
|
||||
def get_github_payload(repo, signature):
|
||||
'''Return the github-style JSON encoded payload (as if we were called as a github webhook)'''
|
||||
data = sys.stdin.buffer.read()
|
||||
verify_signature = repo.compute_hmac(data)
|
||||
if signature != "sha1="+verify_signature:
|
||||
raise Exception("You are not GitHub!")
|
||||
try:
|
||||
data = json.loads(data.decode('utf-8'))
|
||||
return data
|
||||
except ValueError:
|
||||
return {} # nothing read
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# call this with: <reponame> <event name> <signature>
|
||||
repo = None # we will try to use this during exception handling
|
||||
|
@ -42,7 +55,7 @@ if __name__ == "__main__":
|
|||
repo = repos[reponame]
|
||||
|
||||
# now sync this repository
|
||||
data = get_github_payload()
|
||||
data = get_github_payload(repo, githubSignature)
|
||||
if githubEvent == 'ping':
|
||||
# github sends this initially
|
||||
print("Content-Type: text/plain")
|
||||
|
|
11
webhook.py
11
webhook.py
|
@ -29,17 +29,6 @@ webhook_core = "/home/git/git-mirror/webhook-core.py"
|
|||
#
|
||||
import urllib.request, urllib.parse, json, os, sys
|
||||
|
||||
def is_github(remote_addr):
|
||||
'''Returns whether the address is a github hook address. This function requires Python 3.3.'''
|
||||
from ipaddress import ip_address, ip_network
|
||||
remote_addr = ip_address(ip_network)
|
||||
github = urllib.request.urlopen('https://api.github.com/meta').read()
|
||||
github = json.loads(github.decode('utf-8'))
|
||||
for net in github['hooks']:
|
||||
if remote_addr in ip_network(net):
|
||||
return True
|
||||
return False
|
||||
|
||||
# get repository from query string
|
||||
query = os.getenv("QUERY_STRING")
|
||||
query = urllib.parse.parse_qs(query)
|
||||
|
|
Loading…
Reference in a new issue