feat(webhook): GEMINI-HARDEN-04 — authenticated webhook runner\n\nReplace print-only payload parser with production-hardened receiver:\n - HMAC-SHA256 signature verification (X-Gitea-Signature)\n - Event / repo / branch / action allowlists (config + env driven)\n - Idempotent event processing via X-Gitea-Delivery with TTL state file\n - Structured JSON logging (stdout + optional file)\n - Safe dispatch — pre-approved script invocations only, no arbitrary shell\n\nNew files:\n - scripts/webhook_runner.py — main HTTP server + policy engine\n - scripts/webhook_config.yaml — sample configuration\n - tests/test_webhook_runner.py — 40 pytest unit tests\n - tests/fixtures/webhook/*.json — payload fixtures for push/PR/issue\n\nAcceptance criteria:\n ✓ Verify Gitea webhook secret/signature\n ✓ Event, repo, branch, and action allowlists explicit and config-driven\n ✓ No direct git pull, shell execution, or fleet mutation from payload fields\n ✓ Structured logging with accepted/rejected events\n ✓ Idempotency via X-Gitea-Delivery tracking\n ✓ Local test fixtures: push, PR, issue, invalid-signature, unknown-event\n ✓ Deployment notes: config via env vars or scripts/webhook_config.yaml\n\nCloses #436
Some checks failed
Smoke Test / smoke (pull_request) Failing after 23s
Architecture Lint / Linter Tests (pull_request) Successful in 27s
Validate Config / YAML Lint (pull_request) Failing after 18s
Validate Config / JSON Validate (pull_request) Successful in 20s
Validate Config / Python Syntax & Import Check (pull_request) Failing after 58s
Validate Config / Python Test Suite (pull_request) Has been skipped
Validate Config / Shell Script Lint (pull_request) Failing after 1m1s
Validate Config / Cron Syntax Check (pull_request) Successful in 10s
Validate Config / Deploy Script Dry Run (pull_request) Successful in 12s
Validate Config / Playbook Schema Validation (pull_request) Successful in 27s
Architecture Lint / Lint Repository (pull_request) Failing after 23s
PR Checklist / pr-checklist (pull_request) Successful in 3m4s
Some checks failed
Smoke Test / smoke (pull_request) Failing after 23s
Architecture Lint / Linter Tests (pull_request) Successful in 27s
Validate Config / YAML Lint (pull_request) Failing after 18s
Validate Config / JSON Validate (pull_request) Successful in 20s
Validate Config / Python Syntax & Import Check (pull_request) Failing after 58s
Validate Config / Python Test Suite (pull_request) Has been skipped
Validate Config / Shell Script Lint (pull_request) Failing after 1m1s
Validate Config / Cron Syntax Check (pull_request) Successful in 10s
Validate Config / Deploy Script Dry Run (pull_request) Successful in 12s
Validate Config / Playbook Schema Validation (pull_request) Successful in 27s
Architecture Lint / Lint Repository (pull_request) Failing after 23s
PR Checklist / pr-checklist (pull_request) Successful in 3m4s
This commit is contained in:
75
scripts/webhook_config.yaml
Normal file
75
scripts/webhook_config.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
# Webhook Runner Configuration — GEMINI-HARDEN-04
|
||||
# Placed alongside scripts/webhook_runner.py
|
||||
# Environment variables override these values.
|
||||
|
||||
webhook:
|
||||
# Network binding
|
||||
host: 127.0.0.1
|
||||
port: 7777
|
||||
|
||||
# Shared secret with Gitea (REQUIRED in production)
|
||||
# Set via WEBHOOK_SECRET env var or replace here
|
||||
secret: null
|
||||
|
||||
# Allowlists
|
||||
allowed_events:
|
||||
- push
|
||||
- pull_request
|
||||
- issues
|
||||
- issue_comment
|
||||
|
||||
# Repository allowlist — patterns: "org/repo" or "org/*"
|
||||
allowed_repos:
|
||||
- "Timmy_Foundation/*"
|
||||
|
||||
# Branches allowed for push events (pattern match against full ref)
|
||||
allowed_branches:
|
||||
- main
|
||||
- master
|
||||
- develop
|
||||
|
||||
# PR/issue actions allowed
|
||||
allowed_actions:
|
||||
- opened
|
||||
- closed
|
||||
- synchronize
|
||||
- reopened
|
||||
- created
|
||||
- edited
|
||||
|
||||
# Idempotency — prevents double-processing on retries
|
||||
idempotency:
|
||||
state_file: .webhook_idempotency.json
|
||||
max_entries: 10000
|
||||
ttl_days: 30
|
||||
|
||||
# Structured logging
|
||||
logging:
|
||||
level: INFO
|
||||
file: null # null → stdout
|
||||
|
||||
# Safe dispatch rules — only pre-approved actions
|
||||
dispatch:
|
||||
push:
|
||||
refs/heads/main:
|
||||
allowed: true
|
||||
action: log_and_ack
|
||||
comment: Main push — logged, no auto-deploy
|
||||
refs/heads/:
|
||||
allowed: true
|
||||
action: log_and_ack
|
||||
comment: Non-main branch push — logged
|
||||
pull_request:
|
||||
opened:
|
||||
allowed: true
|
||||
action: log_and_ack
|
||||
comment: PR opened — logged
|
||||
synchronize:
|
||||
allowed: true
|
||||
action: log_and_ack
|
||||
comment: PR updated — logged
|
||||
issues:
|
||||
opened:
|
||||
allowed: true
|
||||
action: log_and_ack
|
||||
comment: Issue opened — logged
|
||||
Reference in New Issue
Block a user