fix(registryctl): permit tutorial purpose in generated notary policy#189
Merged
Conversation
Member
Author
|
Two follow-up commits after a template audit:
Same security posture as before: one purpose permitted in generated local sample configs only. |
The "Evaluate a claim with Registry Notary" tutorial failed at its central step: `registryctl notary smoke` reported 6 PASS then `FAIL notary evaluator can verify starter claim`, and the documented evaluate curl returned 403 pdp.purpose_not_permitted instead of 200 satisfied. Root cause: the generated benefits/local-relay notary config (notary_config.yaml.tmpl) declared a source binding with no matching.allowed_purposes. Source-binding PDP policies run with permit_unconstrained = false, so purpose_gate_is_declared always returns true; an empty purpose allow-list therefore denies every request with pdp.purpose_not_permitted before any evidence lookup. This also made the tutorial's 409 evidence.not_available teaching point (per-9999) unreachable. Fix: add matching.allowed_purposes with the tutorial purpose to the generated source binding, mirroring what the OpenCRVS/DCI sample template already does and matching the purpose the smoke check and docs send. Security review notes: - The change only permits one additional purpose (https://example.local/purpose/tutorial) in the LOCAL sample project that registryctl generates from `init relay --sample benefits` + `add notary`. It does not touch production defaults, shared PDP behavior, or any committed runtime config; the server keeps failing closed on empty allow-lists. - Purpose is the only gate added. No legal-basis, consent, jurisdiction, or assurance constraints are relaxed; the sample carries none of those, matching the tutorial's single-purpose evaluate request. Test: added local_relay_notary_config_permits_tutorial_purpose, which parses the generated notary config and asserts the person source binding permits TUTORIAL_PURPOSE. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
`registryctl open` and `registryctl notary open` promised to "open or print" the local API docs URL, but printed nothing in headless sessions. On macOS `open <url>` returns exit 0 even over SSH with no display, so the conditional fallback (print only when the launch failed) never fired and the user was left with no URL. Always print the docs URL(s) first, then best-effort launch a browser. Extract relay_open_lines / notary_open_lines pure helpers so the surfaced URLs are unit testable without spawning a browser during tests. Tests: relay_open_always_reports_docs_url_for_headless_fallback and notary_open_always_reports_docs_url_for_headless_fallback. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
registryctl notary smoke sends the tutorial purpose for standalone projects too, and the source-binding PDP policy fails closed, so the standalone template's empty allow-list denied every evaluation with pdp.purpose_not_permitted, same defect as the benefits template. Security review notes: permits exactly one purpose in the generated local project config; no production defaults or shared PDP behavior change, and the server still fails closed on empty allow-lists. Also gives the generated file an orientation header comment matching the relay template's voice. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
The generated configs are read by tutorial followers, not maintainers. Reword the purpose allow-list comment to state the field's contract (deny-by-default, the error code, what to edit) instead of justifying the change, add orientation headers matching the relay template, and warn in the OpenCRVS/DCI template that matching context constraints must stay in sync with the evaluator key's authorization_details. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
adc6bc0 to
293076b
Compare
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.
Problem
The "Evaluate a claim with Registry Notary" tutorial fails at its central step on both released v0.8.3 and current main.
registryctl notary smokefails at "notary evaluator can verify starter claim" (expected 200, actual 403), and the tutorial's own evaluate curl returns403 pdp.purpose_not_permitted(matching_policy_idnotary.source_binding.relay.benefits_casework.person) for the tutorial's own purpose URI. The 409evidence.not_availableteaching point is unreachable for the same reason. Found by a full black-box reader run of the published tutorial.Root cause
The benefits template (
crates/registryctl/src/templates/notary_config.yaml.tmpl) declared thepersonsource binding with nomatching.allowed_purposes. Source-binding PDP policies are built fail-closed (permit_unconstrained: falseinregistry-notary-server/src/runtime.rs; emptypurpose_constraintsdenies inregistry-platform-pdp), so the generated sample denied every purpose, including its own documented one. The OpenCRVS/DCI template already allow-lists the same tutorial purpose, confirming the server behavior is intended and the fix belongs in the generated config.Changes
fix(registryctl): permit tutorial purpose in generated notary policy: add amatching.allowed_purposesblock containing onlyhttps://example.local/purpose/tutorialto the benefits notary template. Test-first:local_relay_notary_config_permits_tutorial_purposeparses and validates the generated config and asserts the allow-list.fix(registryctl): always print docs URL for open commands:registryctl open/notary openprinted nothing in headless sessions because macOSopenexits 0 even with no display, so the documented fallback never fired. The commands now always print the URL(s), then best-effort launch a browser. Output extracted into unit-testable helpers with tests.Security review notes (authorization/policy defaults)
registryctlgenerates. It does not alter production defaults, shared PDP behavior, or any committed runtime config.Verification
cargo fmt --check,cargo check --locked --workspace --all-targets,cargo clippy -p registryctl --all-targets -- -D warnings,cargo test --locked -p registryctl: all green.registryctl notary smokechecks pass; the tutorial's evaluate curl forper-2001returns 200 withsatisfied: true;per-9999now returns the documented409 evidence.not_available.Known related issues, deliberately not in this PR
commitmentfingerprint field the pinned released relay image requires, so a project generated by a locally built registryctl fails to start the pinned relay (missing field commitment). Separate relay-config drift.registry-relay.dev,docs.registry-notary.dev); domain consolidation is tracked separately.version.workspace = true.