Hi,

We have been struggling to get a decorator working for proposed new RBAC 
functionality in ceilometer-api.  We're hitting a problem where GET request 
query parameters are mucked up by our decorator.  Here's an example call:

curl -H "X-Auth-Token:$TOKEN" 
'http://localhost:8777/v2/meters?q.field=project_id&q.value=8c678720fb5b4e3bb18dee222d7d7933'

And here's the decorator method (we've tried changing the kwargs, args, etc. 
with no luck):

_ENFORCER = None

def protected(controller_class):

    global _ENFORCER
    if not _ENFORCER:
        _ENFORCER = policy.Enforcer()

    def wrapper(f):
        @functools.wraps(f)
        def inner(self, **kwargs):
            pdb.set_trace()
            self._rbac_context = {}
            if not _ENFORCER.enforce('context_is_admin',
                                     {},
                                     {'roles': 
pecan.request.headers.get('X-Roles', "").split(",")}):
                self._rbac_context['project_id'] = 
pecan.request.headers.get('X-Project-Id')
                self._rbac_context['user_id'] = 
pecan.request.headers.get('X-User-Id')
            return f(self, **kwargs)
        return inner
    return wrapper

tried this too:

_ENFORCER = None

def protected(*args):

    controller_class = 'meter'
    global _ENFORCER
    if not _ENFORCER:
        _ENFORCER = policy.Enforcer()

    def wrapper(f, *args):
        def inner(self, *args):
            pdb.set_trace()
#            self._rbac_context = {}
#            if not _ENFORCER.enforce('context_is_admin',
#                                     {},
#                                     {'roles': 
pecan.request.headers.get('X-Roles', "").split(",")}):
#                self._rbac_context['project_id'] = 
pecan.request.headers.get('X-Project-Id')
#                self._rbac_context['user_id'] = 
pecan.request.headers.get('X-User-Id')
            #return f(*args)
            f(self, *args)
        return inner
    return wrapper

and here's how it's used:

class MetersController(rest.RestController):
    """Works on meters."""

    _rbac_context = {}
    @pecan.expose()
    def _lookup(self, meter_name, *remainder):
        return MeterController(meter_name), remainder

    @wsme_pecan.wsexpose([Meter], [Query])
    @rbac_validate.protected('meters')
    def get_all(self, q=None):
        """Return all known meters, based on the data recorded so far.

        :param q: Filter rules for the meters to be returned.
        """
        q = q or [] ...


but we get errors similar to below where the arg parser cannot find the query 
parameter because the decorator doesn't take a q argument as 
MetersController.get_all does.

Is there any way to get a decorator to work within the v2 API code and wsme 
framework or should we consider another approach?  Decorators would really 
simplify the RBAC idea we're working on, which is mostly code-implemented save 
for this fairly major problem.

I have a WIP registered BP on this at 
https://blueprints.launchpad.net/ceilometer/+spec/ready-ceilometer-rbac-keystone-v3.

If I can provide more details I'll be happy to.

Thanks
Eric

  /usr/local/bin/ceilometer-api(10)<module>()
-> sys.exit(api())
  /opt/stack/ceilometer/ceilometer/cli.py(96)api()
-> srv.serve_forever()
  /usr/lib/python2.7/SocketServer.py(227)serve_forever()
-> self._handle_request_noblock()
  /usr/lib/python2.7/SocketServer.py(284)_handle_request_noblock()
-> self.process_request(request, client_address)
  /usr/lib/python2.7/SocketServer.py(310)process_request()
-> self.finish_request(request, client_address)
  /usr/lib/python2.7/SocketServer.py(323)finish_request()
-> self.RequestHandlerClass(request, client_address, self)
  /usr/lib/python2.7/SocketServer.py(638)__init__()
-> self.handle()
  /usr/lib/python2.7/wsgiref/simple_server.py(124)handle()
-> handler.run(self.server.get_app())
  /usr/lib/python2.7/wsgiref/handlers.py(85)run()
-> self.result = application(self.environ, self.start_response)
  
/opt/stack/python-keystoneclient/keystoneclient/middleware/auth_token.py(663)__call__()
-> return self.app(env, start_response)
  /opt/stack/ceilometer/ceilometer/api/app.py(97)__call__()
-> return self.v2(environ, start_response)
  
/usr/local/lib/python2.7/dist-packages/pecan/middleware/static.py(151)__call__()
-> return self.app(environ, start_response)
  
/usr/local/lib/python2.7/dist-packages/pecan/middleware/debug.py(289)__call__()
-> return self.app(environ, start_response)
  
/usr/local/lib/python2.7/dist-packages/pecan/middleware/recursive.py(56)__call__()
-> return self.application(environ, start_response)
  /opt/stack/ceilometer/ceilometer/api/middleware.py(83)__call__()
-> app_iter = self.app(environ, replacement_start_response)
  /usr/local/lib/python2.7/dist-packages/pecan/core.py(750)__call__()
-> return super(Pecan, self).__call__(environ, start_response)
  /usr/local/lib/python2.7/dist-packages/pecan/core.py(616)__call__()
-> self.invoke_controller(controller, args, kwargs, state)
  /usr/local/lib/python2.7/dist-packages/pecan/core.py(526)invoke_controller()
-> result = controller(*args, **kwargs)
  /usr/local/lib/python2.7/dist-packages/wsmeext/pecan.py(79)callfunction()
-> pecan.request.body, pecan.request.content_type
  /usr/local/lib/python2.7/dist-packages/wsme/rest/args.py(276)get_args()
-> from_args = args_from_args(funcdef, args, kwargs)
> /usr/local/lib/python2.7/dist-packages/wsme/rest/args.py(189)args_from_args()
-> funcdef.get_arg(argname).datatype, value

_______________________________________________
OpenStack-dev mailing list
OpenStack-dev@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

Reply via email to