Exemplo n.º 1
0
def _validate_security_group_rule(context, rule):
    # TODO(mdietz): As per RM8615, Remote groups are not currently supported
    if rule.get("remote_group_id"):
        raise exceptions.InvalidInput(
            error_message="Remote groups are not currently supported")

    if "direction" in rule and rule["direction"] != "ingress":
        raise exceptions.InvalidInput(
            error_message="Non-ingress rules are not currently supported")

    protocol = rule.pop('protocol')
    port_range_min = rule['port_range_min']
    port_range_max = rule['port_range_max']

    if protocol:
        protocol = protocols.translate_protocol(protocol, rule["ethertype"])
        protocols.validate_protocol_with_port_ranges(protocol, port_range_min,
                                                     port_range_max)
        rule['protocol'] = protocol
    else:
        if port_range_min is not None or port_range_max is not None:
            raise sg_ext.SecurityGroupProtocolRequiredWithPorts()

    ethertype = protocols.translate_ethertype(rule["ethertype"])
    rule["ethertype"] = ethertype

    protocols.validate_remote_ip_prefix(ethertype,
                                        rule.get("remote_ip_prefix"))

    return rule
Exemplo n.º 2
0
    def test_update_security_group_rule(self):
        sg_dict = {"id": 0}
        sg = models.SecurityGroup()
        sg.update(sg_dict)

        rule_dict = {"id": 1, "direction": "ingress",
                     "port_range_min": 80, "port_range_max": 100,
                     "remote_ip_prefix": None,
                     "ethertype": protocols.translate_ethertype("IPv4"),
                     "tenant_id": "foo", "protocol": "UDP", "group_id": 1,
                     "external_service_id": None, "external_service": None}
        rule = models.SecurityGroupRule()
        rule.update(rule_dict)

        updated_part = {'external_service_id': 'aaa',
                        'external_service': 'bbb'}

        with mock.patch('quark.db.api.security_group_rule_find') as db_find, \
                mock.patch('quark.db.api.security_group_rule_update') \
                as db_update, \
                mock.patch('quark.db.api.security_group_find') as sg_find:
            db_find.return_value = rule
            rule_dict.update(updated_part)
            new_rule = models.SecurityGroupRule()
            new_rule.update(rule_dict)
            db_update.return_value = new_rule
            sg_find.return_value = sg

            update = dict(security_group_rule=updated_part)
            resp = self.plugin.update_security_group_rule(self.context, 1,
                                                          update)
            self.assertEqual(resp['external_service_id'],
                             updated_part['external_service_id'])
            self.assertEqual(resp['external_service'],
                             updated_part['external_service'])
Exemplo n.º 3
0
def _validate_security_group_rule(context, rule):
    # TODO(mdietz): As per RM8615, Remote groups are not currently supported
    if rule.get("remote_group_id"):
        raise n_exc.InvalidInput(
            error_message="Remote groups are not currently supported")

    direction = rule.get("direction")
    if direction == Capabilities.EGRESS:
        if Capabilities.EGRESS not in CONF.QUARK.environment_capabilities:
            raise q_exc.EgressSecurityGroupRulesNotEnabled()

    protocol = rule.pop('protocol')
    port_range_min = rule['port_range_min']
    port_range_max = rule['port_range_max']
    ethertype = protocols.translate_ethertype(rule["ethertype"])

    if protocol:
        protocol = protocols.translate_protocol(protocol, rule["ethertype"])
        protocols.validate_protocol_with_port_ranges(ethertype,
                                                     protocol,
                                                     port_range_min,
                                                     port_range_max)
        rule['protocol'] = protocol
    else:
        if port_range_min is not None or port_range_max is not None:
            raise sg_ext.SecurityGroupProtocolRequiredWithPorts()

    rule["ethertype"] = ethertype

    protocols.validate_remote_ip_prefix(ethertype,
                                        rule.get("remote_ip_prefix"))

    return rule
