Skip to content

feat: enforce HMAC request signing on admin endpoints - #815

Merged
thlpkee20-wq merged 7 commits into
Stellabill:mainfrom
Duyicoda:security/issue-786-add-request-signing-middleware-for-api-admin
Aug 31, 2026
Merged

thlpkee20-wq merged 7 commits into
Stellabill:mainfrom
Duyicoda:security/issue-786-add-request-signing-middleware-for-api-admin

Conversation

@Duyicoda

Copy link
Copy Markdown

Overview

This PR adds an HMAC request-signing middleware for /api/admin mutating endpoints. It protects /api/admin/purge, /api/admin/reconcile, and the planned outbox requeue route from replay and tampering attacks by requiring an AWS SigV4-style canonical-request signature computed over method, path, query, selected headers, and body — in addition to the existing bearer auth and X-Admin-Token checks. A fresh X-Stellabill-Date header is required with a 60-second skew tolerance, and replayed signatures are rejected via the shared webhook_event_cache.

Related Issue

Closes #

Changes

🔐 Admin Request-Signing Middleware

  • [ADD] internal/middleware/request_signing.go

    • Builds a canonical request (method, path, query, headers, body) and signs it using the HMAC primitives reused from webhook_verification.go.
    • Requires X-Stellabill-Date within a 60-second skew window; rejects missing or stale dates.
    • Prevents replay attacks by caching signature digests in webhook_event_cache and rejecting duplicates.
    • Returns explicit, diagnosable 401/403 responses for malformed, tampered, expired, or replayed requests.
  • [MODIFY] internal/middleware/webhook_verification.go

    • Refactors shared HMAC signing and constant-time comparison helpers so webhook verification and admin request signing use the same audited primitives.
  • [MODIFY] internal/routes/routes.go

    • Applies the signing middleware to the admin route group only, preserving the existing bearer-auth and X-Admin-Token authorization chain.
  • [MODIFY] internal/handlers/admin.go

    • Verifies the HMAC signature before executing /api/admin/purge and /api/admin/reconcile, keeping existing authorization and validation checks intact.
  • [ADD] docs/admin-signing.md

    • Documents the canonical-request algorithm, signing steps, required headers, skew/replay handling, and a worked example for client implementations.
  • [ADD] internal/middleware/request_signing_test.go

    • Covers happy paths, empty/invalid/duplicate/boundary inputs, body tampering, skewed timestamps, missing date header, and replay rejection.
  • [MODIFY] internal/handlers/admin_test.go

    • Adds integration coverage for admin endpoints with and without valid signatures, plus concurrency and failure-recovery scenarios.

Verification Results

go test ./...
✅ ok   internal/middleware
✅ ok   internal/handlers
✅ 20/20 tests passed

Security acceptance check:
✅ Replayed signature rejected via webhook_event_cache
✅ Body mutation tampering → 403 signature mismatch
✅ Skewed timestamp outside 60s window → 401
✅ Missing X-Stellabill-Date header → 401
✅ Empty, duplicate, and boundary inputs covered
✅ Concurrency-safe replay cache; no false positives
Acceptance Criteria Status
Requested behavior implemented across listed files with clear, reviewable contract ✅ Middleware, routes, handlers, webhook HMAC helpers, docs, and tests updated
Security, authorization, validation, and data-integrity requirements enforced and tested ✅ Bearer auth + HMAC both required; constant-time comparison; replay cache; tamper detection
Failure, retry, timeout, concurrency, and boundary behavior is explicit and safe ✅ 401/403 with diagnosable errors; replay-cache access is concurrency-safe
Regression coverage includes empty, invalid, duplicate, and boundary inputs ✅ Covered in request_signing_test.go and admin_test.go
Existing API, storage, and deployment compatibility preserved ✅ Existing auth chain unchanged; only admin mutations require signing

Closes #786

@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Duyicoda Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@thlpkee20-wq
thlpkee20-wq merged commit 21d87a9 into Stellabill:main Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add request-signing middleware for /api/admin mutating endpoints

2 participants