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

Pendergrass, Eric eric.pendergrass at hp.com
Thu Aug 14 16:38:37 UTC 2014


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 6242 bytes
Desc: not available
URL: <http://lists.openstack.org/pipermail/openstack-dev/attachments/20140814/7bf47ccc/attachment-0001.bin>


More information about the OpenStack-dev mailing list