Commit 46653ed4 authored by Anael Beutot's avatar Anael Beutot
Browse files

Actually implement permission checking for RPC handlers

parent 95744f5a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -75,3 +75,8 @@ class JobError(CCNodeError):
class RemoteExecutionError(CCNodeError):
    """Thrown when a remote command execution error occurs."""
    pass


class ForbiddenHandler(CCNodeError):
    """Raised when a handler is called but disabled by configuration."""
    pass
+27 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
import os
import logging
import logging.config
from functools import wraps

from cloudcontrol.common.client.loop import RPCStartHandler, MainLoop
from cloudcontrol.common.client.tags import Tag
@@ -24,11 +25,32 @@ from cloudcontrol.common.client.tags import Tag
from cloudcontrol.node import __version__
from cloudcontrol.node.config import NodeConfigParser, configure_logging
from cloudcontrol.node.jobs import JobManager
from cloudcontrol.node.exc import ForbiddenHandler


logger = logging.getLogger(__name__)


def _rights_check(handler_name):
    """Method instance decorator for checking permissions before executing an
    RPC handler.

    """
    def decorator(func):
        @wraps(func)
        def decorated(*args, **kwargs):
            if handler_name in func.im_self.main.config.forbidden_handlers:
                logger.error('Remote tried to call forbidden handler "%s"',
                             handler_name)
                raise ForbiddenHandler('Forbidden handler "%s"' % handler_name)

            return func(*args, **kwargs)

        return decorated

    return decorator


class NodeRPCStartHandler(RPCStartHandler):
    def handle_authentication_response(self, response=None):
        # set handler according to which role was returned by the cc-server
@@ -85,6 +107,11 @@ class NodeLoop(MainLoop):
        MainLoop.__init__(self, config_path)
        self.job_manager = JobManager(self)

    def reset_handler(self, name, handl):
        # we decorate each handler for permissions to be checked before each
        # invocation
        MainLoop.reset_handler(self, name, _rights_check(name)(handl))

    def configure_logging(self):
        configure_logging(self.config.logging_level, self.config.logging_output)