mirror of
https://github.com/peeringdb/peeringdb.git
synced 2024-05-11 05:55:09 +00:00
Additional IRR validators (#690)
* increase rdap lookup timeout to 2.5 * Allow as set hierarchy according to RFC 2622 5.0 during IRR validation (#151) * fix wording of validation error message (#151) * allow single as in irr validation (#151) allow as rs-set combination in irr validation (#151) Co-authored-by: Stefan Pratter <stefan@20c.com>
This commit is contained in:
@@ -163,6 +163,9 @@ set_option("DATA_QUALITY_MIN_PREFIXLEN_V6", 64)
|
||||
# maximum value to allow for prefix length on a v6 prefix
|
||||
set_option("DATA_QUALITY_MAX_PREFIXLEN_V6", 116)
|
||||
|
||||
# maximum value to allow for irr set hierarchy depth
|
||||
set_option("DATA_QUALITY_MAX_IRR_DEPTH", 3)
|
||||
|
||||
RATELIMITS = {
|
||||
"request_login_POST": "4/m",
|
||||
"request_translation": "2/m",
|
||||
|
@@ -120,6 +120,7 @@ class RdapLookup(rdap.RdapClient):
|
||||
config = dict(
|
||||
bootstrap_url=settings.RDAP_URL.rstrip("/"),
|
||||
lacnic_apikey=settings.RDAP_LACNIC_APIKEY,
|
||||
timeout=2.5,
|
||||
)
|
||||
super(RdapLookup, self).__init__(config)
|
||||
|
||||
|
@@ -180,23 +180,62 @@ def validate_irr_as_set(value):
|
||||
for item in value.split(","):
|
||||
item = item.upper()
|
||||
source = None
|
||||
as_set = None
|
||||
|
||||
# <name>@<source>
|
||||
parts_match = re.match("^(AS|RS)-([\w\d\-]+)@(\w+)$", item)
|
||||
parts_match = re.match("^([\w\d\-:]+)@(\w+)$", item)
|
||||
if parts_match:
|
||||
source = parts_match.group(3)
|
||||
source = parts_match.group(2)
|
||||
as_set = parts_match.group(1)
|
||||
|
||||
# <source>::<name>
|
||||
else:
|
||||
parts_match = re.match("^(\w+)::(AS|RS)-([\w\d\-]+)$", item)
|
||||
parts_match = re.match("^(\w+)::([\w\d\-:]+)$", item)
|
||||
if parts_match:
|
||||
source = parts_match.group(1)
|
||||
as_set = parts_match.group(2)
|
||||
else:
|
||||
raise ValidationError(_("Invalid formatting: {} - should be AS-SET@SOURCE or SOURCE::AS-SET").format(item))
|
||||
|
||||
if source not in IRR_SOURCE:
|
||||
raise ValidationError(_("Unknown IRR source: {}").format(source))
|
||||
|
||||
|
||||
# validate set name and as hierarchy
|
||||
as_parts = as_set.split(":")
|
||||
|
||||
if len(as_parts) > settings.DATA_QUALITY_MAX_IRR_DEPTH:
|
||||
raise ValidationError(
|
||||
_("Maximum AS-SET hierarchy depth: {}").format(
|
||||
settings.DATA_QUALITY_MAX_IRR_DEPTH
|
||||
)
|
||||
)
|
||||
|
||||
set_found = False
|
||||
typ = None
|
||||
types = []
|
||||
|
||||
for part in as_parts:
|
||||
match_set = re.match("^(AS|RS)-[\w\d\-]+$", part)
|
||||
match_as = re.match("^(AS)[\d]+$", part)
|
||||
|
||||
# set name found
|
||||
|
||||
if match_set:
|
||||
set_found = True
|
||||
types.append(match_set.group(1))
|
||||
elif not match_as:
|
||||
raise ValidationError(_("Invalid formatting: {} - should be RS-SET, AS-SET or AS123").format(part))
|
||||
|
||||
|
||||
if len(list(set(types))) > 1:
|
||||
raise ValidationError(
|
||||
_("All parts of an hierarchical name have to be of the same type")
|
||||
)
|
||||
|
||||
if not set_found and len(as_parts) > 1:
|
||||
raise ValidationError(_("At least one component must be an actual set name"))
|
||||
|
||||
validated.append(item)
|
||||
|
||||
return " ".join(validated)
|
||||
|
@@ -154,6 +154,7 @@ settings.configure(
|
||||
DATA_QUALITY_MAX_PREFIXLEN_V4=28,
|
||||
DATA_QUALITY_MIN_PREFIXLEN_V6=64,
|
||||
DATA_QUALITY_MAX_PREFIXLEN_V6=116,
|
||||
DATA_QUALITY_MAX_IRR_DEPTH=3,
|
||||
TUTORIAL_MODE=False,
|
||||
CAPTCHA_TEST_MODE=True,
|
||||
SITE_ID=1,
|
||||
|
@@ -156,11 +156,20 @@ def test_validate_prefix_overlap():
|
||||
# success validation
|
||||
("RIPE::AS-FOO", "RIPE::AS-FOO"),
|
||||
("AS-FOO@RIPE", "AS-FOO@RIPE"),
|
||||
("AS-FOO-BAR@RIPE", "AS-FOO-BAR@RIPE"),
|
||||
("ripe::as-foo", "RIPE::AS-FOO"),
|
||||
("as-foo@ripe", "AS-FOO@RIPE"),
|
||||
("as-foo@ripe as-bar@ripe", "AS-FOO@RIPE AS-BAR@RIPE"),
|
||||
("as-foo@ripe,as-bar@ripe", "AS-FOO@RIPE AS-BAR@RIPE"),
|
||||
("as-foo@ripe, as-bar@ripe", "AS-FOO@RIPE AS-BAR@RIPE"),
|
||||
(
|
||||
"RIPE::AS12345:AS-FOO RIPE::AS12345:AS-FOO:AS9876",
|
||||
"RIPE::AS12345:AS-FOO RIPE::AS12345:AS-FOO:AS9876"
|
||||
),
|
||||
("ripe::as-foo:as123:as345", "RIPE::AS-FOO:AS123:AS345"),
|
||||
("RIPE::AS12345", "RIPE::AS12345"),
|
||||
("AS12345@RIPE", "AS12345@RIPE"),
|
||||
("RIPE::AS123456:RS-FOO", "RIPE::AS123456:RS-FOO"),
|
||||
|
||||
# fail validation
|
||||
("AS-FOO", False),
|
||||
@@ -170,6 +179,11 @@ def test_validate_prefix_overlap():
|
||||
("UNKNOWN::ASFOO", False),
|
||||
("AS-FOO RIPE:AS-FOO", False),
|
||||
("AS-FOO AS-FOO@RIPE", False),
|
||||
("RIPE::RS15562:RS-FOO", False),
|
||||
("RIPE::AS123456:RS-FOO:AS-FOO", False),
|
||||
|
||||
# > DATA_QUALITY_MAX_IRR_DEPTH
|
||||
("ripe::as-foo:as123:as345:as678", False),
|
||||
])
|
||||
def test_validate_irr_as_set(value, validated):
|
||||
if not validated:
|
||||
|
Reference in New Issue
Block a user