Beispiel #1
0
    def __init__(self):
        """ Constructor.
        """

        # Initialize stuff.
        self._config = NipapConfig()
        self._logger = logging.getLogger(self.__class__.__name__)
        self._init_backends()
Beispiel #2
0
    def __init__(self, username, password, authoritative_source, auth_backend, auth_options={}):
        """ Constructor.

            Note that the instance variables not are set by the constructor but
            by the :func:`authenticate` method. Therefore, run the
            :func:`authenticate`-method before trying to access those
            variables!

            * `username` [string]
                Username to authenticate as.
            * `password` [string]
                Password to authenticate with.
            * `authoritative_source` [string]
                Authoritative source of the query.
            * `auth_backend` [string]
                Name of authentication backend.
            * `auth_options` [dict]
                A dict which, if authenticated as a trusted user, can override
                `username` and `authoritative_source`.
        """

        self._logger = logging.getLogger(self.__class__.__name__)
        self._cfg = NipapConfig()

        self.username = username
        self.password = password
        self.auth_backend = auth_backend
        self.authoritative_source = authoritative_source

        self._auth_options = auth_options
Beispiel #3
0
    def __init__(self):
        """ Constructor.
        """

        # Initialize stuff.
        self._config = NipapConfig()
        self._logger = logging.getLogger(self.__class__.__name__)
        self._init_backends()
Beispiel #4
0
    def __init__(self, root_logger = None):
        self.logger = logging.getLogger(self.__class__.__name__)
        self.root_logger = root_logger

        self._cfg = NipapConfig()
        self.cfg_file = None

        # Add dispatch entry for <ex:nil/>
        xmlrpclib.Unmarshaller.dispatch["ex:nil"] = xmlrpclib.Unmarshaller.end_nil

        self.init()
Beispiel #5
0
class AuthFactory:
    """ An factory for authentication backends.
    """

    _logger = None
    _config = None
    _auth_cache = {}
    _backends = {}


    def __init__(self):
        """ Constructor.
        """

        # Initialize stuff.
        self._config = NipapConfig()
        self._logger = logging.getLogger(self.__class__.__name__)
        self._init_backends()



    def _init_backends(self):
        """ Initialize auth backends.
        """

        # fetch auth backends from config file
        self._backends = {}
        for section in self._config.sections():

            # does the section define an auth backend?
            section_components = section.rsplit('.', 1)
            if section_components[0] == 'auth.backends':
                auth_backend = section_components[1]
                self._backends[auth_backend] = eval(self._config.get(section, 'type'))

        self._logger.debug("Registered auth backends %s" % str(self._backends))



    def reload(self):
        """ Reload AuthFactory.
        """

        self._auth_cache = {}
        self._init_backends()



    def get_auth(self, username, password, authoritative_source, auth_options=None):
        """ Returns an authentication object.
    
            Examines the auth backend given after the '@' in the username and
            returns a suitable instance of a subclass of the BaseAuth class.

            * `username` [string]
                Username to authenticate as.
            * `password` [string]
                Password to authenticate with.
            * `authoritative_source` [string]
                Authoritative source of the query.
            * `auth_options` [dict]
                A dict which, if authenticated as a trusted user, can override
                `username` and `authoritative_source`.
        """

        if auth_options is None:
            auth_options = {}

        # validate arguments
        if (authoritative_source is None):
            raise AuthError("Missing authoritative_source.")

        # remove invalid cache entries
        rem = list()
        for key in self._auth_cache:
            if self._auth_cache[key]['valid_until'] < datetime.utcnow():
                rem.append(key)
        for key in rem:
            del(self._auth_cache[key])

        user_authbackend = username.rsplit('@', 1)
    
        # Find out what auth backend to use.
        # If no auth backend was specified in username, use default
        backend = ""
        if len(user_authbackend) == 1:
            backend = self._config.get('auth', 'default_backend')
            self._logger.debug("Using default auth backend %s" % backend)
        else:
            backend = user_authbackend[1]
    
        # do we have a cached instance?
        auth_str = ( str(username) + str(password) + str(authoritative_source)
            + str(auth_options) )
        if auth_str in self._auth_cache:
            self._logger.debug('found cached auth object for user %s' % username)
            return self._auth_cache[auth_str]['auth_object']

        # Create auth object
        try:
            auth = self._backends[backend](backend, user_authbackend[0], password, authoritative_source, auth_options)
        except KeyError:
            raise AuthError("Invalid auth backend '%s' specified" %
                str(backend))

        # save auth object to cache
        self._auth_cache[auth_str] = {
            'valid_until': datetime.utcnow() + timedelta(seconds=self._config.getint('auth', 'auth_cache_timeout')),
            'auth_object': auth
        }

        return auth