Exemplo n.º 4
0
def _validate_security_group_rule(context, rule):
    # TODO(mdietz): As per RM8615, Remote groups are not currently supported
    if rule.get("remote_group_id"):
        raise n_exc.InvalidInput(
            error_message="Remote groups are not currently supported")

    direction = rule.get("direction")
    if direction == env.Capabilities.EGRESS:
        if env.Capabilities.EGRESS not in CONF.QUARK.environment_capabilities:
            raise q_exc.EgressSecurityGroupRulesNotEnabled()

    protocol = rule.pop('protocol')
    # NOTE(roaet): these are not required by spec
    port_range_min = rule.get('port_range_min')
    port_range_max = rule.get('port_range_max')
    # TODO(anyone): this will error as None, so defaulting to ipv4
    et = rule.get('ethertype', 'IPv4')
    ethertype = protocols.translate_ethertype(et)

    if protocol:
        protocol = protocols.translate_protocol(protocol, et)
        protocols.validate_protocol_with_port_ranges(ethertype, protocol,
                                                     port_range_min,
                                                     port_range_max)
        rule['protocol'] = protocol
    else:
        if port_range_min is not None or port_range_max is not None:
            raise sg_ext.SecurityGroupProtocolRequiredWithPorts()

    rule["ethertype"] = ethertype

    protocols.validate_remote_ip_prefix(ethertype,
                                        rule.get("remote_ip_prefix"))

    return rule
Exemplo n.º 5
0
def _validate_security_group_rule(context, rule):
    # TODO(mdietz): As per RM8615, Remote groups are not currently supported
    if rule.get("remote_group_id"):
        raise exceptions.InvalidInput(
            error_message="Remote groups are not currently supported")

    if "direction" in rule and rule["direction"] != "ingress":
        raise exceptions.InvalidInput(
            error_message="Non-ingress rules are not currently supported")

    protocol = rule.pop('protocol')
    port_range_min = rule['port_range_min']
    port_range_max = rule['port_range_max']
    ethertype = protocols.translate_ethertype(rule["ethertype"])

    if protocol:
        protocol = protocols.translate_protocol(protocol, rule["ethertype"])
        protocols.validate_protocol_with_port_ranges(ethertype,
                                                     protocol,
                                                     port_range_min,
                                                     port_range_max)
        rule['protocol'] = protocol
    else:
        if port_range_min is not None or port_range_max is not None:
            raise sg_ext.SecurityGroupProtocolRequiredWithPorts()

    rule["ethertype"] = ethertype

    protocols.validate_remote_ip_prefix(ethertype,
                                        rule.get("remote_ip_prefix"))

    return rule
Exemplo n.º 6
0
def _validate_security_group_rule(context, rule):
    # TODO(mdietz): As per RM8615, Remote groups are not currently supported
    if rule.get("remote_group_id"):
        raise exceptions.InvalidInput(
            error_message="Remote groups are not currently supported")

    direction = rule.get("direction")
    if direction == Capabilities.EGRESS:
        if Capabilities.EGRESS not in CONF.QUARK.environment_capabilities:
            raise q_exc.EgressSecurityGroupRulesNotEnabled()

    protocol = rule.pop('protocol')
    port_range_min = rule['port_range_min']
    port_range_max = rule['port_range_max']
    ethertype = protocols.translate_ethertype(rule["ethertype"])

    if protocol:
        protocol = protocols.translate_protocol(protocol, rule["ethertype"])
        protocols.validate_protocol_with_port_ranges(ethertype, protocol,
                                                     port_range_min,
                                                     port_range_max)
        rule['protocol'] = protocol
    else:
        if port_range_min is not None or port_range_max is not None:
            raise sg_ext.SecurityGroupProtocolRequiredWithPorts()

    rule["ethertype"] = ethertype

    protocols.validate_remote_ip_prefix(ethertype,
                                        rule.get("remote_ip_prefix"))

    return rule
Exemplo n.º 7
0
    def test_get_security_group_rule(self):
        rule = {"id": 1, "remote_group_id": 2, "direction": "ingress",
                "port_range_min": 80, "port_range_max": 100,
                "remote_ip_prefix": None,
                "ethertype": protocols.translate_ethertype("IPv4"),
                "tenant_id": "foo", "protocol": "UDP", "group_id": 1}
        expected = rule.copy()
        expected["security_group_id"] = expected.pop("group_id")
        expected["ethertype"] = "IPv4"

        with self._stubs(rule):
            resp = self.plugin.get_security_group_rule(self.context, 1)
            for key in expected.keys():
                self.assertTrue(key in resp)
                self.assertEqual(resp[key], expected[key])
Exemplo n.º 8
0
    def test_get_security_group_rule(self):
        rule = {"id": 1, "remote_group_id": 2, "direction": "ingress",
                "port_range_min": 80, "port_range_max": 100,
                "remote_ip_prefix": None,
                "ethertype": protocols.translate_ethertype("IPv4"),
                "tenant_id": "foo", "protocol": "UDP", "group_id": 1}
        expected = rule.copy()
        expected["security_group_id"] = expected.pop("group_id")
        expected["ethertype"] = "IPv4"

        with self._stubs(rule):
            resp = self.plugin.get_security_group_rule(self.context, 1)
            for key in expected.keys():
                self.assertTrue(key in resp)
                self.assertEqual(resp[key], expected[key])
