[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