aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 18:11:13 +0000
committertv <tv@krebsco.de>2026-11-08 19:28:38 +0100
commit5bcf27ca2a10f16befb96c70bf04ae8a5c04ceaa (patch)
tree9f2ea97e3482a388aa3959f46b4c91f77a20c440 /src
parent857771cc05c73fb91477d7afcf91f10e25aaa0ab (diff)
rules: under strict, a user's own entry is its own to sign
Review 2, N5: under a strict policy a user's signed PUT of its own entry, keys changed (continuum-signed key-add), passed the API and envelope::check's own_keys_only, and was then refused by the rules' path check: _continuum/users/<name> wanted write on the registry, so the node judged it as every node would and answered 403. 1168 worked only without strict. Under a strict policy the rules now take a write of a user's own entry from that user, leaving what it may be to signed_values, which runs envelope::check: an envelope by the user, with only its keys changed, one left at least. Strict only: under another policy the entry isn't an envelope, and the user would rewrite its own capabilities.
Diffstat (limited to 'src')
-rw-r--r--src/access/rules.rs28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/access/rules.rs b/src/access/rules.rs
index 4e4e6e9..b5dcf3a 100644
--- a/src/access/rules.rs
+++ b/src/access/rules.rs
@@ -193,6 +193,13 @@ pub(crate) fn judge(doc: &Document, epoch: Epoch, change: &Change<'_>) -> Result
|| user_may(path)
|| user_may(&meta::path(&[meta::USERS]))
}
+ // Under a strict policy, a user's own entry, as an envelope: signed by the user
+ // with only its keys changed (`envelope::check`, run by `signed_values`).
+ (Some(meta::USERS), Some(owner))
+ if path.len() == 3 && change.user == Some(owner) && policy.strict() =>
+ {
+ true
+ }
// A user's own keys (`/auth/keys`), whatever else it may do, one left at
// least.
(Some(meta::USERS), Some(owner))
@@ -885,6 +892,27 @@ mod tests {
)));
}
+ /// Under a strict policy, a user's own entry is its own to write (what it may sign
+ /// there, `envelope::check` says); not another's; without strict, not its own either.
+ #[test]
+ fn users_write_their_own_entry_under_strict() {
+ let mut doc = swarm(true);
+ let own = "_continuum/users/bob";
+ assert!(refused(judged(&doc, "a", Some("bob"), &[own])));
+ write(
+ &mut doc,
+ "_continuum/access/policy",
+ json!({"version": 1, "values": "signed"}),
+ );
+ assert!(judged(&doc, "a", Some("bob"), &[own]).is_ok());
+ assert!(refused(judged(
+ &doc,
+ "a",
+ Some("bob"),
+ &["_continuum/users/alice"]
+ )));
+ }
+
/// A node that isn't a member may only register itself.
#[test]
fn strangers_register_themselves_only() {