Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docker-compose-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
- WEBHOOK_SERVER_IP_BIND=0.0.0.0 # IP to listen
- WEBHOOK_SERVER_PORT=5000 # Port to listen
- WEBHOOK_SECRET=<secret> # If set verify hook is a valid hook from Github
- VERIFY_GITHUB_IPS=1 # Verifyhook request is from GitHub IPs
- VERIFY_GITHUB_IPS=1 # Verify hook request is from GitHub IPs
- VERIFY_CLOUDFLARE_IPS=1 # Verify hook request is from Cloudflare IPs
ports:
- "5000:5000"
Expand Down
12 changes: 9 additions & 3 deletions gunicorn.conf.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import os
from webhook_server.libs.config import Config

bind = f"{os.environ.get('WEBHOOK_SERVER_IP_BIND', '0.0.0.0')}:{os.environ.get('WEBHOOK_SERVER_PORT', 5000)}"
_config = Config()
_root_config = _config.root_data
_ip_bind = _root_config.get("ip-bind", "0.0.0.0")
_port = _root_config.get("port", 5000)
_max_workers = _root_config.get("max-workers", 10)

bind = f"{_ip_bind}:{_port}"
worker_class = "uvicorn.workers.UvicornWorker"
workers = int(os.environ.get("MAX_WORKERS", 10))
workers = int(_max_workers)
on_starting = "webhook_server.app.on_starting"
accesslog = "-"
timeout = 60 * 30 # some operation can take long time.
27 changes: 17 additions & 10 deletions webhook_server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@
)
from starlette.datastructures import Headers

from webhook_server.libs.config import Config
from webhook_server.libs.exceptions import NoPullRequestError, RepositoryNotFoundError
from webhook_server.libs.github_api import ProcessGithubWehook
from webhook_server.utils.github_repository_and_webhook_settings import repository_and_webhook_settings
from webhook_server.utils.helpers import get_logger_with_params

VERIFY_GITHUB_IPS = os.getenv("GITHUB_IPS_ONLY", "").lower() in ["true", "1"]
VERIFY_CLOUDFLARE_IPS = os.getenv("CLOUDFLARE_IPS_ONLY", "").lower() in ["true", "1"]
ALLOWED_IPS: tuple[ipaddress._BaseNetwork, ...] = ()

WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET", "")
FASTAPI_APP: FastAPI = FastAPI(title="webhook-server")
APP_URL_ROOT_PATH: str = "/webhook_server"
urllib3.disable_warnings()
Expand Down Expand Up @@ -88,18 +85,24 @@ def on_starting(server: Any) -> None:
logger = get_logger_with_params(name="startup")
logger.info("Application starting up...")
try:
repository_and_webhook_settings(webhook_secret=WEBHOOK_SECRET)
config = Config()
root_config = config.root_data
webhook_secret = root_config.get("webhook-secret")
verify_github_ips = root_config.get("verify-github-ips")
verify_cloudflare_ips = root_config.get("verify-cloudflare-ips")

repository_and_webhook_settings(webhook_secret=webhook_secret)
logger.info("Repository and webhook settings initialized successfully.")

global ALLOWED_IPS

if VERIFY_GITHUB_IPS and VERIFY_CLOUDFLARE_IPS:
if verify_github_ips or verify_cloudflare_ips:
networks: list[ipaddress._BaseNetwork] = []

if VERIFY_CLOUDFLARE_IPS:
if verify_cloudflare_ips:
networks += [ipaddress.ip_network(cidr) for cidr in get_cloudflare_allowlist()]

if VERIFY_GITHUB_IPS:
if verify_github_ips:
networks += [ipaddress.ip_network(cidr) for cidr in get_github_allowlist()]

ALLOWED_IPS = tuple(networks) # immutable & de-duplicated
Expand All @@ -123,9 +126,13 @@ async def process_webhook(request: Request) -> dict[str, Any]:

payload_body = await request.body()

if WEBHOOK_SECRET:
config = Config()
root_config = config.root_data
webhook_secret = root_config.get("webhook-secret")

if webhook_secret:
signature_header = request.headers.get("x-hub-signature-256")
verify_signature(payload_body=payload_body, secret_token=WEBHOOK_SECRET, signature_header=signature_header)
verify_signature(payload_body=payload_body, secret_token=webhook_secret, signature_header=signature_header)

delivery_id = request.headers.get("X-GitHub-Delivery", "unknown-delivery")
event_type = request.headers.get("X-GitHub-Event", "unknown-event")
Expand Down
19 changes: 19 additions & 0 deletions webhook_server/config/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ properties:
webhook_ip:
type: string
description: IP or FQDN address of the webhook server for adding to the repositories

ip-bind:
type: string
description: IP address to bind the server to
port:
type: integer
description: Port to bind the server to
max-workers:
type: integer
description: Maximum number of workers to run
webhook-secret:
type: string
description: Secret for validating webhook
verify-github-ips:
type: boolean
description: Verify hook request is from GitHub IPs
verify-cloudflare-ips:
type: boolean
description: Verify hook request is from Cloudflare IPs
docker:
type: object
properties:
Expand Down