aboutsummaryrefslogtreecommitdiffstats
path: root/src/access/rules.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 15:43:45 +0000
committertv <tv@krebsco.de>2026-11-08 16:49:56 +0100
commited27acb707d940c5b796b1079d3d74698484aeba (patch)
tree2761073c72f91ad8f3f0ed4b38844bb8ab8d14a2 /src/access/rules.rs
parent1cdf5ce6e2a935ec17f800706aa8f289036d90f7 (diff)
users: a user manages its own keys
Only a user who may manage users could change a user's keys: a user couldn't add a new laptop's key, or remove a lost one. A user now manages its own keys, whatever else it may do: * GET /auth/keys: its keys, its entry, and the envelope holding it under a strict policy (`signed`), to sign against. * PUT /auth/keys/{id} with an authorized_keys line, DELETE /auth/keys/{id}: one change, as the user. The rules take a write of _continuum/users/<name>/keys/… from the user it names. * Under a strict policy, the user signs its entry with only its keys changed, with a key it holds already (envelope::check takes that from the user itself), PUT to its own entry even without write on the registry; continuum-signed key-add and key-remove do so.
Diffstat (limited to 'src/access/rules.rs')
-rw-r--r--src/access/rules.rs42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/access/rules.rs b/src/access/rules.rs
index 3eca1c9..450addb 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]))
}
+ // A user's own keys (`/auth/keys`), whatever else it may do.
+ (Some(meta::USERS), Some(owner))
+ if path.get(3).map(String::as_str) == Some("keys")
+ && change.user == Some(owner) =>
+ {
+ true
+ }
// A node forgotten while alive cancels its own record (`swarm::peer::forget`).
(Some(meta::FORGOTTEN), Some(owner)) => owner == node || user_may(path),
(Some(meta::REMAKES), Some(id)) => match path.get(3).map(String::as_str) {
@@ -788,6 +795,41 @@ mod tests {
assert!(decide(Some("carol"), "committed", 0).is_ok());
}
+ /// A user's own keys: its own to change, whatever else it may do; another's, or the
+ /// rest of its own entry, not.
+ #[test]
+ fn users_change_their_own_keys() {
+ let doc = swarm(true);
+ assert!(
+ judged(
+ &doc,
+ "a",
+ Some("bob"),
+ &["_continuum/users/bob/keys/laptop"]
+ )
+ .is_ok()
+ );
+ assert!(judged(&doc, "a", Some("bob"), &["_continuum/users/bob/keys"]).is_ok());
+ assert!(refused(judged(
+ &doc,
+ "a",
+ Some("bob"),
+ &["_continuum/users/alice/keys/laptop"]
+ )));
+ assert!(refused(judged(
+ &doc,
+ "a",
+ Some("bob"),
+ &["_continuum/users/bob/caps"]
+ )));
+ assert!(refused(judged(
+ &doc,
+ "a",
+ None,
+ &["_continuum/users/bob/keys/laptop"]
+ )));
+ }
+
/// A node that isn't a member may only register itself.
#[test]
fn strangers_register_themselves_only() {