[openstack-dev] [Ceilometer] Way to get wrapped method's name/class using Pecan secure decorators?

Doug Hellmann doug at doughellmann.com
Thu Aug 21 12:48:23 UTC 2014


On Aug 20, 2014, at 2:43 PM, Pendergrass, Eric <eric.pendergrass at hp.com> wrote:

> Hi Ryan,
> 
> We tried globally applying the hook but could not get execution to enter the
> hook class. 
> 
> Perhaps we made a mistake, but we concluded the Controller still had to
> inherit from HookController using the project-wide method.  Otherwise we
> would have been satisfied applying it project-wide.

Ceilometer already has a couple of other hooks installed (for example, to provide the database handle) and those do work. I assume you followed them as examples?

Doug

> 
> Thanks,
> Eric
> 
>> Eric,
> 
>> 
>> Doug's correct - this looks like a bug in pecan that occurs when you
> subclass both rest.RestController and hooks.HookController.  I'm working on
> a bug fix as we speak.  In the meantime, have you tried applying hooks at a
> global application level?  This approach should still work.
>> 
>> On 08/14/14 04:38 PM, Pendergrass, Eric wrote:
>>> Sure, Doug.  We want the ability to selectively apply policies to 
>>> certain Ceilometer API methods based on user/tenant roles.
>>> 
>>> For example, we want to restrict the ability to execute Alarm deletes 
>>> to admins and user/tenants who have a special role, say "domainadmin".
>>> 
>>> The policy file might look like this:
>>> {
>>>    "context_is_admin":  [["role:admin"]],
>>>    "admin_and_matching_project_domain_id":  [["role:domainadmin"]],
>>>    "admin_or_cloud_admin": [["rule:context_is_admin"], 
>>> ["rule:admin_and_matching_project_domain_id"]],
>>>    "telemetry:delete_alarms":  [["rule:admin_or_cloud_admin"]] }
>>> 
>>> The current acl.py and _query_to_kwargs access control setup either 
>>> sets project_id scope to None (do everything) or to the project_id in 
>>> the request header 'X-Project-Id'.  This allows for admin or project 
>>> scope, but nothing in between.
>>> 
>>> We tried hooks.  Unfortunately we can't seem to turn the API 
>>> controllers into HookControllers just by adding HookController to the 
>>> Controller class definition.  It causes infinite recursion on API 
>>> startup.  For example, this doesn't work because ceilometer-api will 
>>> not start with it:
>>>    class MetersController(rest.RestController, HookController):
>>> 
>>> If there was a way to use hooks with the v2. API controllers that 
>>> might work really well.
>>> 
>>> So we are left using the @secure decorator and deriving the method 
>>> name from the request environ PATH_INFO and REQUEST_METHOD values.  
>>> This is how we determine the wrapped method within the class 
>>> (REQUEST_METHOD + PATH_INFO = "telemetry:delete_alarms" with some 
>>> munging).  We need the method name in order to selectively apply acces 
>>> control to certain methods.
>>> 
>>> Deriving the method this way isn't ideal but it's the only thing we've 
>>> gotten working between hooks, @secure, and regular decorators.
>>> 
>>> I submitted a WIP BP here: https://review.openstack.org/#/c/112137/3.  
>>> It is slightly out of date but should give you a beter idea of our
> goals.
>>> 
>>> Thanks
>>> 
>>>> Eric,
>>>> 
>>>> If you can give us some more information about your end goal, 
>>>> independent
>>> of the implementation, maybe we can propose an alternate technique to 
>>> achieve the same thing.
>>>> 
>>>> Doug
>>>> 
>>>> On Aug 12, 2014, at 6:21 PM, Ryan Petrello 
>>>> <ryan.petrello at dreamhost.com>
>>> wrote:
>>>> 
>>>>> Yep, you're right, this doesn't seem to work.  The issue is that 
>>>>> security is enforced at routing time (while the controller is 
>>>>> still actually being discovered).  In order to do this sort of 
>>>>> thing with the `check_permissions`, we'd probably need to add a
> feature to pecan.
>>>>> 
>>>>> On 08/12/14 06:38 PM, Pendergrass, Eric wrote:
>>>>>> Sure, here's the decorated method from v2.py:
>>>>>> 
>>>>>>   class MetersController(rest.RestController):
>>>>>>       """Works on meters."""
>>>>>> 
>>>>>>       @pecan.expose()
>>>>>>       def _lookup(self, meter_name, *remainder):
>>>>>>           return MeterController(meter_name), remainder
>>>>>> 
>>>>>>       @wsme_pecan.wsexpose([Meter], [Query])
>>>>>>       @secure(RBACController.check_permissions)
>>>>>>       def get_all(self, q=None):
>>>>>> 
>>>>>> and here's the decorator called by the secure tag:
>>>>>> 
>>>>>>   class RBACController(object):
>>>>>>       global _ENFORCER
>>>>>>       if not _ENFORCER:
>>>>>>           _ENFORCER = policy.Enforcer()
>>>>>> 
>>>>>> 
>>>>>>       @classmethod
>>>>>>       def check_permissions(cls):
>>>>>>           # do some stuff
>>>>>> 
>>>>>> In check_permissions I'd like to know the class and method with 
>>>>>> the
>>> @secure tag that caused check_permissions to be invoked.  In this 
>>> case, that would be MetersController.get_all.
>>>>>> 
>>>>>> Thanks
>>>>>> 
>>>>>> 
>>>>>>> Can you share some code?  What do you mean by, "is there a way 
>>>>>>> for the
>>> decorator code to know it was called by MetersController.get_all"
>>>>>>> 
>>>>>>> On 08/12/14 04:46 PM, Pendergrass, Eric wrote:
>>>>>>>> Thanks Ryan, but for some reason the controller attribute is
> None:
>>>>>>>> 
>>>>>>>> (Pdb) from pecan.core import state
>>>>>>>> (Pdb) state.__dict__
>>>>>>>> {'hooks': [<ceilometer.api.hooks.ConfigHook object at 
>>>>>>>> 0x31894d0>, <ceilometer.api.hooks.DBHook object at 0x3189650>,
> 
>>>>>>>> <ceilometer.api.hooks.PipelineHook object at 0x39871d0>, 
>>>>>>>> <ceilometer.api.hooks.TranslationHook object at 0x3aa5510>],
> 'app':
>>>>>>>> <pecan.core.Pecan object at 0x2e76390>, 'request': <Request at
>>>>>>>> 0x3ed7390 GET http://localhost:8777/v2/meters>, 'controller': 
>>>>>>>> None,
>>>>>>>> 'response': <Response at 0x3ed74d0 200 OK>}
>>>>>>>> 
>>>>>>>>> -----Original Message-----
>>>>>>>>> From: Ryan Petrello [mailto:ryan.petrello at dreamhost.com]
>>>>>>>>> Sent: Tuesday, August 12, 2014 10:34 AM
>>>>>>>>> To: OpenStack Development Mailing List (not for usage 
>>>>>>>>> questions)
>>>>>>>>> Subject: Re: [openstack-dev] [Ceilometer] Way to get wrapped
>>> method's name/class using Pecan secure decorators?
>>>>>>>>> 
>>>>>>>>> This should give you what you need:
>>>>>>>>> 
>>>>>>>>> from pecan.core import state
>>>>>>>>> state.controller
>>>>>>>>> 
>>>>>>>>> On 08/12/14 04:08 PM, Pendergrass, Eric wrote:
>>>>>>>>>> Hi, I'm trying to use the built in secure decorator in
> Pecan 
>>>>>>>>>> for
>>> access control, and I'ld like to get the name of the method that is 
>>> wrapped from within the decorator.
>>>>>>>>>> 
>>>>>>>>>> For instance, if I'm wrapping MetersController.get_all
> with 
>>>>>>>>>> an
>>> @secure decorator, is there a way for the decorator code to know it 
>>> was called by MetersController.get_all?
>>>>>>>>>> 
>>>>>>>>>> I don't see any global objects that provide this
> information.  
>>>>>>>>>> I
>>> can get the endpoint, v2/meters, with pecan.request.path, but that's 
>>> not as elegant.
>>>>>>>>>> 
>>>>>>>>>> Is there a way to derive the caller or otherwise pass this
>>> information to the decorator?
>>>>>>>>>> 
>>>>>>>>>> Thanks
>>>>>>>>>> Eric Pendergrass
>>>>>>>>> 
>>>>>>>>>> _______________________________________________
>>>>>>>>>> OpenStack-dev mailing list
>>>>>>>>>> OpenStack-dev at lists.openstack.org 
>>>>>>>>>> 
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack
>>>>>>>>>> -dev
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> --
>>>>>>>>> Ryan Petrello
>>>>>>>>> Senior Developer, DreamHost
>>>>>>>>> ryan.petrello at dreamhost.com
>>>>>> 
>>>>>> _______________________________________________
>>>>>> OpenStack-dev mailing list
>>>>>> OpenStack-dev at lists.openstack.org 
>>>>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>>>> 
>>>>> --
>>>>> Ryan Petrello
>>>>> Senior Developer, DreamHost
>>>>> ryan.petrello at dreamhost.com
>>>>> 
>>>>> _______________________________________________
>>>>> OpenStack-dev mailing list
>>>>> OpenStack-dev at lists.openstack.org
>>>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>>> 
>>>> 
>>>> _______________________________________________
>>>> OpenStack-dev mailing list
>>>> OpenStack-dev at lists.openstack.org
>>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>> 
>> 
>> 
>>> _______________________________________________
>>> OpenStack-dev mailing list
>>> OpenStack-dev at lists.openstack.org
>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>> 
>> 
>> --
>> Ryan Petrello
>> Senior Developer, DreamHost
>> ryan.petrello at dreamhost.com
>> 
>> _______________________________________________
>> OpenStack-dev mailing list
>> OpenStack-dev at lists.openstack.org
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
> _______________________________________________
> OpenStack-dev mailing list
> OpenStack-dev at lists.openstack.org
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev




More information about the OpenStack-dev mailing list