Re: [Python-Dev] Re: Capabilities
(I, Zooko, wrote the lines prepended with "> > ".) Guido wrote:
The [Principle-of-Least-Privilege approach to securing a standard library] is to separate the tools so that dangerous ones don't come tied together with common ones. The security policy, then, is expressed by code that grants or withholds capabilities (== references) rather than by code that toggles the "restricted" bit.
This sounds interesting, but I'm not sure I follow it. Can you elaborate by giving a couple of examples?
First let me say that "capability access control" [1] is a theoretical construct, comparable to "access control lists" [2] and "Trust Management" [3]. Each is a formal model for specifying access control rules -- who is allowed to do what. But in the context of Python we are interested not only in the theoretical model but also in a specific way of implementing it -- by making object references unforgeable and binding all authorities to object references. So in this discussion it may not be clear whether a claimed advantage of "capabilities" flows from the formal model or from the practice of unifying security programming with object oriented programming. I don't think it is important to differentiate in this discussion. Now for examples... Hm, well first of all, where are rexec and Zope proxies currently used? I believe that a "cap-Python" would support those uses, implementing the same security policies, but more cleanly since access control would be a first-class part of the language. I don't know Zope very well, and rather than guess, I'd like to ask someone who does know Zope to give a typical example of how proxies are used in workaday Zope. I suspect that capabilities are quite similar to Zope proxies. Now for a quick made-up example to demonstrate what I meant about expressing security policy above, consider a tic-tac-toe game that is supposed to draw to the screen. In "restricted Python v1", certain modules have been flagged as "safe" and others "unsafe". Code can execute other code with a "restricted" flag set, something like this: # restricted Python v1 game = eval(TicTacToeGame, restricted=True) game.display() Unfortunately, in "restricted Python v1", all of the modules that allow drawing to the screen are marked as "unsafe", so the tic-tac-toe-game immediately dies with an exception. In "restricted Python v2", an arbitrary security policy can be implemented: # restricted Python v2 games=[] def securitypolicy(subject, action, object): if ((subject in games) and (action == "import") and (object == "wxPython")) or (subject in games) and (action == "execute") and (object == "wxPython.Window") or (subject in games) and (action == "execute") and (object == "wxPython.Window.paint")): return True # ... return False game = eval(TicTacToeGame, policy=securitypolicy) gameobjh.append(game) game.display() I think that the "rexec" design was along the lines of "restricted Python v2", but I apologize if this simple analogy insults anyone. I'm not sure whether "restricted Python v2" is expressive enough to implement the capability security access control model or not, but I don't care, because I don't like "restricted Python v2". I like restricted Python v3: # restricted Python v3 game = TicTacToeGame() game.display(wxPython.wxWindow()) Now the game object has a reference to the window object, and it can use that reference to draw the pictures. If I later change this design and decide that instead of drawing to a window, I want the game to write to a file, then I'll change the implementation of the TicTacToeGame class, and then'll I'll come back here to this code and change it from passing a wxWindows to: # restricted Python v3 game = TicTacToeGame() game.display(open("/tmp/tttgame.out","w")) Now if I were writing in "restricted Python v2", then in addition to those two changes I would also have to make a third change, which is to edit my securitypolicy function in order to allow this particular game object to access a file named "/tmp/tttgame.out", and to disallow it access to wxPython: # restricted Python v2 def securitypolicy(subject, action, object): if (subject in games) and (action in ("read", "write",)) and (object == "file:/tmp/tttgame.out"): return True # ... return False game = TicTacToeGame() game.display("/tmp/tttgame.out") This is what I meant by saying that the security policy is expressed in Python instead of by twiddling access bits in an embedded policy language. In a capability-secure language, the change (which the programmer has to make anyway), from "wxPython.wxWindows()" to "open('/tmp/tttgame.out', 'w')" is necessary and sufficient to enforce the programmer's intended security policy, so there is no need for the redundant and brittle "policy" function. I find this unification access control and application logic to resonate deeply with the Zen of Python. Regards, Zooko [1] http://www.eros-os.org/papers/shap-thesis.ps [2] http://www.research.microsoft.com/~lampson/09-Protection/Acrobat.pdf [3] http://citeseer.nj.nec.com/blaze96decentralized.html
(Zooko, would it kill you to keep your line lengths well below 79?) [Zooko]
The [Principle-of-Least-Privilege approach to securing a standard library] is to separate the tools so that dangerous ones don't come tied together with common ones. The security policy, then, is expressed by code that grants or withholds capabilities (== references) rather than by code that toggles the "restricted" bit.
[Guido]
This sounds interesting, but I'm not sure I follow it. Can you elaborate by giving a couple of examples?
[Zooko]
First let me say that "capability access control" [1] is a theoretical construct, comparable to "access control lists" [2] and "Trust Management" [3]. Each is a formal model for specifying access control rules -- who is allowed to do what.
But in the context of Python we are interested not only in the theoretical model but also in a specific way of implementing it -- by making object references unforgeable and binding all authorities to object references.
So in this discussion it may not be clear whether a claimed advantage of "capabilities" flows from the formal model or from the practice of unifying security programming with object oriented programming. I don't think it is important to differentiate in this discussion.
Now for examples...
Hm, well first of all, where are rexec and Zope proxies currently used? I believe that a "cap-Python" would support those uses, implementing the same security policies, but more cleanly since access control would be a first-class part of the language.
I don't know Zope very well, and rather than guess, I'd like to ask someone who does know Zope to give a typical example of how proxies are used in workaday Zope. I suspect that capabilities are quite similar to Zope proxies.
Yes.
Now for a quick made-up example to demonstrate what I meant about expressing security policy above, consider a tic-tac-toe game that is supposed to draw to the screen.
In "restricted Python v1", certain modules have been flagged as "safe" and others "unsafe". Code can execute other code with a "restricted" flag set, something like this:
# restricted Python v1 game = eval(TicTacToeGame, restricted=True) game.display()
Unfortunately, in "restricted Python v1", all of the modules that allow drawing to the screen are marked as "unsafe", so the tic-tac-toe-game immediately dies with an exception.
In "restricted Python v2", an arbitrary security policy can be implemented:
# restricted Python v2 games=[] def securitypolicy(subject, action, object): if ((subject in games) and (action == "import") and (object == "wxPython")) or (subject in games) and (action == "execute") and (object == "wxPython.Window") or (subject in games) and (action == "execute") and (object == "wxPython.Window.paint")): return True # ... return False
game = eval(TicTacToeGame, policy=securitypolicy) gameobjh.append(game) game.display()
I think that the "rexec" design was along the lines of "restricted Python v2", but I apologize if this simple analogy insults anyone.
Not really. The rexec design gives you the tools to implement either v1, v2 or v3. Its basic features are more like v1, but it has a concept of Zope-like proxies, named Bastions, and it allows you to use functions or bound methods as capabilities. Bastions are mostly a convenience to allow a bunch of capabilities to be used like an object. The "security policy" you sketch as part of v2 would be possible but there aren't really any hooks to implement this; you'd have to craft it out of Bastions and capabilities.
I'm not sure whether "restricted Python v2" is expressive enough to implement the capability security access control model or not, but I don't care, because I don't like "restricted Python v2". I like restricted Python v3:
# restricted Python v3 game = TicTacToeGame() game.display(wxPython.wxWindow())
Now the game object has a reference to the window object, and it can use that reference to draw the pictures. If I later change this design and decide that instead of drawing to a window, I want the game to write to a file, then I'll change the implementation of the TicTacToeGame class, and then'll I'll come back here to this code and change it from passing a wxWindows to:
# restricted Python v3 game = TicTacToeGame() game.display(open("/tmp/tttgame.out","w"))
Now if I were writing in "restricted Python v2", then in addition to those two changes I would also have to make a third change, which is to edit my securitypolicy function in order to allow this particular game object to access a file named "/tmp/tttgame.out", and to disallow it access to wxPython:
# restricted Python v2 def securitypolicy(subject, action, object): if (subject in games) and (action in ("read", "write",)) and (object == "file:/tmp/tttgame.out"): return True # ... return False
game = TicTacToeGame() game.display("/tmp/tttgame.out")
This is what I meant by saying that the security policy is expressed in Python instead of by twiddling access bits in an embedded policy language. In a capability-secure language, the change (which the programmer has to make anyway), from "wxPython.wxWindows()" to "open('/tmp/tttgame.out', 'w')" is necessary and sufficient to enforce the programmer's intended security policy, so there is no need for the redundant and brittle "policy" function.
I find this unification access control and application logic to resonate deeply with the Zen of Python.
Me too.
Regards,
Zooko
[1] http://www.eros-os.org/papers/shap-thesis.ps [2] http://www.research.microsoft.com/~lampson/09-Protection/Acrobat.pdf [3] http://citeseer.nj.nec.com/blaze96decentralized.html
--Guido van Rossum (home page: http://www.python.org/~guido/)
Zooko wrote:
I suspect that capabilities are quite similar to Zope proxies.
If I understand them correctly, a Zope proxy where the security checker always says "yes" is a capability. Except, possibly, they may be forgeable, I don't know them well enough to know. Cheers, Ben. -- http://www.apache-ssl.org/ben.html http://www.thebunker.net/ "There is no limit to what a man can do or how far he can go if he doesn't mind who gets the credit." - Robert Woodruff
Ben Laurie
If I understand them correctly, a Zope proxy where the security checker always says "yes" is a capability. Except, possibly, they may be forgeable, I don't know them well enough to know.
A security checker that could be easily forged wouldn't be very, er, secure, would it?-) Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Greg Ewing wrote:
Ben Laurie
: If I understand them correctly, a Zope proxy where the security checker always says "yes" is a capability. Except, possibly, they may be forgeable, I don't know them well enough to know.
A security checker that could be easily forged wouldn't be very, er, secure, would it?-)
Its the proxy that needs to be unforgeable. And since their model is role-based, I assume its not a fundamental requirement for them. Cheers, Ben. -- http://www.apache-ssl.org/ben.html http://www.thebunker.net/ "There is no limit to what a man can do or how far he can go if he doesn't mind who gets the credit." - Robert Woodruff
participants (4)
-
Ben Laurie
-
Greg Ewing
-
Guido van Rossum
-
Zooko