Repository navigation
feat: enforce optional inbound HMAC request signatures on configured routes - #4200
Open
pardeep-singh wants to merge 1 commit into
Open
pardeep-singh wants to merge 1 commit into
pardeep-singh wants to merge 1 commit into
Conversation
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #3924.
On master,
openmed/service/signing.pyalready hadverify_request_signatureand
NonceCache, and the docs said the scheme was available for inboundverification. But the service had no setting or middleware to require it.
Integrators had to wrap the ASGI app themselves.
This PR adds opt-in enforcement. Operators list route templates and point to a
secret file. Requests to those routes must carry a valid signature, or they are
rejected with a value-free
401before the handler runs. Everything else isunchanged, and nothing is installed when the settings are unset.
Type of Change
Changes Made
openmed/service/request_signing.py(new): settings parser, route validation, a verifier and a pure ASGI middleware. It reusesverify_request_signature,NonceCacheand the existing header names. It does not reimplement the HMAC.openmed/service/app.py: oneinstall_request_signing(...)block, placed so the check runs inside both body-limit layers and before routing.openmed/service/api_compatibility.py: registersignature_missing,signature_invalid,signature_staleandsignature_replayedas stable error categories.tests/unit/service/test_request_signing_middleware.py(new): 46 tests with synthetic secrets and an injected clock.docs/serving/request-signing.md: settings, route format, failure codes, middleware order, nonce cache limits and the multi-replica caveat.CHANGELOG.md: Unreleased Security entry.Testing
New tests cover:
signature_missing;signature_invalid, and no nonce is consumed;signature_stalein both directions;signature_replayed;/jobs/{job_id}, andHEADon a signedGETtemplate;413, not a signature error;caplogor/metrics.Before the fix the new file gave
1 failed, 45 errors(the module did notexist). After the fix all 46 pass.
Documentation
Code Quality
make format,make lint, andmake format-checkmake format-swiftandmake lint-swiftDependencies
Notes
OPENMED_SERVICE_REQUEST_SIGNING_ROUTES(for examplePOST /jobs,GET /jobs/{job_id}),OPENMED_SERVICE_REQUEST_SIGNING_SECRET_FILE,..._MAX_SKEW_SECONDS(300) and..._NONCE_CACHE_SIZE(10000). Signing is on only when routes are set.ROUTE_POLICIESand registered on the live app. Route matching reusesroute_key_for_requestfromauth.py, the same matcher used for route scopes.OSErrortext.503 service_busy, not one of the four401codes. It is a capacity limit, not a bad signature.GETtemplate also guardsHEAD, so a router that answersHEADwith theGEThandler cannot skip the check.signature_missing, and signature failures are not counted in request metrics or the auth failure limiter. Body-limit413s already behave this way.POST,PUTandPATCH.app.pychange is one import and one call. fix: run trusted-host, CORS and auth checks before buffering request bodies #4140 reorders the middleware increate_app, so a small rebase conflict there is expected. The fix is to keep this call inside the body-limit layers.Related Issues
Closes #3924
Related to #3573 (outbound webhook signing and key rotation stay there)