Re: Joins on capabilities that have passed through different membranes
David Bruant <[email protected]> Tue, 5 Jan 2016 13:41:38 +0100
| Newsgroups | gmane.comp.capabilities.general |
|---|---|
| Message-ID | <[email protected]> |
Le 05/01/2016 02:53, Kenton Varda a =E9crit :
> Hi Mark and cap-talk,
>
> I'm interested to know if you've thought about the following problem:
>
> You want to perform a join on two capabilities A and B, which were =
> obtained from Alice and Bob respectively.
Can you provide a concrete example of why one would want to perform the =
join instead of just using the two capabilities separately?
If you obtained two capabilities from two different parties, it seems =
non-intuitive (to me at least) to want to merge them. You obtained a =
capability from Alice and can do some things with it, you obtained a =
capability from Bob and can do some things, why trying to merge them =
(especially if you do not have prior knowledge that they may point to =
the same underlying object)?
(assuming the join makes sense in the rest of my response)
> Semantically, the two capabilities point to the same object, in that =
> the messages passed to either one are ultimately routed to the same =
> place. However, the two capabilities have different conditions under =
> which they become revoked, because the original creator of the =
> capability wanted to maintain the ability to revoke Alice's and Bob's =
> access independently. Therefore, capabilities A and B are not really =
> pointing to the same object. So, what happens when you join them?
>
> The naive answer seems to be "they can't be joined because they're not =
> the same". However, this answer seems highly problematic in practice.
>
> It seems to me that it is necessary to separate the notion of the =
> endpoint object to which the capabilities point from the notion of =
> restrictions/requirements added on top of them (where cap A has the =
> requirement "Alice's access has not been revoked" and cap B has the =
> requirement "Bob's access has not been revoked"). When joining two =
> capabilities -- as long as the endpoint is the same, then the =
> requirements must be "merged".
>
> "Merging" requirements could either mean taking the intersection (the =
> joined capability is revoked if either original capability is revoked) =
> or the union (the joined capability is revoked if *both* inputs are =
> revoked).
or anything in between as suggested by others.
In your message, you're refering to the revokation policy, but =
attenuation is also something that wants to be merged when joining.
Without loss of generality, it looks like merging code needs to be added =
to the mix.
In initial context:
```
var O =3D {...}; // original capability, "same original object"
var capPolicyForAlice =3D {...};
var capPolicyForBob =3D {...};
var A =3D makeCapForAlice(O, capPolicyForAlice);
var B =3D makeCapForBob(O, capPolicyForBob);
// send A to Alice
// send B to Bob
```
in your context:
```
var A; // capability for O received from Alice
var B; // capability for O received from Bob
var M =3D merge(A, B);
```
Without more information, merge can only perform an intersection or =
union of capPolicyForAlice and capPolicyForBob (assuming there even =
exists an "intesect" or "unite" function that does something sensible =
with these objects?)
Still, the code as written above does not tell where the merge function =
comes from. Let's assume it comes from the initial context (maybe =
travelled through Alice or Bob?). But at least, I don't think there is a =
reason to assume there exists a global (and generic) merge function.
So there might need to be code that decides how the merge should happen. =
At first guess, I'd say a reducer function attached to each policy.
The code in the initial context would then look lik something like:
```
var O =3D {...}; // original capability, "same original object"
var capToPolicy =3D new WeakMap();
var capPolicyForAlice =3D {reduce(otherPolicy){
return combine(this, otherPolicy);
// combine can be intesect, union, or something else
}, ...};
var capPolicyForBob =3D {reduce(otherPolicy){
return combine(this, otherPolicy);
}, ...};
var A =3D makeCap(O, capPolicyForAlice);
capToPolicy.set(A, capPolicyForAlice);
var B =3D makeCap(O, capPolicyForBob);
capToPolicy.set(B, capPolicyForBob);
function merge(o1, o2){
var capPolicy1 =3D capToPolicy.get(o1);
var capPolicy2 =3D capToPolicy.get(o2);
if(!capPolicy1 || !capPolicy2)
throw new Error('no idea how to merge these')
var mergeCapPolicy =3D capPolicy1.reduce(capPolicy2); // this is =
asymetric
return makeCap(O, mergeCapPolicy);
}
// send A to Alice
// send B to Bob
```
With this "architecture", it's possible to join two caps leading to the =
same object (... maybe I should have made nested weakmaps with the cap =
target as first key, but you get the point) by merging their =
revokation/attenuation requirements with arbitrary flexibility, but it's =
only possible if someone in the chain has access to the policies that =
need to be merged.
The reduce functions are given access to other cap policies at merge =
time. It worries me a bit, but at the same time, they do need these =
policies to perform the merge so it doesn't seem like abusive authority.
David