Add authentication key support to API

This commit is contained in:
Joshua Boniface 2021-10-31 00:38:37 -04:00
parent 0e4bb177ef
commit 2a941e6ece
1 changed files with 34 additions and 3 deletions

View File

@ -1,9 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import click import click
import hmac
import bbuilder.lib.worker import bbuilder.lib.worker
from flask import Flask, request from hashlib import sha1, sha256
from flask import Flask, request, abort
from celery import Celery from celery import Celery
DEFAULT_REDIS_QUEUE = 'redis://127.0.0.1:6379/0' DEFAULT_REDIS_QUEUE = 'redis://127.0.0.1:6379/0'
@ -56,7 +58,12 @@ def cli_worker(concurrency):
default='7999', show_default=True, default='7999', show_default=True,
help='Listen on this port. Envvar: BB_LISTEN_PORT' help='Listen on this port. Envvar: BB_LISTEN_PORT'
) )
def cli_run(listen_addr, listen_port): @click.option(
'-k', '--auth-key', 'auth_key', envvar='BB_AUTH_KEY',
default=None,
help='An authentication key to secure webhook access. Envvar: BB_AUTH_KEY'
)
def cli_run(listen_addr, listen_port, auth_key):
""" """
Run the Basic Builder server Run the Basic Builder server
""" """
@ -71,7 +78,31 @@ def cli_run(listen_addr, listen_port):
request_json = request.get_json() request_json = request.get_json()
request_headers = dict(request.headers) request_headers = dict(request.headers)
if request_json is None or request_headers is None: if request_json is None or request_headers is None:
return False abort(400)
# Authenticate
if auth_key is not None:
# We use only X-Hub-Signature for compatibility; Gitea supports this
header_signature = request_headers.get('X-Hub-Signature-256', None)
# If we don't find the sha256 signature, use the sha1 one instead
if header_signature is None:
header_signature = request_headers.get('X-Hub-Signature', None)
# If we found neither, abort
if header_signature is None:
abort(403)
sha_name, signature = header_signature.split('=')
if sha_name == 'sha256':
mac = hmac.new(auth_key.encode('ascii'), msg=request.data, digestmod=sha256)
elif sha_name == 'sha1':
mac = hmac.new(auth_key.encode('ascii'), msg=request.data, digestmod=sha1)
else:
abort(501)
if not str(mac.hexdigest()) == str(signature):
abort(403)
flask_request = (request_headers, request_json) flask_request = (request_headers, request_json)
@celery.task(bind=True) @celery.task(bind=True)