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 | # maximum value to allow for prefix length on a v6 prefix | ||||||
| set_option("DATA_QUALITY_MAX_PREFIXLEN_V6", 116) | 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 = { | RATELIMITS = { | ||||||
|     "request_login_POST": "4/m", |     "request_login_POST": "4/m", | ||||||
|     "request_translation": "2/m", |     "request_translation": "2/m", | ||||||
|   | |||||||
| @@ -120,6 +120,7 @@ class RdapLookup(rdap.RdapClient): | |||||||
|         config = dict( |         config = dict( | ||||||
|             bootstrap_url=settings.RDAP_URL.rstrip("/"), |             bootstrap_url=settings.RDAP_URL.rstrip("/"), | ||||||
|             lacnic_apikey=settings.RDAP_LACNIC_APIKEY, |             lacnic_apikey=settings.RDAP_LACNIC_APIKEY, | ||||||
|  |             timeout=2.5, | ||||||
|         ) |         ) | ||||||
|         super(RdapLookup, self).__init__(config) |         super(RdapLookup, self).__init__(config) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -180,23 +180,62 @@ def validate_irr_as_set(value): | |||||||
|     for item in value.split(","): |     for item in value.split(","): | ||||||
|         item = item.upper() |         item = item.upper() | ||||||
|         source = None |         source = None | ||||||
|  |         as_set = None | ||||||
|  |  | ||||||
|         # <name>@<source> |         # <name>@<source> | ||||||
|         parts_match = re.match("^(AS|RS)-([\w\d\-]+)@(\w+)$", item) |         parts_match = re.match("^([\w\d\-:]+)@(\w+)$", item) | ||||||
|         if parts_match: |         if parts_match: | ||||||
|             source = parts_match.group(3) |             source = parts_match.group(2) | ||||||
|  |             as_set = parts_match.group(1) | ||||||
|  |  | ||||||
|         # <source>::<name> |         # <source>::<name> | ||||||
|         else: |         else: | ||||||
|             parts_match = re.match("^(\w+)::(AS|RS)-([\w\d\-]+)$", item) |             parts_match = re.match("^(\w+)::([\w\d\-:]+)$", item) | ||||||
|             if parts_match: |             if parts_match: | ||||||
|                 source = parts_match.group(1) |                 source = parts_match.group(1) | ||||||
|  |                 as_set = parts_match.group(2) | ||||||
|             else: |             else: | ||||||
|                 raise ValidationError(_("Invalid formatting: {} - should be AS-SET@SOURCE or SOURCE::AS-SET").format(item)) |                 raise ValidationError(_("Invalid formatting: {} - should be AS-SET@SOURCE or SOURCE::AS-SET").format(item)) | ||||||
|  |  | ||||||
|         if source not in IRR_SOURCE: |         if source not in IRR_SOURCE: | ||||||
|             raise ValidationError(_("Unknown IRR source: {}").format(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) |         validated.append(item) | ||||||
|  |  | ||||||
|     return " ".join(validated) |     return " ".join(validated) | ||||||
|   | |||||||
| @@ -154,6 +154,7 @@ settings.configure( | |||||||
|     DATA_QUALITY_MAX_PREFIXLEN_V4=28, |     DATA_QUALITY_MAX_PREFIXLEN_V4=28, | ||||||
|     DATA_QUALITY_MIN_PREFIXLEN_V6=64, |     DATA_QUALITY_MIN_PREFIXLEN_V6=64, | ||||||
|     DATA_QUALITY_MAX_PREFIXLEN_V6=116, |     DATA_QUALITY_MAX_PREFIXLEN_V6=116, | ||||||
|  |     DATA_QUALITY_MAX_IRR_DEPTH=3, | ||||||
|     TUTORIAL_MODE=False, |     TUTORIAL_MODE=False, | ||||||
|     CAPTCHA_TEST_MODE=True, |     CAPTCHA_TEST_MODE=True, | ||||||
|     SITE_ID=1, |     SITE_ID=1, | ||||||
|   | |||||||
| @@ -156,11 +156,20 @@ def test_validate_prefix_overlap(): | |||||||
|     # success validation |     # success validation | ||||||
|     ("RIPE::AS-FOO", "RIPE::AS-FOO"), |     ("RIPE::AS-FOO", "RIPE::AS-FOO"), | ||||||
|     ("AS-FOO@RIPE", "AS-FOO@RIPE"), |     ("AS-FOO@RIPE", "AS-FOO@RIPE"), | ||||||
|  |     ("AS-FOO-BAR@RIPE", "AS-FOO-BAR@RIPE"), | ||||||
|     ("ripe::as-foo", "RIPE::AS-FOO"), |     ("ripe::as-foo", "RIPE::AS-FOO"), | ||||||
|     ("as-foo@ripe", "AS-FOO@RIPE"), |     ("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"), |     ("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 |     # fail validation | ||||||
|     ("AS-FOO", False), |     ("AS-FOO", False), | ||||||
| @@ -170,6 +179,11 @@ def test_validate_prefix_overlap(): | |||||||
|     ("UNKNOWN::ASFOO", False), |     ("UNKNOWN::ASFOO", False), | ||||||
|     ("AS-FOO RIPE:AS-FOO", False), |     ("AS-FOO RIPE:AS-FOO", False), | ||||||
|     ("AS-FOO AS-FOO@RIPE", 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): | def test_validate_irr_as_set(value, validated): | ||||||
|     if not validated: |     if not validated: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user