Exemplo n.º 9
0
    def test_update_security_group_rule(self):
        sg_dict = {"id": 0}
        sg = models.SecurityGroup()
        sg.update(sg_dict)

        rule_dict = {
            "id": 1,
            "direction": "ingress",
            "port_range_min": 80,
            "port_range_max": 100,
            "remote_ip_prefix": None,
            "ethertype": protocols.translate_ethertype("IPv4"),
            "tenant_id": "foo",
            "protocol": "UDP",
            "group_id": 1,
            "external_service_id": None,
            "external_service": None
        }
        rule = models.SecurityGroupRule()
        rule.update(rule_dict)

        updated_part = {
            'external_service_id': 'aaa',
            'external_service': 'bbb'
        }

        with mock.patch('quark.db.api.security_group_rule_find') as db_find, \
                mock.patch('quark.db.api.security_group_rule_update') \
                as db_update, \
                mock.patch('quark.db.api.security_group_find') as sg_find:
            db_find.return_value = rule
            rule_dict.update(updated_part)
            new_rule = models.SecurityGroupRule()
            new_rule.update(rule_dict)
            db_update.return_value = new_rule
            sg_find.return_value = sg

            update = dict(security_group_rule=updated_part)
            resp = self.plugin.update_security_group_rule(
                self.context, 1, update)
            self.assertEqual(resp['external_service_id'],
                             updated_part['external_service_id'])
            self.assertEqual(resp['external_service'],
                             updated_part['external_service'])
Exemplo n.º 10
0
def _validate_security_group_rule(context, rule):
    # TODO(mdietz): As per RM8615, Remote groups are not currently supported
    if rule.get("remote_group_id"):
        raise n_exc.InvalidInput(
            error_message="Remote groups are not currently supported")

    direction = rule.get("direction")
    if direction == env.Capabilities.EGRESS:
        if env.Capabilities.EGRESS not in CONF.QUARK.environment_capabilities:
            raise q_exc.EgressSecurityGroupRulesNotEnabled()

    protocol = rule.pop('protocol')
    # NOTE(roaet): these are not required by spec
    port_range_min = rule.get('port_range_min')
    port_range_max = rule.get('port_range_max')
    # TODO(anyone): this will error as None, so defaulting to ipv4
    et = rule.get('ethertype', 'IPv4')
    ethertype = protocols.translate_ethertype(et)

    if protocol:
        protocol = protocols.translate_protocol(protocol, et)
        protocols.validate_protocol_with_port_ranges(ethertype,
                                                     protocol,
                                                     port_range_min,
                                                     port_range_max)
        rule['protocol'] = protocol
    else:
        if port_range_min is not None or port_range_max is not None:
            raise sg_ext.SecurityGroupProtocolRequiredWithPorts()

    rule["ethertype"] = ethertype

    protocols.validate_remote_ip_prefix(ethertype,
                                        rule.get("remote_ip_prefix"))

    return rule
Exemplo n.º 11
0
def _model_query(context, model, filters, fields=None):
    filters = filters or {}
    model_filters = []
    eq_filters = [
        "address", "cidr", "deallocated", "ip_version", "mac_address_range_id",
        "transaction_id"
    ]
    in_filters = [
        "device_id", "device_owner", "group_id", "id", "mac_address", "name",
        "network_id", "segment_id", "subnet_id", "used_by_tenant_id", "version"
    ]

    # Sanitize incoming filters to only attributes that exist in the model.
    # NOTE: Filters for unusable attributes are silently dropped here.
    # NOTE: When the filter key != attribute key, a conditional must be added
    #       here.
    model_attrs = _model_attrs(model)
    filters = {
        x: y
        for x, y in filters.items()
        if x in model_attrs or (x == "tenant_id" and model == models.IPAddress)
        or (x == "ip_address" and model == models.IPAddress) or
        (x == "reuse_after" and model in (models.IPAddress, models.MacAddress))
    }

    # Inject the tenant id if none is set. We don't need unqualified queries.
    # This works even when a non-shared, other-tenant owned network is passed
    # in because the authZ checks that happen in Neutron above us yank it back
    # out of the result set.
    if not filters.get("tenant_id") and not context.is_admin:
        filters["tenant_id"] = [context.tenant_id]

    if model == models.SecurityGroupRule:
        sg_rule_attribs = ["direction", "port_range_max", "port_range_min"]
        eq_filters.extend(sg_rule_attribs)

    for key, value in filters.items():
        # This is mostly for unittests, as they're configured to send in None
        if value is None:
            continue
        if key in in_filters:
            model_type = getattr(model, key)
            model_filters.append(model_type.in_(value))
        elif key in eq_filters:
            model_type = getattr(model, key)
            model_filters.append(model_type == value)
        elif key == "_deallocated":
            if value:
                model_filters.append(model._deallocated == 1)
            else:
                model_filters.append(model._deallocated != 1)
        elif key == "ethertype":
            etypes = []
            for etype in value:
                etypes.append(protocols.translate_ethertype(etype))
            model_filters.append(model.ethertype.in_(etypes))
        elif key == "ip_address":
            model_filters.append(
                model.address.in_([ip.ipv6().value for ip in value]))
        elif key == 'protocol':
            pnums = []
            for version in (protocols.PROTOCOLS_V4, protocols.PROTOCOLS_V6):
                pnums.extend([y for x, y in version.items() if x in value])
            model_filters.append(model.protocol.in_(pnums))
        elif key == "reuse_after":
            reuse = (timeutils.utcnow() - datetime.timedelta(seconds=value))
            # NOTE(asadoughi): should this allow for deallocated_at = null?
            model_filters.append(model.deallocated_at <= reuse)
        elif key == "tenant_id":
            if model == models.IPAddress:
                model_filters.append(model.used_by_tenant_id.in_(value))
            else:
                model_filters.append(model.tenant_id.in_(value))

    return model_filters
