Exemplo n.º 1
0
def validate_sg_rule(plan_data, params, condition):
    from_port = int(params['from_port'])
    to_port = int(params['to_port'])

    assert from_port <= to_port, 'Port range is defined incorrectly within the Scenario. ' \
                                'Define it {}-{} instead of {}-{}.'.format(from_port,
                                                                           to_port,
                                                                           to_port,
                                                                           from_port)

    defined_range = set(range(plan_data['from_port'],
                              plan_data['to_port'] + 1))
    defined_network_list = plan_data['cidr_blocks']
    given_network = params.get('cidr', None)

    # Condition: must only have
    # Fail only if ;
    # * the ports does not match and defined network is a subset of given network.
    if condition:
        given_range = set([int(port) for port in params['ports']])
        from_to_port = ','.join(params['ports'])

        # Set to True if ports are exactly same.
        port_intersection = given_range == defined_range

        # Set to True if one of the given networks is a subset.
        network_check = is_ip_in_cidr(given_network, defined_network_list)

        if not port_intersection and network_check:
            raise Failure('{}/{} ports are defined for {} network. '
                          'Must be limited to {}/{} and {}'.format(
                              '/'.join(plan_data['protocol']),
                              '{}-{}'.format(plan_data['from_port'],
                                             plan_data['to_port']),
                              plan_data['cidr_blocks'],
                              '/'.join(plan_data['protocol']), from_to_port,
                              given_network))

    # Condition: must not have
    # Fail only if ;
    # * the ports match and networks match
    else:
        given_range = set(range(from_port, to_port + 1))
        port_intersection = given_range & defined_range
        from_to_port = str(from_port) + '-' + str(to_port)
        network_intersection = is_ip_in_cidr(given_network,
                                             defined_network_list)

        if port_intersection and network_intersection:
            raise Failure('{}/{} ports are defined for {} network.'.format(
                '/'.join(plan_data['protocol']),
                '{}-{}'.format(plan_data['from_port'], plan_data['to_port']),
                plan_data['cidr_blocks']))

    return True
Exemplo n.º 2
0
 def fail(assertion, message):
     try:
         assert assertion, 'Failed'
     except AssertionError as e:
         raise Failure('for {} on {}. {}.'.format(_step_obj.context.address,
                                                  _step_obj.context.property_name,
                                                  message))
Exemplo n.º 3
0
def assign_sg_params(rule):
    from_port = int(rule.get('from_port', 0))
    to_port = int(rule.get('to_port', 0))

    protocol = [proto for proto in [rule.get('protocol', '-1')]]

    if protocol[0] == '-1' or type(protocol[0]) is int:
        protocol = ['tcp', 'udp']

    protocol[0] = protocol[0].lower()

    cidr_blocks = rule.get('cidr_blocks', [])

    if type(cidr_blocks) is not list:
        cidr_blocks = [cidr_blocks]

    if to_port == 0 and from_port == 0:
        to_port = 65535

    if from_port > to_port:
        raise Failure(
            'Invalid configuration from_port can not be bigger than to_port. '
            '{} > {} {} in {}'.format(from_port, to_port, protocol,
                                      cidr_blocks))

    return dict(protocol=protocol,
                from_port=from_port,
                to_port=to_port,
                cidr_blocks=cidr_blocks)
Exemplo n.º 4
0
def encryption_is_enabled(_step_obj):
    for resource in _step_obj.context.stash:
        if type(resource) is dict:
            prop = encryption_property.get(resource['type'], None)

            if not prop:
                raise TerraformComplianceNotImplemented(
                    'Encryption property for {} '
                    'is not implemented yet.'.format(resource['type']))

            encryption_value = seek_key_in_dict(
                resource.get('values', {}),
                encryption_property[resource['type']])

            if len(encryption_value):
                encryption_value = encryption_value[0]

                if type(encryption_value) is dict:
                    encryption_value = encryption_value[encryption_property[
                        resource['type']]]

            if not encryption_value:
                raise Failure(
                    'Resource {} does not have encryption enabled ({}={}).'.
                    format(resource['address'], prop, encryption_value))

    return True
