def test_get_actions_from_statement(self):
     statement = {
         "Action": "ec2:thispermissiondoesntexist",
         "NotAction": list(all_permissions),
         "Resource": "*",
         "Effect": "Allow"
     }
     expected_result = {"ec2:thispermissiondoesntexist"}
     result = get_actions_from_statement(statement)
     self.assertEqual(result, expected_result)
     get_actions_from_statement(dict(NotAction="abc"))
 def test_get_actions_from_statement(self):
     statement = {
         "Action": "ec2:thispermissiondoesntexist",
         "NotAction": list(all_permissions),
         "Resource": "*",
         "Effect": "Allow"
     }
     expected_result = {"ec2:thispermissiondoesntexist"}
     result = get_actions_from_statement(statement)
     self.assertEqual(result, expected_result)
     get_actions_from_statement(dict(NotAction="abc"))
Beispiel #3
0
def pass_condition(b, test, a):
    if test == 'inSubnets':
        grant = netaddr.IPNetwork(b)
        for c in a:
            known_subnet = netaddr.IPNetwork(c)
            if grant in known_subnet:
                return True
        return False
    if test == 'notInSubnets':
        grant = netaddr.IPNetwork(b)
        for c in a:
            known_subnet = netaddr.IPNetwork(c)
            if grant in known_subnet:
                return False
        return True
    elif test == 'containAction':
        if type(b) != dict:
            b = json.loads(b)
        actions = get_actions_from_statement(b)
        return True if a.lower() in actions else False
    elif test == 'isCrossAccount':
        if type(b) != list:
            b = [b]
        for c in b:
            if c == a or re.match(r'arn:aws:iam:.*?:%s:.*' % a, c):
                continue
            else:
                return True
        return False
    elif test == 'isSameAccount':
        if type(b) != list:
            b = [b]
        for c in b:
            if c == a or re.match(r'arn:aws:iam:.*?:%s:.*' % a, c):
                return True
            else:
                continue
        return False
    elif test == 'containOneMatching':
        if not type(b) == list:
            b = [b]
        for c in b:
            if re.match(a, c) != None:
                return True
        return False
    elif test == 'containAtLeastOneOf':
        if not type(b) == list:
            b = [b]
        for c in b:
            if type(c):
                c = str(c)
            if c in a:
                return True
        return False
    elif test == 'containAtLeastOneDifferentFrom':
        if not type(b) == list:
            b = [b]
        if not type(a) == list:
            a = [a]
        for c in b:
            if c not in a:
                return True
        return False
    elif test == 'containNoneOf':
        if not type(b) == list:
            b = [b]
        for c in b:
            if c in a:
                return False
        return True
    elif test == 'equal':
        if type(b) != str:
            b = str(b)
        return a == b
    elif test == 'notEqual':
        if type(b) != str:
            b = str(b)
        return a != b
    elif test == 'lessThan':
        return int(b) < int(a)
    elif test == 'lessOrEqual':
        return int(b) <= int(a)
    elif test == 'moreThan':
        return int(b) > int(a)
    elif test == 'moreOrEqual':
        return int(b) >= int(a)
    elif test == 'empty':
        return ((type(b) == dict and b == {}) or (type(b) == list and b == [])
                or (type(b) == list and b == [None]))
    elif test == 'notEmpty':
        return not ((type(b) == dict and b == {}) or
                    (type(b) == list and b == []) or
                    (type(b) == list and b == [None]))
    elif test == 'match':
        if type(b) != str:
            b = str(b)
        return re.match(a, b) != None
    elif test == 'notMatch':
        return re.match(a, b) == None
    elif test == 'null':
        return ((b == None) or (type(b) == str and b == 'None'))
    elif test == 'notNull':
        return not ((b == None) or (type(b) == str and b == 'None'))
    elif test == 'datePriorTo':
        b = dateutil.parser.parse(str(b)).replace(tzinfo=None)
        a = dateutil.parser.parse(str(a)).replace(tzinfo=None)
        return b < a
    elif test == 'dateOlderThan':
        try:
            age = (datetime.datetime.today() -
                   dateutil.parser.parse(str(b)).replace(tzinfo=None)).days
            return age > int(a)
        except Exception as e:
            # Failure means an invalid date, meaning no activity
            printException(e)
            return True
    elif test == 'dateNotOlderThan':
        try:
            age = (datetime.datetime.today() -
                   dateutil.parser.parse(b).replace(tzinfo=None)).days
            return age < int(a)
        except Exception as e:
            # Failure means an invalid date, meaning no activity
            return True
    elif test == 'true':
        return b in [True, 'True', 'true']
    elif test == 'notTrue' or test == 'false':
        return b not in [True, 'True', 'true']
    elif test == 'withKey':
        return a in b
    elif test == 'withoutKey':
        return not a in b
    elif test == 'inRange':
        range_found = re_port_range.match(b)
        if range_found:
            p1 = int(range_found.group(1))
            p2 = int(range_found.group(2))
            if int(a) in range(int(range_found.group(1)),
                               int(range_found.group(2))):
                return True
        else:
            port_found = re_single_port.match(b)
            if port_found and a == port_found.group(1):
                return True
    elif test == 'lengthLessThan':
        return len(b) < int(a)
    elif test == 'lengthMoreThan':
        return len(b) > int(a)
    elif test == 'lengthEqual':
        return len(b) == int(a)
    else:
        # Throw an exception here actually...
        printError('Error: unknown test case %s' % test)
    return False
