示例#1
0
文件: ldap.py 项目: umithardal/nicos
class Authenticator(BaseAuthenticator):
    """Authenticates against the configured LDAP server.

    Basically it tries to bind on the server with the given userdn.
    Per default, all ldap users are rejected when there is no user level
    definition inside the 'roles' dictionary.
    """

    BIND_METHODS = {
        'none': ldap3.AUTO_BIND_NONE,
        'no_tls': ldap3.AUTO_BIND_NO_TLS,
        'tls_before_bind': ldap3.AUTO_BIND_TLS_BEFORE_BIND,
        'tls_after_bind': ldap3.AUTO_BIND_TLS_AFTER_BIND,
    }

    parameters = {
        'uri':
        Param('LDAP connection URI', type=str, mandatory=True),
        'bindmethod':
        Param('LDAP port', type=oneof(*BIND_METHODS), default='no_tls'),
        'userbasedn':
        Param('Base dn to query users.', type=str, mandatory=True),
        'userfilter':
        Param('Filter for querying users. Must contain '
              '"%(username)s"',
              type=str,
              default='(&(uid=%(username)s)'
              '(objectClass=posixAccount))'),
        'groupbasedn':
        Param('Base dn to query groups', type=str, mandatory=True),
        'groupfilter':
        Param(
            'Filter for querying groups. '
            'Must contain "%(gidnumber)s"',
            type=str,
            default='(&(gidNumber=%(gidnumber)s)'
            '(objectClass=posixGroup))'),
        'usergroupfilter':
        Param(
            'Filter groups of a specific user. '
            'Must contain "%(username)s"',
            type=str,
            default='(&(memberUid=%(username)s)'
            '(objectClass=posixGroup))'),
        'userroles':
        Param('Dictionary of allowed users with their '
              'associated role',
              type=dictof(str, oneof(*ACCESS_LEVELS.values()))),
        'grouproles':
        Param('Dictionary of allowed groups with their '
              'associated role',
              type=dictof(str, oneof(*ACCESS_LEVELS.values()))),
    }

    def doInit(self, mode):
        self._access_levels = {
            value: key
            for key, value in iteritems(ACCESS_LEVELS)
        }

    def authenticate(self, username, password):
        userdn = self._get_user_dn(username)

        # first of all: try a bind to check user existence and password
        try:
            connection = ldap3.Connection(
                self.uri,
                user=userdn,
                password=password,
                auto_bind=self.BIND_METHODS[self.bindmethod])
        except ldap3.core.exceptions.LDAPException as e:
            raise AuthenticationError('LDAP connection failed (%s)' % e)

        userlevel = -1

        # check if the user has explicit rights
        if username in self.userroles:
            userlevel = self._access_levels[self.userroles[username]]
            return User(username, userlevel)

        # if no explicit user right was given, check group rights
        groups = self._get_user_groups(connection, username)

        for group in groups:
            if group in self.grouproles:
                userlevel = max(userlevel,
                                self._access_levels[self.grouproles[group]])

        if userlevel >= 0:
            return User(username, userlevel)

        raise AuthenticationError('Login not permitted for the given user')

    def _get_user_groups(self, connection, username):
        # start with the users default group
        groups = [self._get_default_group(connection, username)]

        # find additional groups of the user
        filter_str = self.usergroupfilter % {'username': username}
        connection.search(self.groupbasedn,
                          filter_str,
                          ldap3.LEVEL,
                          attributes=ldap3.ALL_ATTRIBUTES)

        for group in connection.response:
            groups.append(group['attributes']['cn'][0])

        return groups

    def _get_default_group(self, connection, username):
        filter_str = self.userfilter % {'username': username}

        if not connection.search(self.userbasedn,
                                 filter_str,
                                 ldap3.LEVEL,
                                 attributes=ldap3.ALL_ATTRIBUTES):
            raise AuthenticationError('User not found in LDAP directory')

        return self._get_group_name(
            connection, connection.response[0]['attributes']['gidNumber'])

    def _get_group_name(self, connection, gid):
        filter_str = self.groupfilter % {'gidnumber': gid}
        if not connection.search(self.groupbasedn,
                                 filter_str,
                                 ldap3.LEVEL,
                                 attributes=ldap3.ALL_ATTRIBUTES):
            raise AuthenticationError('Group %s not found' % gid)
        return connection.response[0]['attributes']['cn'][0]

    def _get_user_dn(self, username):
        return 'uid=%s,%s' % (username, self.userbasedn)
示例#2
0
def _access_level_list():
    return ', '.join(repr(l) for l in ACCESS_LEVELS.values())