{"id":21455116,"url":"https://github.com/antvirf/webhook-forwarder-python","last_synced_at":"2025-07-14T23:32:30.870Z","repository":{"id":54337297,"uuid":"522159896","full_name":"Antvirf/webhook-forwarder-python","owner":"Antvirf","description":"FastAPI based Github webhook forwarder with sender IP and signature checking","archived":false,"fork":false,"pushed_at":"2024-10-18T01:18:39.000Z","size":134,"stargazers_count":3,"open_issues_count":12,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-20T13:21:03.022Z","etag":null,"topics":["fastapi","forwarder","github","jenkins","webhook"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Antvirf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-07T08:43:01.000Z","updated_at":"2024-09-09T03:15:15.000Z","dependencies_parsed_at":"2023-02-10T20:45:31.941Z","dependency_job_id":"235c465d-74ab-4a96-81e6-2195705ff97d","html_url":"https://github.com/Antvirf/webhook-forwarder-python","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antvirf%2Fwebhook-forwarder-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antvirf%2Fwebhook-forwarder-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antvirf%2Fwebhook-forwarder-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antvirf%2Fwebhook-forwarder-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Antvirf","download_url":"https://codeload.github.com/Antvirf/webhook-forwarder-python/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226003010,"owners_count":17558157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","forwarder","github","jenkins","webhook"],"created_at":"2024-11-23T05:10:28.724Z","updated_at":"2024-11-23T05:10:29.454Z","avatar_url":"https://github.com/Antvirf.png","language":"Python","readme":"# Webhook forwarder API in Python\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Antvirf_webhook-forwarder\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Antvirf_webhook-forwarder)\n![CodeQL](https://github.com/Antvirf/webhook-forwarder/actions/workflows/codeql.yml/badge.svg)\n![Vulnerabilities](https://snyk.io/test/github/Antvirf/webhook-forwarder-python/badge.svg)\n![Pytests](https://github.com/Antvirf/webhook-forwarder/actions/workflows/python-tests.yml/badge.svg)\n![Pytest coverage](./coverage.svg)\n[![CircleCI](https://dl.circleci.com/status-badge/img/gh/Antvirf/webhook-forwarder-python/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/Antvirf/webhook-forwarder-python/tree/main)\n![Python Versions](https://img.shields.io/badge/python-3.8%20|%203.9%20|%203.10%20-blue)\n\nA Python FastAPI-based application intended to forward Github webhooks, primarily to a protected Jenkins instance.\n\nThe application checks the sender's IP, X-IP (if behind proxy) and validates the signature of the webhook before forwarding the webhook to a specified target address.\n\nThe intended usage is to host this on a public Internet-facing server/service, which can then forward the webhook to a different, more protected VM via different routes.\n\n\n```mermaid\nflowchart LR\n\n    subgraph gh[Github]\n        webhook[Send webhook]\n    end\n\n    subgraph midnet[Accessible VM]\n        fwd[Webhook Forwarder]\n    end\n\n    subgraph vpn[VPN]\n        jenkins[Jenkins]\n    end\n\n    webhook --\u003e|Public internet| fwd\n    fwd --\u003e |Private link| jenkins\n```\n\n## High-level usage guide (With ngrok and Docker Compose)\n\n```mermaid\nflowchart LR\n\n    subgraph gh[Github]\n        webhook[Send webhook]\n    end\n    \n    subgraph ngrok[Ngrok]\n        ngroker[Ngrok app]\n    end\n\n    subgraph compose[Docker Compose]\n        subgraph forwarder[Forwarder, port 8000]\n            fwd[Webhook Forwarder]\n        end\n\n        subgraph receiver[Receiver, 9001]\n            rec[Receiver logs output]\n        end\n    end\n\n    webhook --\u003e |Internet| ngroker\n    ngroker --\u003e |Ngrok forwarder| fwd\n    fwd --\u003e |Webhook sent if valid| rec\n\n```\n### Step 1: [Ngrok](https://ngrok.com/) startup\n\n```\n# start ngrok on port 8000\nngrok http 8000\n```\n\n### Step 2: Configure your [Github Webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks)\n1. Point your github webhook URL to your ngrok url, appending \"/forward_webhook\" at the end to use the correct endpoint\n1. Configure your webhook secret to a particular value. Use an actual token, or a placeholder (e.g. \"test\").\n\n### Step 3: Configure your environment variables\nFor a real setup, you should actually configure these as environment variables. For testing, configure them directly in main.py near lines 33-38.\u003cbr\u003e\nAs ```TARGET_URL```, leave this to ```http://receiver:9001/receive_webhook``` to run the example testing.\u003cbr\u003e\nAs ```WEBHOOK_TOKEN_SECRET```, set whatever you configured in your webhook.\n```\nTARGET_URL = http://127.0.0.1:7000\nWEBHOOK_TOKEN_SECRET = \"test\"\n```\n\n### Step 4: Launch webhook forwarder\nBring up two instances of webhook_forwarder, one acting as forwarder, one as receiver.\n\n```\ndocker compose up --build\n```\n\n### Step 5: Trigger the webhook in GitHub\nYou can do this in your Github, either as \"redeliver\" if you already had sent one, or by committing to the repository.\n\n### Step 6: Watch the magic happen\n1. Github webhook is triggered, and is sent to the ngrok.url/forward_webhook endpoint configured earlier.\n1. Ngrok receives this and sends it to the 'forwarder' instance you have running on port 8000.\n1. If correctly configured, this instance should log the IP and signature of the message, and log whether it is forwarded (or an appropriate error message, on failure).\n1. The 'receiver' instance you have running on port 7000 receives the webhook and logs out its contents.\n\nSample terminal output after running the example with some less important lines cleaned:\n```\nAttaching to webhook_forwarder, webhook_receiver\nwebhook_forwarder  | INFO:     Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)\nwebhook_receiver   | INFO:     Uvicorn running on http://0.0.0.0:9001 (Press CTRL+C to quit)\n\nwebhook_forwarder  | Environment configuration variables not found, using test value defaults.\nwebhook_receiver   | Environment configuration variables not found, using test value defaults.\nwebhook_forwarder  | Starting new HTTPS connection (1): api.github.com:443\nwebhook_receiver   | Starting new HTTPS connection (1): api.github.com:443\nwebhook_forwarder  | https://api.github.com:443 \"GET /meta HTTP/1.1\" 200 None\nwebhook_receiver   | https://api.github.com:443 \"GET /meta HTTP/1.1\" 200 None\nwebhook_forwarder  | INFO:     Application startup complete.\nwebhook_receiver   | INFO:     Application startup complete.\n\n# webhook is sent from github\nwebhook_forwarder  | sender_ip/x_ip: 172.22.0.1/140.82.115.116 is valid! \nwebhook_forwarder  | payld_signature: sha256=\u003csignature\u003e\nwebhook_forwarder  | local_signature: sha256=\u003csignature\u003e\nwebhook_forwarder  | Signature is valid, forwarding request...\nwebhook_forwarder  | Starting new HTTP connection (1): receiver:9001\nwebhook_receiver   | Webhook received, contents logged under debug\nwebhook_forwarder  | http://receiver:9001 \"POST /receive_webhook HTTP/1.1\" 200 29\nwebhook_forwarder  | INFO:     172.22.0.1:59160 - \"POST /forward_webhook HTTP/1.1\" 200 OK\nwebhook_receiver   | INFO:     172.22.0.2:41668 - \"POST /receive_webhook HTTP/1.1\" 200 OK\n```\n\n\n## API Endpoints\nThe application offers the following endpoints:\n1. **POST: /forward_webhook** - target to which a GitHub webhook delivery can be pointed.\n1. **POST: /receive_webhook** - testing endpoint to help troubleshoot your setup, simply takes and outputs a given JSON payload.\n1. **GET: /status** - aliveness check, returns status:alive and a checksum based on the main.py to help with broad version tracking.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantvirf%2Fwebhook-forwarder-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantvirf%2Fwebhook-forwarder-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantvirf%2Fwebhook-forwarder-python/lists"}