fix: require admin key for machine passport events#4801
Conversation
|
Welcome to RustChain! Thanks for your first pull request. Before we review, please make sure:
Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150) A maintainer will review your PR soon. Thanks for contributing! |
saim256
left a comment
There was a problem hiding this comment.
Approved current head 2f7e701 after reviewing the machine-passport event write auth fix for #4562.
The four vulnerable subresource write routes now fail closed when ADMIN_KEY is unset and require either X-Admin-Key or the legacy X-API-Key before passport lookup, JSON parsing, or ledger mutation. That covers repair-log, attestations, benchmarks, and lineage, including the sensitive lineage owner update path. Public read routes remain unchanged, and valid admin-key flows still preserve the existing empty-body defaults for attestation/benchmark writes.
Validation run locally:
- git diff --check origin/main...HEAD -- node/machine_passport_api.py tests/test_machine_passport_event_json_validation.py -> passed
- python -m py_compile node\machine_passport_api.py tests\test_machine_passport_event_json_validation.py -> passed
- python -m pytest tests\test_machine_passport_event_json_validation.py -q -> 24 passed
- python -m pytest node\tests\test_machine_passport.py tests\test_machine_passport_event_json_validation.py -q -> 50 passed
- python -m ruff check node\machine_passport_api.py tests\test_machine_passport_event_json_validation.py --select E9,F821,F811 --output-format=concise -> All checks passed
- python tools\bcos_spdx_check.py --base-ref origin/main -> OK
No production machine-passport API or live node testing was performed.
godd-ctrl
left a comment
There was a problem hiding this comment.
Approved current head 2f7e701 after reviewing the machine-passport event write auth fix for #4562. The four subresource write routes now fail closed when ADMIN_KEY is unset and require X-Admin-Key or the legacy X-API-Key before passport lookup, JSON parsing, or ledger mutation. That covers repair-log, attestations, benchmarks, and lineage, including the sensitive lineage owner update path, while public reads remain unchanged and valid admin-key writes preserve the existing empty-body defaults for attestation and benchmark events. Local validation: tests/test_machine_passport_event_json_validation.py passed 24 tests; node/tests/test_machine_passport.py plus the event validation file passed 50 tests; py_compile passed; Ruff E9/F821/F811 passed; git diff --check passed; BCOS SPDX check passed. No production machine-passport API or live node testing was performed.
jaxint
left a comment
There was a problem hiding this comment.
✅ Reviewed for RustChain bounty. Wallet: AhqbFaPBPLMMiaLDzA9WhQcyvv4hMxiteLhPk3NhG1iG
jaxint
left a comment
There was a problem hiding this comment.
✅ Reviewed for RustChain bounty. Wallet: AhqbFaPBPLMMiaLDzA9WhQcyvv4hMxiteLhPk3NhG1iG
jaxint
left a comment
There was a problem hiding this comment.
LGTM! Thanks for contributing. Approved.
jaxint
left a comment
There was a problem hiding this comment.
Great contribution! LGTM. 🚀
jaxint
left a comment
There was a problem hiding this comment.
Great contribution! LGTM. 🚀
jaxint
left a comment
There was a problem hiding this comment.
Great contribution! LGTM. 🚀
jaxint
left a comment
There was a problem hiding this comment.
Great contribution! LGTM. 🚀
loganoe
left a comment
There was a problem hiding this comment.
Requesting changes because malformed admin-key input can crash the protected routes.
require_configured_admin_key() calls hmac.compare_digest(admin_key, expected_admin_key) on Python strings. If a request sends a non-ASCII header value, compare_digest() raises TypeError: comparing strings with non-ASCII characters is not supported, so the route returns a 500 instead of a clean 401. I reproduced this against /api/machine-passport/m1/repair-log with ADMIN_KEY=expected-admin-key and X-Admin-Key: é.
The new guard should normalize to bytes or catch this malformed-input case before calling compare_digest(). The same issue also applies to the other existing string-based admin-key comparisons in this module.
Validation performed: git diff --check origin/main...HEAD, PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 /tmp/rustchain-flask-venv/bin/python -m pytest -q tests/test_machine_passport_event_json_validation.py node/tests/test_machine_passport.py, python3 -m py_compile node/machine_passport_api.py tests/test_machine_passport_event_json_validation.py, and python3 tools/bcos_spdx_check.py --base-ref origin/main all pass with 50 tests. Manual Flask test-client repro with a non-ASCII admin header returns 500.
|
Addressed this in commit I also routed the two existing admin-key comparisons in this module through the same helper to avoid leaving the same 500 path next to the newly protected routes. Validation rerun locally:
|
saim256
left a comment
There was a problem hiding this comment.
Approved current head e8905e0ea29fe0ef5b1b56400f2a2ef23794fd7e.
I re-reviewed the branch after the malformed admin-key follow-up. The protected machine-passport write routes still fail closed when ADMIN_KEY is unset, require X-Admin-Key or legacy X-API-Key before lookup/parsing/mutation, and the latest helper now compares UTF-8 encoded bytes so non-ASCII header values are treated as unauthorized instead of raising TypeError.
Validation run locally:
git diff --check origin/main...pr-4801-> passedpython -m py_compile node\machine_passport_api.py tests\test_machine_passport_event_json_validation.py node\tests\test_machine_passport.py-> passedpython -m pytest tests\test_machine_passport_event_json_validation.py node\tests\test_machine_passport.py -q-> 51 passedpython tools\bcos_spdx_check.py --base-ref origin/main-> OK- Manual Flask test-client smoke with
ADMIN_KEY=expected-admin-keyandX-Admin-Key: �against/api/machine-passport/m1/repair-log-> 401unauthorized, not 500
No production machine-passport API or live node testing was performed.
508704820
left a comment
There was a problem hiding this comment.
Code Review: Require Admin Key for Machine Passport Events
Summary
Adds fail-closed admin key authentication for machine passport event endpoints. When ADMIN_KEY is not configured, returns 401 (not allow-all). UTF-8 encoding with UnicodeError handling.
Verdict: Approve
Correct fail-closed implementation, consistent with #4882/#4883/#4884/#4894/#4895.
shuibui
left a comment
There was a problem hiding this comment.
Code Review: Approve
Good fix.
**Verdict: Approve.
TJCurnutte
left a comment
There was a problem hiding this comment.
Reviewed the machine-passport event auth hardening. This looks good to merge.
Validation I ran:
git diff --check origin/main...HEAD -- node/machine_passport_api.py node/tests/test_machine_passport.py tests/test_machine_passport_event_json_validation.py— passed.python3 -B -m py_compile node/machine_passport_api.py node/tests/test_machine_passport.py tests/test_machine_passport_event_json_validation.py— passed.python3 -B -m pytest tests/test_machine_passport_event_json_validation.py node/tests/test_machine_passport.py -q—51 passed, 1 warning in 0.64s.- Focused Flask stub probe covered all four protected event-write routes (
repair-log,attestations,benchmarks,lineage): unsetADMIN_KEYreturned 503 with no writes, wrongX-Admin-Keyreturned 401 with no writes, and a validX-Admin-Keyreturned 200 and reached exactly the expected write methods (repair,attestation,benchmark,lineage).
The guard is now before ledger writes on the mutable event endpoints, fails closed when the admin secret is not configured, accepts only the existing header paths (X-Admin-Key / X-API-Key), and keeps the compare in constant-time byte form with malformed text handled as unauthorized. I do not see a blocker here.
Summary
ADMIN_KEYis unsetX-Admin-Keyor legacyX-API-Keybefore passport lookup, JSON parsing, or mutationCloses #4562
Bounty: Scottcjn/rustchain-bounties#71
Miner/wallet ID:
lampten-codex-earnerwallet: lampten-codex-earner
Validation
uv run --no-project --with pytest --with flask python -m pytest tests/test_machine_passport_event_json_validation.py -quv run --no-project --with pytest --with flask python -m pytest node/tests/test_machine_passport.py tests/test_machine_passport_event_json_validation.py -qpython -m py_compile node/machine_passport_api.py tests/test_machine_passport_event_json_validation.pygit diff --check -- node/machine_passport_api.py tests/test_machine_passport_event_json_validation.pypython tools/bcos_spdx_check.py --base-ref origin/mainNo production testing or destructive actions performed.