controlling method execution

Robert Brewer fumanchu at amor.org
Thu Nov 20 18:41:04 CET 2003


It depends on what you mean by 'users'. If you're trying to secure your
Python code from other Python code, good luck. If you're simply trying
to include an authorization step in an interface you have 'complete'
control over, then you have more options.

For the object server I'm currently working on, I combined two neat
Python tricks to create a fairly workable solution. I wanted a mechanism
to lock down any method on any primitive object which the server
manages; in my case, such objects (which I call 'Units') are class
instances. Each Unit has a secure() method which does the actual calls
to the security module. The security module can 'lock' a Unit instance
method by the process:

1. Obtain a reference to the method ('aResource', below), and a 'Lock'
instance.
2. Rename the existing method (e.g. by prefixing the string '_locked_'
to the method name).
3. Create a new method which performs a permission lookup, binding it to
the instance using the old method name.

Here's the function which locks methods:

    def _lock_method(self, aLock, aResource):
        """Create an authorization wrapper for an instance method."""
        resourcename = aResource.__name__
        mySecurityManager = self
        
        def locked_method(self, *args, **kwargs):
            """Check permissions on a locked method."""
            mySecurityManager.attempt(aLock)
            return apply(self.__dict__[u'_locked_%s' % resourcename],
                         args, kwargs)
        
        # Bind the existing function to a new name.
        # Then bind the old name to our wrapper function.
        anInstance = aResource.im_self
        anInstance.__dict__[u'_locked_%s' % resourcename] = aResource
        lm = new.instancemethod(locked_method, anInstance,
                                anInstance.__class__)
        anInstance.__dict__[resourcename] = lm

One of the nice features of this technique is that Units and methods
which do not need locks incur no overhead of the locking code--it's
added on only when you need it.

The second neat trick (IMO ;), is the use of dynamic attribute creation
on threading.currentThread(). I have a UI class heirarchy (subclasses
for HTML, XML, wxPython, etc.), which has a 'user' attribute. Whenever a
new UI is instantiated, I stick a reference to it in currentThread():

import threading
class UserInterfaceHTML(ui.UserInterface):
    """A base class for HTML interfaces."""
    
    def __init__(self):
        threading.currentThread().UI = self

This is wonderful, because it saves having to pass the username and/or
ACL's around during intermediate methods on my way to the locked method.
That information is always available in currentThread(). In
locked_method(), above, there is a call made to .attempt(), which looks
like this (in a capability-style model):

    def attempt(self, aLock):
        """Test permission on a lock."""
        UI = threading.currentThread().UI
        if aLock.hash in self._get_tokens(UI.user):
            return
        else:
            raise errors.AccessDeniedError



Hope that gives you some ideas, even if the code is from a relative
newbie. I'm sure I didn't explain it half as well as I should have.


Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org

> -----Original Message-----
> From: mic [mailto:aldo123 at onet.pl] 
> Sent: Thursday, November 20, 2003 12:37 AM
> To: python-list at python.org
> Subject: controlling method execution
> 
> 
> Is it possible to control method exectution using similiar 
> mechanism as with
> get/setatrribute special methods for attributes? I'd like to 
> have every (or
> some of ) method of class instance run common code defined 
> outside the class
> without making any explicit references to it.
> To give an example, I'd like to prepare secure environment, 
> in which users
> could execute only methods that can be accessed by them. IMO the most
> universal way to do it would be to run automatically 
> authorisation routine
> before every method execution.
> 
> Regards,
> 
> Michal
> 
> 
> -- 
> http://mail.python.org/mailman/listinfo/python-list
> 





More information about the Python-list mailing list