Hi Thomas,

Sorry I missed this earlier!

So, "level 2" of the RPC protocol / SturdyRefs turn out to be something
that does not make sense to specify as part of the Cap'n Proto
implementation itself. Probably level 2 should be ripped out of the spec
entirely. This is what we learned as we build Sandstorm: SturdyRefs and how
to restore them turned out to be intrinsically tied to the Sandstorm
environment, and attempts to define an "abstract" SturdyRef format not
dependent on Sandstorm did not seem to fit what Sandstorm needed.

To understand this, consider a few different cases:
- A Sandstorm grain (app instance).
- A node in the Blackrock (clustered Sandstorm) infrastructure.
- An application on the general internet that has nothing to do with
Sandstorm.

Now try to answer the question: What does a SturdyRef express, and how does
one restore it?

The answer is totally different depending on the context:

- For a Sandstorm grain, a SturdyRef can be an opaque byte string, which
refers to an object in another grain. The client grain passes the SturdyRef
to the Sandstorm API to restore it. The Sandstorm infrastructure then looks
up the token in its database, verifies that the token belongs to the
requesting grain, finds out to what grain the token points, starts up that
grain, asks that grain for a live ref of the desired capability, and then
returns that to the requesting grain.

- For a Blackrock node, a SturdyRef typically refers to another component
of the Blackrock infrastructure: maybe an object in Blackrock storage (a
graph store of Cap'n Proto objects), or a running container on one of the
worker nodes. Or, it could also refer to something hosted in a grain, or a
totally external capability. See the definition here:
https://github.com/sandstorm-io/blackrock/blob/master/src/blackrock/cluster-rpc.capnp#L67
Notice how the namespace of SturdyRefs as seen by the infrastructure itself
is completely different from the namespace of SturdyRefs seen by apps --
although some kinds of objects can be represented by both. Also notice that
depending on the type of SturdyRef, the process for restoring is different:
for "transient" objects located on a specific machine, the restorer
connects directly to the target, but for stored object, the restorer
connects to "the storage service" which it is introduced to independently
at startup, and for external caps, it connects to "the gateways", etc.

- For the public internet, you probably want a SturdyRef to encode a
hostname and perhaps a pinned certificate list. Maybe it even encodes an
HTTP URL, to which a Cap'n Proto session can be created over WebSocket or
streaming HTTP/2. Additionally, it would encode some sort of object ID,
probably as an AnyPointer. The target host would provide a bootstrap
interface with a restore() method that takes this AnyPointer.

As you can see, in each case the format of a SturdyRef and the procedure
for restoring it is completely different, so much so that it doesn't appear
that any "standard" definition makes sense.

At some point I do want to spec out the "public internet" SturdyRef format
and protocol. But, for now, I think implementations should leave SturdyRefs
up to the application to define.

On a side note, it seems like you were confused a bit by EZ RPC's mechanism
for exporting capabilities by name. We deprecated this in favor of a
singleton bootstrap interface because you can trivially implement the same
thing by defining a bootstrap interface with a "restore(name)" method.

-Kenton

On Wed, Aug 23, 2017 at 7:48 AM, Thomas Leonard <[email protected]> wrote:

> Hi,
>
> I'm currently trying to implement RPC level 2 (for the OCaml RPC
> implementation - see https://github.com/mirage/capnp-rpc#encryption-and-
> authentication for the current status).
>
> I have some questions...
>
> https://capnproto.org/cxxrpc.html says:
>
> Current Status: As of version 0.4, Cap’n Proto’s C++ RPC implementation is
>> a Level 1 implementation. Persistent capabilities, three-way introductions,
>> and distributed equality are not yet implemented.
>>
>
> But I imagine this is out of date.
>
> The RPC spec says:
>
> How exactly a SturdyRef is restored to a live object is specified along
>> with the SturdyRef definition (i.e. not by rpc.capnp).
>>
>
> and
>
> However, in practice, the ability to restore SturdyRefs is itself a
>> capability that may require going through an authentication process to
>> obtain. Thus, it makes more sense to define a "restorer service" as a full
>> Cap'n Proto interface. If this restorer interface is offered as the vat's
>> bootstrap interface, then this is equivalent to the old arrangement.
>
>
> I imagine this must be some network-realm-wide restorer API, because if
> every SturdyRef has its own restorer API then an RPC implementation won't
> know how to authenticate to it when the user does something like:
>
> liveRef := sturdyRef.getRcvr()
>
> Is this restorer API specified somewhere? The Python docs mention an
> *ez_restore* method and say "Refer to the Cap’n Proto docs if you don’t
> know what this means", but it's not clear to me what I should be looking at.
>
> For now, my SturdyRefs can only refer to bootstrap services.
>
> Also, I couldn't find much about authentication.
> https://capnproto.org/rpc.html#encryption says:
>
> At this time, Cap’n Proto does not specify an encryption scheme, but as it
>> is a simple byte stream protocol, it can easily be layered on top of
>> SSL/TLS or other such protocols.
>>
>
> For now, I have used TLS with self-signed non-expiring certificates (just
> as a container for the public key) and a validator that checks a hash of
> the server key fingerprint. My SturdyRefs convert to URIs that currently
> look like this:
>
>   capnp://sha-256:s16WV4JeGusAL_nTjvICiQOFqm3LqYrDj3K-HXdMi8s@
> 127.0.0.1:7000
>
> (based on the format at http://iiw.idcommons.net/
> HTTPSY_%E2%80%93_Leave_the_Certificate_Authority_Behind)
>
> However, https://capnproto.org/roadmap.html says:
>
> Cap’n Proto RPC should support an encrypted transport which uses
>> capability-based authorization (not PKI), can accomplish zero-round-trip
>> three-party introductions (via a pre-shared key from the introducer) and
>> based on modern crypto. TLS is not designed for this, but we don’t want to
>> invent new crypto; we intend to build on libsodium and the Noise Protocol
>> Framework as much as possible.
>>
>
> For interoperability, I allowed "insecure@" to disable encryption. e.g.
> to connect my OCaml client to the C++ calculator service I can use:
>
>   capnp://[email protected]:7000
>
> I treat an empty host:port section as requesting a Unix-domain socket, e.g.
>
>   capnp://insecure@/tmp/calc
>
> It's a bit of a hack, but I'm not sure what would be better.
>
> Things I'd like to know:
>
> - Do any other implementations support authentication or encryption?
>
> - Has anyone else defined a URI format I can use for sturdy refs?
>
> - Where in the URI should I put the service ID for the restorer server?
>
> - Is there a spec defining what a StudyRef and restorer service should
> look like for the default public Internet?
>   If not, is there anything obvious I should change in my current
> implementation to match what this will look like?
>
> Thanks,
>
> --
> You received this message because you are subscribed to the Google Groups
> "Cap'n Proto" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> Visit this group at https://groups.google.com/group/capnproto.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to