Exemplo n.º 5
0
 def fail(condition):
     text = 'matches' if condition == 'must not' else 'does not match'
     raise Failure('{} property in {} {} {} with {} regex. '
                   'It is set to {}.'.format(
                       _step_obj.context.property_name,
                       _step_obj.context.name, _step_obj.context.type, text,
                       regex, values))
Exemplo n.º 6
0
 def fail(condition, name=None):
     text = 'matches' if condition == 'must not' else 'does not match'
     name = name if (name is not None
                     or name is not False) else _step_obj.context.name
     pattern = 'Null/None' if regex == '\x00' else regex
     raise Failure('{} property in {} {} {} with {} regex. '
                   'It is set to {}.'.format(
                       _step_obj.context.property_name, name,
                       _step_obj.context.type, text, pattern, values))
Exemplo n.º 7
0
def it_condition_have_proto_protocol_and_port_port_for_cidr(
        _step_obj, condition, proto, port, cidr):
    proto = str(proto)
    cidr = str(cidr)

    # Set to True only if the condition is 'only'
    condition = condition == 'only'

    # In case we have a range
    if '-' in port:
        if condition:
            raise Failure(
                '"must only" scenario cases must be used either with individual port '
                'or multiple ports separated with comma.')

        from_port, to_port = port.split('-')
        ports = [from_port, to_port]

    # In case we have comma delimited ports
    elif ',' in port:
        ports = [port for port in port.split(',')]
        from_port = min(ports)
        to_port = max(ports)

    else:
        from_port = to_port = int(port)
        ports = list(set([str(from_port), str(to_port)]))

    from_port = int(from_port) if int(from_port) > 0 else 1
    to_port = int(to_port) if int(to_port) > 0 else 1
    ports[0] = ports[0] if int(ports[0]) > 0 else '1'

    looking_for = dict(proto=proto,
                       from_port=int(from_port),
                       to_port=int(to_port),
                       ports=ports,
                       cidr=cidr)

    for security_group in _step_obj.context.stash:
        if type(security_group['values']) is list:
            for sg in security_group['values']:
                check_sg_rules(plan_data=sg,
                               security_group=looking_for,
                               condition=condition)

        elif type(security_group['values']) is dict:
            check_sg_rules(plan_data=security_group['values'],
                           security_group=looking_for,
                           condition=condition)
        else:
            raise TerraformComplianceInternalFailure(
                'Unexpected Security Group, '
                'must be either list or a dict: '
                '{}'.format(security_group['values']))
    return True
Exemplo n.º 8
0
def property_is_enabled(_step_obj, something):
    for resource in _step_obj.context.stash:
        if type(resource) is dict:
            if something in property_match_list:
                something = property_match_list[something].get(resource['type'], something)

            property_value = seek_key_in_dict(resource.get('values', {}), something)

            if len(property_value):
                property_value = property_value[0]

                if type(property_value) is dict:
                    property_value = property_value.get(something, Null)

            if not property_value:
                raise Failure('Resource {} does not have {} property enabled ({}={}).'.format(resource.get('address', "resource"),
                                                                                              something,
                                                                                              something,
                                                                                              property_value))
    return True
Exemplo n.º 9
0
def _its_value_condition_contain(_step_obj, condition, value, values):
    assert condition in ('must', 'must not'), 'Condition should be one of: `must`, `must not`'
    if isinstance(values, (int, bool, str, float)):
        values = [values]

    if isinstance(values, list):
        values = [str(v) for v in values]
        _fail_text = 'did not contain' if condition == 'must' else 'contains'
        fail_message = '{} property in {} {} {}, it is set to {}'.format(
            _step_obj.context.property_name,
            _step_obj.context.name,
            _fail_text,
            value,
            values,
        )
        if condition == 'must':
            assert value in values, fail_message
        else:
            assert value not in values, fail_message
    else:
        raise Failure('Can only check that if list contains value')
Exemplo n.º 10
0
def it_fails(_step_obj):
    raise Failure('Forcefully failing the scenario on {} {}'.format(
        _step_obj.context.name, _step_obj.context.type))
