Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix travis signature authorized #158

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion cfg.sample.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ app_client_secret = ""
#"""

[web]

# The ip homu used
host = "0.0.0.0"
# The port homu listens on
port = 54856

Expand Down Expand Up @@ -74,6 +75,14 @@ secret = ""
## found under <https://travis-ci.org/profile/info>.
#token = ""

# found travis api document
# https://docs.travis-ci.com/user/notifications/
# Make sure you use the correct config URL, the .org and .com
# have different keys!
# https://api.travis-ci.org/config
# https://api.travis-ci.com/config
#public_key_url="https://api.travis-ci.org/config"

## Use the Status API
#[repo.NAME.status]
#
Expand Down
36 changes: 24 additions & 12 deletions homu/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,18 +565,30 @@ def travis():

repo_cfg = g.repo_cfgs[repo_label]
token = repo_cfg['travis']['token']
auth_header = request.headers['Authorization']
code = hashlib.sha256(('{}/{}{}'.format(state.owner, state.name, token)).encode('utf-8')).hexdigest()
if auth_header != code:
# this isn't necessarily an error, e.g. maybe someone is
# fabricating travis notifications to try to trick Homu, but,
# I imagine that this will most often occur because a repo is
# misconfigured.
logger.warn('authorization failed for {}, maybe the repo has the wrong travis token? ' \
'header = {}, computed = {}'
.format(state, auth_header, code))
abort(400, 'Authorization failed')

lazy_debug(logger, lambda:'request header details {}'.format(request.headers))
if 'Authorization' in request.headers.keys():
auth_header = request.headers['Authorization']
code = hashlib.sha256(('{}/{}{}'.format(state.owner, state.name, token)).encode('utf-8')).hexdigest()
if auth_header != code:
# this isn't necessarily an error, e.g. maybe someone is
# fabricating travis notifications to try to trick Homu, but,
# I imagine that this will most often occur because a repo is
# misconfigured.
logger.warn('authorization failed for {}, maybe the repo has the wrong travis token? ' \
'header = {}, computed = {}'
.format(state, auth_header, code))
abort(400, 'Authorization failed')
elif 'Signature' in request.headers.keys():
public_key = utils.get_travis_pubilc_key(repo_cfg['travis']['public_key_url'])
if public_key:
try:
utils.check_authorized(request.headers['Signature'], public_key, request.forms.payload)
except Exception as e:
logger.warn('check travis data signature error: {}'.format(e))
abort(400, 'Signature failed')
else:
abort(400, 'Get public_key failed')

succ = info['result'] == 0

report_build_res(succ, info['build_url'], 'travis', state, logger, repo_cfg)
Expand Down
28 changes: 26 additions & 2 deletions homu/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import traceback
import requests
import time
import base64
from OpenSSL.crypto import verify, load_publickey, FILETYPE_PEM, X509
from OpenSSL.crypto import Error as SignatureError

def github_set_ref(repo, ref, sha, *, force=False, auto_create=True):
url = repo._build_url('git', 'refs', ref, base_url=repo._api)
Expand Down Expand Up @@ -54,11 +57,14 @@ def lazy_debug(logger, f):
logger.debug(f())

def logged_call(args):
try: subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as e:
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
if p.returncode != 0:
print('* Failed to execute command: {}'.format(args))
print('shell ruturn data: {}'.format(p.communicate()))
raise


def silent_call(args):
return subprocess.call(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

Expand All @@ -85,3 +91,21 @@ def retry_until(inner, fail, state):
traceback.print_exception(*exc_info)

fail(err)


def get_travis_pubilc_key(travis_pubilc_key_url):
try:
key_detail = requests.get(travis_pubilc_key_url).json()
except Exception as e:
print('* Get travis public_key url error: {}'.format(e))
return False

return key_detail['config']['notifications']['webhook']['public_key']

def check_authorized(signature, public_key, payload):
signature = base64.b64decode(signature)
pkey_public_key = load_publickey(FILETYPE_PEM, public_key)
certificate = X509()
certificate.set_pubkey(pkey_public_key)
verify(certificate, signature, payload, str('sha1'))