Ka-Ping Yee wrote:
Ben Laurie wrote:
BTW, if you would like to explain why you don't think bound methods are the way to go on python-dev, I'd love to hear it.
Guido van Rossum wrote:
Using capabilities, I would have to hand her a bunch of capabilities for various methods: __getitem__, has_key, get, keys, items, values, and many more. Using proxies I can simply give her a read-only proxy for the object. So proxies are more powerful.
I'm pretty sure that Guido meant to say "bound method" rather than "capability" in the text above. I think that the debate is partly whether to express capabilities (or some other scheme) in terms of bound methods or proxies, which expose entire interfaces.
There seems to be a persistent confusion here that i would like to dispel: a capability is not a single lambda.
There are a bunch of confusions floating around. :) A major one is a concise definition os what a capability and why the capability approach is good or bad.
In reading about capabilities in E, http://www.erights.org/. I really need to read all that stuff again. Of course, as others pointed out, I ended up creating something for Zope 3 that isn't capabilities. I think you touch on a reason below.
Guido's paragraph, above, seems to believe that it is. In fact, the pattern he described is a common and powerful way of using capabilities. A capability is just an unforgeable object reference. In a pure capability system, the only thing you can do with a capability is to call methods on it (or, if you prefer, all you can do is send messages to it). Interposing an object to expose only a subset of another object's API, such as a read-only subset, is exactly the power capabilities give you.
It seems to me that the "rexec vs. proxy" debate is really about a very different question: How do we get from Python's currently promiscuous objects to properly restricted objects?
(Once we have properly restricted objects in either fashion, yes, definitely, using proxies to restrict access is a great technique.)
If i understand correctly, the "proxy" answer is "we create a special wrapper object, then the programmer has to individually wrap any object they want to be secure". And the "rexec" answer is "we create an interpreter mode in which all objects are secure".
I think the latter is far better. To have any sort of real chance at establishing security, you have to start from a place where everything is secure, instead of starting from a place where everything is insecure and you have to individually secure every single object with its own wrapper.
The eventual ideal is to have a system where all objects are "pure" objects (i.e. non-introspectable capabilities) by default. Anyone wanting to do introspection would simply have to obtain the "introspect" capability from a privileged place (e.g. sys). For example,
class Foo: pass print Foo.__dict__ # fails from sys import introspect print introspect(Foo).__dict__ # succeeds
When running the interpreter in secure mode, "introspect" would just be missing from the sys module (again, ideally sys.introspect wouldn't exist by default, and a command-line option would turn it on, but i realize that's far away).
This would have the effect of the "introspectable flag" that Guido mentioned, but without expending any storage at all, until you actually needed to introspect something.
You seem to be arguing that programmers should not have to explictly create capabilities, but that everythink should be a capability by default. Please correct me if I'm wrong.
I thought that the main point of capabilities was that programmers *should* explictly bother to pass capabilities. Programmers should think about arguments passed to (or returned or raised to) other code as capabilities to do things and pass *just* the capabilities needed. I find a lot of appeal in this idea.
Zope employs proxies in a way that falls somewhere between the extremes of capabilities and implicitly protecting everything.
(I'm going to be a little sloppy hear for brevity. A Zope proxy is made up of two objects, a simple proxy that *could* be used to implement capabilities and a checker that provides policy. The policy we currently use in Zope is not a capability policy.)
Zope security proxies assure that "everything" is proxied. (We choose not to proxy simple valies like numbers, strings, and None.) Values returned from operations on proxied. This maked it pretty straightforward to set up execution environments where untrusted code only has access to proxies. In addition, if untrusted code calls trusted code, the untrusted code can only pass proxies. This means that trusted code can't be tricked into performing operations that the untrusted code could not perform. Zope proxies achiev this level of automation by providing registries, mostly based on classes, that allow programmers to say how different kinds of objects should be proxied. Programmers decide what capabilities to expose at "compile" time (really program startup) rather than run time. Programmers *can* create proxies explicitly that provides non-default access. In fact, there are apis that actually provide the the equivalent of capabilities.
I mention all of this because I think it's worth thinking/debating this issue about how explicit security should be. On the one hand, explictly giving *just* the capabilities needed for a task seems very appealing. OTOH, making sure that everything is protected by default is safer. I suspect that there are ways to combine (trade off?) these in reasonable ways.