Exemplo n.º 11
0
def it_condition_contain_something(_step_obj, something):
    prop_list = []

    if _step_obj.context.type in ('resource', 'data'):
        for resource in _step_obj.context.stash:
            if type(resource) is not dict:
                resource = {
                    'values': resource,
                    'address': resource,
                    'type': _step_obj.context.name
                }

            values = resource.get('values', resource.get('expressions', {}))

            found_value = Null
            found_key = Null
            if type(values) is dict:
                found_key = values.get(something,
                                       seek_key_in_dict(values, something))
                if type(found_key) is not list:
                    found_key = [{something: found_key}]

                if len(found_key):
                    found_key = found_key[0] if len(
                        found_key) == 1 else found_key

                    if type(found_key) is dict:
                        found_value = jsonify(
                            found_key.get(something, found_key))
                    else:
                        found_value = found_key
            elif type(values) is list:
                found_value = []

                for value in values:

                    if type(value) is dict:
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(
                                value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break

                    if found_key is not Null and len(found_key):
                        found_key = found_key[0] if len(
                            found_key) == 1 else found_key

                        if type(found_key) is dict:
                            found_value.append(
                                jsonify(found_key.get(something, found_key)))

            if type(found_value) is dict and 'constant_value' in found_value:
                found_value = found_value['constant_value']

            if found_value is not Null and found_value != [] and found_value != '' and found_value != {}:
                prop_list.append({
                    'address': resource['address'],
                    'values': found_value,
                    'type': _step_obj.context.name
                })

            elif 'must' in _step_obj.context_sensitive_sentence:
                raise Failure('{} ({}) does not have {} property.'.format(
                    resource['address'], resource.get('type', ''), something))

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something
            return True

        skip_step(_step_obj,
                  resource=_step_obj.context.name,
                  message='Can not find any {} property for {} resource in '
                  'terraform plan.'.format(something, _step_obj.context.name))

    elif _step_obj.context.type == 'provider':
        values = seek_key_in_dict(_step_obj.context.stash, something)

        if values:
            _step_obj.context.stash = values
            _step_obj.context.property_name = something
            return True

    skip_step(
        _step_obj,
        resource=_step_obj.context.name,
        message='Skipping the step since {} type does not have {} property.'.
        format(_step_obj.context.type, something))
Exemplo n.º 12
0
def it_fails(_step_obj):
    raise Failure('Forcefully failing the scenario on {} ({}) {}'.format(_step_obj.context.name,
                                                                         ', '.join(_step_obj.context.addresses),
                                                                         _step_obj.context.type))
Exemplo n.º 13
0
def it_condition_contain_something(_step_obj, something):
    prop_list = []

    if _step_obj.context.type == 'resource':
        for resource in _step_obj.context.stash:
            if type(resource) is not dict:
                resource = {
                    'values': resource,
                    'address': resource,
                    'type': _step_obj.context.name
                }

            values = resource.get('values', {})

            found_value = None
            found_key = None
            if type(values) is dict:
                found_key = seek_key_in_dict(values, something)
                if len(found_key):
                    found_key = found_key[0]

                    if type(found_key) is dict:
                        found_value = jsonify(found_key[something])
            elif type(values) is list:
                for value in values:

                    if type(value) is dict:
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(
                                value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break
                    else:
                        raise TerraformComplianceInternalFailure(
                            'Unexpected value type {}. {}'.format(
                                type(value), value))

            if found_key:
                prop_list.append({
                    'address': resource['address'],
                    'values': found_value,
                    'type': _step_obj.context.name
                })

            elif 'must' in _step_obj.context_sensitive_sentence:
                raise Failure('{} ({}) does not have {} property.'.format(
                    resource['address'], resource.get('type', ''), something))

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something
            return True

        skip_step(_step_obj,
                  resource=_step_obj.context.name,
                  message='Can not find any {} property for {} resource in '
                  'terraform plan.'.format(something, _step_obj.context.name))

    elif _step_obj.context.type == 'provider':
        values = seek_key_in_dict(_step_obj.context.stash, something)

        if values:
            _step_obj.context.stash = values
            _step_obj.context.property_name = something
            return True

    skip_step(
        _step_obj,
        resource=_step_obj.context.name,
        message='Skipping the step since {} type does not have {} property.'.
        format(_step_obj.context.type, something))