예제 #1
0
    def lookup_user(self, user, rhost, vhost_in, conn_name, conn_id):
        """
        Lookup function called from C.
        Determine if a user on host accessing vhost through AMQP Open is allowed
        according to the policy access rules.
        If allowed then return the policy vhost settings name. If stats.can_connect
        returns true then it has registered and counted the connection.
        @param[in] user connection authId
        @param[in] rhost connection remote host numeric IP address as string
        @param[in] vhost_in vhost user is accessing
        @param[in] conn_name connection name used for tracking reports
        @param[in] conn_id internal connection id
        @return settings user-group name if allowed; "" if not allowed
        """
        try:
            # choose rule set based on incoming vhost or default vhost
            # or potential vhost found by pattern matching
            vhost = vhost_in
            if self.use_hostname_patterns:
                agent = self._manager.get_agent()
                vhost = agent.qd.qd_dispatch_policy_host_pattern_lookup(
                    agent.dispatch, vhost)
            if vhost not in self.rulesetdb:
                if self.default_vhost_enabled():
                    vhost = self._default_vhost
                else:
                    self._manager.log_info(
                        "DENY AMQP Open for user '%s', rhost '%s', vhost '%s': "
                        "No policy defined for vhost" %
                        (user, rhost, vhost_in))
                    return ""
            if vhost != vhost_in:
                self._manager.log_debug(
                    "AMQP Open for user '%s', rhost '%s', vhost '%s': "
                    "proceeds using vhost '%s' ruleset" %
                    (user, rhost, vhost_in, vhost))

            ruleset = self.rulesetdb[vhost]

            # look up the stats
            if vhost not in self.statsdb:
                msg = ("DENY AMQP Open for user '%s', rhost '%s', vhost '%s': "
                       "INTERNAL: Policy is defined but stats are missing" %
                       (user, rhost, vhost))
                raise PolicyError(msg)
            stats = self.statsdb[vhost]

            # Get settings for user in a user group or in default
            if user in ruleset[PolicyKeys.RULESET_U2G_MAP]:
                usergroup = ruleset[PolicyKeys.RULESET_U2G_MAP][user]
            elif "*" in ruleset[PolicyKeys.RULESET_U2G_MAP]:
                usergroup = ruleset[PolicyKeys.RULESET_U2G_MAP]["*"]
            else:
                if ruleset[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT]:
                    usergroup = PolicyKeys.KW_DEFAULT_SETTINGS
                else:
                    self._manager.log_info(
                        "DENY AMQP Open for user '%s', rhost '%s', vhost '%s': "
                        "User is not in a user group and unknown users are denied"
                        % (user, rhost, vhost))
                    stats.count_other_denial()
                    return ""
            groupsettings = ruleset[PolicyKeys.KW_GROUPS][usergroup]

            # User in usergroup allowed to connect from rhost?
            allowed = False
            if PolicyKeys.KW_REMOTE_HOSTS in groupsettings:
                # Users are restricted to connecting from a rhost
                # defined by the group's remoteHost list
                cglist = groupsettings[PolicyKeys.KW_REMOTE_HOSTS]
                uhs = HostStruct(rhost)
                for cohost in cglist:
                    if cohost.match_bin(uhs):
                        allowed = True
                        break
            if not allowed:
                self._manager.log_info(
                    "DENY AMQP Open for user '%s', rhost '%s', vhost '%s': "
                    "User is not allowed to connect from this network host" %
                    (user, rhost, vhost))
                stats.count_other_denial()
                return ""

            # This user passes administrative approval.
            # Now check live connection counts
            diags = []
            if not stats.can_connect(conn_name, user, rhost, diags):
                for diag in diags:
                    self._manager.log_info(
                        "DENY AMQP Open for user '%s', rhost '%s', vhost '%s': "
                        "%s" % (user, rhost, vhost, diag))
                return ""

            # Record facts about this connection to use during teardown
            facts = ConnectionFacts(user, rhost, vhost, conn_name)
            self._connections[conn_id] = facts

            # Return success
            return usergroup

        except Exception, e:
            self._manager.log_info(
                "DENY AMQP Open lookup_user failed for user '%s', rhost '%s', vhost '%s': "
                "Internal error: %s" % (user, rhost, vhost, e))
            # return failure
            return ""