Show HN: Hooky – Go로 작성된 경량 HTTP 웹훅 서버

hackernews | | 📰 뉴스
#go #http #오픈소스 #웹훅 #자동화 #하드웨어/반도체
원문 출처: hackernews · Genesis Park에서 요약 및 분석

요약

Go 언어로 작성된 경량 웹훅 서버 'Hooky'가 공개되었습니다. 이 도구는 HMAC-SHA256과 베어러 토큰을 이용한 비밀 검증, 슬라이딩 윈도우 기반의 속도 제한, IP 화이트리스트 등을 포함한 보안 기능을 제공합니다. 또한 요청 페이로드나 헤더를 기반으로 명령어를 동적으로 구성할 수 있으며, Docker 이미지나 바이너리로 쉽게 배포할 수 있습니다. 주요 기능으로는 핫 리로드, 구조화된 로깅, 그리고 장기 실행 명령어 처리를 위한 타임아웃 및 동시 실행 제어가 포함됩니다.

본문

A lightweight HTTP webhook server written in Go. Trigger shell scripts from HTTP requests with built-in secret validation, rate limiting, and configurable execution controls. Runs standalone or in Docker. - Secret validation — HMAC-SHA256/SHA1/SHA512 signatures or bearer tokens - Trigger rules — composable and /or /not conditions on payload fields, headers, query params, or IP ranges - Rate limiting — sliding window per hook - Concurrency control — limit simultaneous executions per hook - Command timeouts — kill long-running commands automatically - Fire-and-forget — return a response immediately and run the script in the background - Hot reload — edit your config without restarting ( -hotreload orSIGHUP ) - Proxy-aware — correct client IP resolution behind reverse proxies - Structured logging — JSON or text output via log/slog - Health endpoint — /health - No secret in config — use env:VAR orfile:/path to keep secrets out of config files Binary — download the latest release for your platform from the releases page: tar -xzf hooky_*_linux_amd64.tar.gz sudo mv hooky /usr/local/bin/ Docker: docker pull ghcr.io/virtuallytd/hooky:latest From source: go install hooky@latest - Create a hooks.yaml : hooks: - id: deploy command: /scripts/deploy.sh secret: type: hmac-sha256 header: X-Hub-Signature-256 value: env:DEPLOY_SECRET - Run: DEPLOY_SECRET=mysecret hooky -hooks hooks.yaml - Trigger it: BODY='{"ref":"main"}' SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "mysecret" | awk '{print $2}') curl -X POST http://localhost:9000/hooks/deploy \ -H "Content-Type: application/json" \ -H "X-Hub-Signature-256: sha256=$SIG" \ -d "$BODY" Hooks are defined in a YAML or JSON file. Pass the path with -hooks . hooks: - id: string # URL endpoint: /hooks/{id} command: string # Executable to run working-dir: string # Working directory for the command timeout: duration # e.g. 30s, 5m (default: 30s) http-methods: [POST] # Allowed HTTP methods (default: [POST]) fire-and-forget: false # Return 200 immediately, run script in background max-concurrent: 0 # Max simultaneous executions (0 = unlimited) secret: # Validate the incoming request type: hmac-sha256 # hmac-sha1 | hmac-sha256 | hmac-sha512 | token header: X-Hub-Signature-256 query: token # Alternative: read token from query parameter value: env:MY_SECRET # env:VAR, file:/path, or a literal string trigger-rule: # Additional conditions (optional) and: - match: type: value # value | regex | ip-whitelist | payload-hmac-sha256 | ... parameter: source: payload # payload | header | query | request | raw-body name: event # dot-notation for nested fields: repository.full_name value: push args: # Positional arguments passed to the command - source: payload name: ref env: # Environment variables for the command - name: GIT_REF source: payload # payload | header | query | env | literal key: ref response: success-code: 200 error-code: 500 mismatch-code: 403 # Returned when secret or trigger rules fail message: "Triggered." include-output: false # Stream stdout/stderr back to the caller headers: X-Custom: value rate-limit: requests: 10 window: 1m | Source | Description | |---|---| payload | JSON body field. Supports dot-notation: repository.full_name | header | HTTP request header | query | URL query parameter | request | Request metadata. Supported names: remote-addr | raw-body | The raw, unparsed request body | literal | A hard-coded string value (use name as the value) | entire-payload | The full JSON body as a string | entire-headers | All headers serialised as JSON | entire-query | All query parameters serialised as JSON | The value field in secret and trigger rule secret fields supports three formats: | Format | Description | |---|---| env:MY_VAR | Read from the $MY_VAR environment variable | file:/run/secrets/token | Read from a file (whitespace trimmed) | literal-value | Used as-is | Rules can be nested with and , or , and not : trigger-rule: and: - match: type: value parameter: {source: payload, name: event} value: push - or: - match: type: regex parameter: {source: payload, name: ref} value: ^refs/heads/main$ - match: type: ip-whitelist ip-range: 10.0.0.0/8 Match types: | Type | Description | |---|---| value | Exact string match | regex | Go regular expression match | ip-whitelist | CIDR range check (uses ip-range field) | payload-hmac-sha1 | HMAC-SHA1 signature of the raw body | payload-hmac-sha256 | HMAC-SHA256 signature of the raw body | payload-hmac-sha512 | HMAC-SHA512 signature of the raw body | -hooks string Path to hooks config file, JSON or YAML (default: hooks.yaml) -addr string Address to listen on (default: :9000) -prefix string URL prefix for hook endpoints (default: hooks) -cert string TLS certificate file — enables HTTPS when set -key string TLS private key file -hotreload Watch config file and reload on change -log-format string Log format: text | json (default: text) -log-level string Log level: debug | info | warn | error (default: info) -proxy-header string Header

Genesis Park 편집팀이 AI를 활용하여 작성한 분석입니다. 원문은 출처 링크를 통해 확인할 수 있습니다.

공유

관련 저널 읽기

전체 보기 →