Beispiel #6
0
class NipapXMLRPC:

    stop = None
    _cfg = None
    _protocol = None
    root_logger = None

    def __init__(self, root_logger = None):
        self.logger = logging.getLogger(self.__class__.__name__)
        self.root_logger = root_logger

        self._cfg = NipapConfig()
        self.cfg_file = None

        # Add dispatch entry for <ex:nil/>
        xmlrpclib.Unmarshaller.dispatch["ex:nil"] = xmlrpclib.Unmarshaller.end_nil

        self.init()


    def init(self):
        """ Non Python init

            This init function should be called after the configuration has
            been read. It is a separate function from __init__ so that it may
            be called if the configuration file is reread when the daemon is
            running.
        """
        # we cannot switch between foreground and background here, so ignoring
        # 'foreground' option

        # syslog
        if self._cfg.getboolean('nipapd', 'syslog'):
            log_syslog = logging.handlers.SysLogHandler(address = '/dev/log')
            log_syslog.setFormatter(logging.Formatter("%(levelname)-8s %(message)s"))
            self.root_logger.addHandler(log_syslog)

        if self._cfg.getboolean('nipapd', 'foreground'):
            # log to stdout
            log_stream = logging.StreamHandler()
            log_stream.setFormatter(logging.Formatter("%(asctime)s: %(levelname)-8s %(message)s"))
            self.root_logger.addHandler(log_stream)
            self.root_logger.setLevel(logging.DEBUG)

        if self._cfg.getboolean('nipapd', 'debug'):
            self.root_logger.setLevel(logging.DEBUG)



    def run(self):
        """ Create the reactor and start it
        """

        # most signals are handled by Twisted by default but for SIGHUP to
        # behave as we want (ie, reload the configuration file) we need to
        # install a custom handler
        import signal
        signal.signal(signal.SIGHUP, self._sigHup)

        # setup twisted logging
        log.defaultObserver.stop()
        log.defaultObserver = None
        observer = log.PythonLoggingObserver()
        observer.start()

        # twist it!
        self._protocol = NipapProtocol()
        # listen on all interface
        if self._cfg.get('nipapd', 'listen') is None or self._cfg.get('nipapd', 'listen') == '':
            self.logger.info("Listening to all addresses on port " + self._cfg.getint('nipapd', 'port'))
            reactor.listenTCP(self._cfg.getint('nipapd', 'port'), server.Site(self._protocol))
        else:
            # If the used has listed specific addresses to listen to, loop
            # through them and start listening to them. It is possible to
            # specify port per IP by separating the address and port with a +
            # character.
            listen = self._cfg.get('nipapd', 'listen')
            for entry in listen.split(','):
                if len(entry.split('+')) > 1:
                    address = entry.split('+')[0]
                    port = int(entry.split('+')[1])
                else:
                    address = entry
                    port = int(self._cfg.get('nipapd', 'port'))
                self.logger.info("Listening to address " + address + " on port " + str(port))
                reactor.listenTCP(port, server.Site(self._protocol), interface=address)

        # finally, start the reactor!
        reactor.run()



    def _sigHup(self, num, frame):
        """ Customer signal handler for SIGHUP
        """
        self.logger.info("Received SIGHUP - reloading configuration")
        self._cfg.read_file()
        self._protocol._auth_fact.reload()
        self.init()
Beispiel #7
0
class AuthFactory:
    """ An factory for authentication backends.
    """

    _logger = None
    _config = None
    _auth_cache = {}
    _backends = {}

    def __init__(self):
        """ Constructor.
        """

        # Initialize stuff.
        self._config = NipapConfig()
        self._logger = logging.getLogger(self.__class__.__name__)
        self._init_backends()

    def _init_backends(self):
        """ Initialize auth backends.
        """

        # fetch auth backends from config file
        self._backends = {}
        for section in self._config.sections():

            # does the section define an auth backend?
            section_components = section.rsplit('.', 1)
            if section_components[0] == 'auth.backends':
                auth_backend = section_components[1]
                self._backends[auth_backend] = eval(
                    self._config.get(section, 'type'))

        self._logger.debug("Registered auth backends %s" % str(self._backends))

    def reload(self):
        """ Reload AuthFactory.
        """

        self._auth_cache = {}
        self._init_backends()

    def get_auth(self,
                 username,
                 password,
                 authoritative_source,
                 auth_options=None):
        """ Returns an authentication object.
    
            Examines the auth backend given after the '@' in the username and
            returns a suitable instance of a subclass of the BaseAuth class.

            * `username` [string]
                Username to authenticate as.
            * `password` [string]
                Password to authenticate with.
            * `authoritative_source` [string]
                Authoritative source of the query.
            * `auth_options` [dict]
                A dict which, if authenticated as a trusted user, can override
                `username` and `authoritative_source`.
        """

        if auth_options is None:
            auth_options = {}

        # validate arguments
        if (authoritative_source is None):
            raise AuthError("Missing authoritative_source.")

        # remove invalid cache entries
        rem = list()
        for key in self._auth_cache:
            if self._auth_cache[key]['valid_until'] < datetime.utcnow():
                rem.append(key)
        for key in rem:
            del (self._auth_cache[key])

        user_authbackend = username.rsplit('@', 1)

        # Find out what auth backend to use.
        # If no auth backend was specified in username, use default
        backend = ""
        if len(user_authbackend) == 1:
            backend = self._config.get('auth', 'default_backend')
            self._logger.debug("Using default auth backend %s" % backend)
        else:
            backend = user_authbackend[1]

        # do we have a cached instance?
        auth_str = (str(username) + str(password) + str(authoritative_source) +
                    str(auth_options))
        if auth_str in self._auth_cache:
            self._logger.debug('found cached auth object for user %s' %
                               username)
            return self._auth_cache[auth_str]['auth_object']

        # Create auth object
        try:
            auth = self._backends[backend](backend, user_authbackend[0],
                                           password, authoritative_source,
                                           auth_options)
        except KeyError:
            raise AuthError("Invalid auth backend '%s' specified" %
                            str(backend))

        # save auth object to cache
        self._auth_cache[auth_str] = {
            'valid_until':
            datetime.utcnow() + timedelta(
                seconds=self._config.getint('auth', 'auth_cache_timeout')),
            'auth_object':
            auth
        }

        return auth