Exemplo n.º 12
0
def _model_query(context, model, filters, fields=None):
    filters = filters or {}
    model_filters = []
    eq_filters = ["address", "cidr", "deallocated", "ip_version", "service",
                  "mac_address_range_id", "transaction_id", "lock_id",
                  "address_type"]
    in_filters = ["device_id", "device_owner", "group_id", "id", "mac_address",
                  "name", "network_id", "segment_id", "subnet_id",
                  "used_by_tenant_id", "version"]

    # Sanitize incoming filters to only attributes that exist in the model.
    # NOTE: Filters for unusable attributes are silently dropped here.
    # NOTE: When the filter key != attribute key, a conditional must be added
    #       here.
    model_attrs = _model_attrs(model)
    filters = {x: y for x, y in filters.items()
               if x in model_attrs or
               (x == "tenant_id" and model == models.IPAddress) or
               (x == "ip_address" and model == models.IPAddress) or
               (x == "reuse_after" and model in (models.IPAddress,
                                                 models.MacAddress))}

    # Inject the tenant id if none is set. We don't need unqualified queries.
    # This works even when a non-shared, other-tenant owned network is passed
    # in because the authZ checks that happen in Neutron above us yank it back
    # out of the result set.
    if not filters.get("tenant_id") and not context.is_admin:
        filters["tenant_id"] = [context.tenant_id]

    if model == models.SecurityGroupRule:
        sg_rule_attribs = ["direction", "port_range_max", "port_range_min"]
        eq_filters.extend(sg_rule_attribs)

    for key, value in filters.items():
        if key in in_filters:
            model_type = getattr(model, key)
            model_filters.append(model_type.in_(value))
        elif key in eq_filters:
            model_type = getattr(model, key)
            model_filters.append(model_type == value)
        elif key == "_deallocated":
            if value:
                model_filters.append(model._deallocated == 1)
            else:
                model_filters.append(model._deallocated != 1)
        elif key == "ethertype":
            etypes = []
            for etype in value:
                etypes.append(protocols.translate_ethertype(etype))
            model_filters.append(model.ethertype.in_(etypes))
        elif key == "ip_address":
            model_filters.append(model.address.in_(
                [ip.ipv6().value for ip in value]))
        elif key == 'protocol':
            pnums = []
            for version in (protocols.PROTOCOLS_V4, protocols.PROTOCOLS_V6):
                pnums.extend([y for x, y in version.items() if x in value])
            model_filters.append(model.protocol.in_(pnums))
        elif key == "reuse_after":
            reuse = (timeutils.utcnow() -
                     datetime.timedelta(seconds=value))
            # NOTE(asadoughi): should this allow for deallocated_at = null?
            model_filters.append(model.deallocated_at <= reuse)
        elif key == "port_id":
            if model == models.PortIpAssociation:
                model_filters.append(model.port_id == value)
        elif key == "tenant_id":
            if model == models.IPAddress:
                model_filters.append(model.used_by_tenant_id.in_(value))
            elif model in _NO_TENANT_MODELS:
                pass
            else:
                model_filters.append(model.tenant_id.in_(value))

    return model_filters