Beispiel #4
0
def pass_condition(b, test, a):
    """
    Generic test function used by Scout
                                        .
    :param b:                           Value to be tested against
    :param test:                        Name of the test case to run
    :param a:                           Value to be tested

    :return:                            True of condition is met, False otherwise
    """

    # Return false by default
    result = False

    # Equality tests
    if test == 'equal':
        a = str(a)
        b = str(b)
        result = (a == b)
    elif test == 'notEqual':
        result = (not pass_condition(b, 'equal', a))

    # More/Less tests
    elif test == 'lessThan':
        result = (int(b) < int(a))
    elif test == 'lessOrEqual':
        result = (int(b) <= int(a))
    elif test == 'moreThan':
        result = (int(b) > int(a))
    elif test == 'moreOrEqual':
        result = (int(b) >= int(a))

    # Empty tests
    elif test == 'empty':
        result = ((type(b) == dict and b == {})
                  or (type(b) == list and b == [])
                  or (type(b) == list and b == [None]))
    elif test == 'notEmpty':
        result = (not pass_condition(b, 'empty', 'a'))
    elif test == 'null':
        result = ((b is None) or (type(b) == str and b == 'None'))
    elif test == 'notNull':
        result = (not pass_condition(b, 'null', a))

    # Boolean tests
    elif test == 'true':
        result = (str(b).lower() == 'true')
    elif test == 'notTrue' or test == 'false':
        result = (str(b).lower() == 'false')

    # Object length tests
    elif test == 'lengthLessThan':
        result = (len(b) < int(a))
    elif test == 'lengthMoreThan':
        result = (len(b) > int(a))
    elif test == 'lengthEqual':
        result = (len(b) == int(a))

    # Dictionary keys tests
    elif test == 'withKey':
        result = (a in b)
    elif test == 'withoutKey':
        result = a not in b

    # List tests
    elif test == 'containAtLeastOneOf':
        result = False
        if not type(b) == list:
            b = [b]
        if not type(a) == list:
            a = [a]
        for c in b:
            if type(c):
                c = str(c)
            if c in a:
                result = True
                break
    elif test == 'containAtLeastOneDifferentFrom':
        result = False
        if not type(b) == list:
            b = [b]
        if not type(a) == list:
            a = [a]
        for c in b:
            if c and c != '' and c not in a:
                result = True
                break
    elif test == 'containNoneOf':
        result = True
        if not type(b) == list:
            b = [b]
        if not type(a) == list:
            a = [a]
        for c in b:
            if c in a:
                result = False
                break

    # Regex tests
    elif test == 'match':
        if type(a) != list:
            a = [a]
        b = str(b)
        for c in a:
            if re.match(c, b):
                result = True
                break
    elif test == 'notMatch':
        result = (not pass_condition(b, 'match', a))

    # Date tests
    elif test == 'priorToDate':
        b = dateutil.parser.parse(str(b)).replace(tzinfo=None)
        a = dateutil.parser.parse(str(a)).replace(tzinfo=None)
        result = (b < a)
    elif test == 'olderThan':
        age, threshold = __prepare_age_test(a, b)
        result = (age > threshold)
    elif test == 'newerThan':
        age, threshold = __prepare_age_test(a, b)
        result = (age < threshold)

    # CIDR tests
    elif test == 'inSubnets':
        result = False
        grant = netaddr.IPNetwork(b)
        if type(a) != list:
            a = [a]
        for c in a:
            known_subnet = netaddr.IPNetwork(c)
            if grant in known_subnet:
                result = True
                break
    elif test == 'notInSubnets':
        result = (not pass_condition(b, 'inSubnets', a))

    # Policy statement tests
    elif test == 'containAction':
        result = False
        if type(b) != dict:
            b = json.loads(b)
        statement_actions = get_actions_from_statement(b)
        rule_actions = _expand_wildcard_action(a)
        for action in rule_actions:
            if action.lower() in statement_actions:
                result = True
                break
    elif test == 'notContainAction':
        result = (not pass_condition(b, 'containAction', a))
    elif test == 'containAtLeastOneAction':
        result = False
        if type(b) != dict:
            b = json.loads(b)
        if type(a) != list:
            a = [a]
        actions = get_actions_from_statement(b)
        for c in a:
            if c.lower() in actions:
                result = True
                break

    # Policy principal tests
    elif test == 'isCrossAccount':
        result = False
        if type(b) != list:
            b = [b]
        for c in b:
            if c != a and not re.match(r'arn:aws:iam:.*?:%s:.*' % a, c):
                result = True
                break
    elif test == 'isSameAccount':
        result = False
        if type(b) != list:
            b = [b]
        for c in b:
            if c == a or re.match(r'arn:aws:iam:.*?:%s:.*' % a, c):
                result = True
                break

    # Unknown test case
    else:
        print_error('Error: unknown test case %s' % test)
        raise Exception

    return result