Przeglądaj źródła

fix(api): limit RRset subname labels to 63 characters

Peter Thomassen 4 lat temu
rodzic
commit
46f5875c1f

+ 20 - 0
api/desecapi/migrations/0012_rrset_label_length.py

@@ -0,0 +1,20 @@
+# Generated by Django 3.1.5 on 2021-01-14 12:51
+
+import desecapi.models
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('desecapi', '0011_captcha_kind'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='rrset',
+            name='subname',
+            field=models.CharField(blank=True, max_length=178, validators=[desecapi.models.validate_lower, django.core.validators.RegexValidator(code='invalid_subname', message="Subname can only use (lowercase) a-z, 0-9, ., -, and _, may start with a '*.', or just be '*'. Components may not exceed 63 characters.", regex='^([*]|(([*][.])?([a-z0-9_-]{1,63}[.])*[a-z0-9_-]{1,63}))$')]),
+        ),
+    ]

+ 2 - 2
api/desecapi/models.py

@@ -505,9 +505,9 @@ class RRset(ExportModelOperationsMixin('RRset'), models.Model):
         validators=[
         validators=[
             validate_lower,
             validate_lower,
             RegexValidator(
             RegexValidator(
-                regex=r'^([*]|(([*][.])?([a-z0-9_-]+[.])*[a-z0-9_-]+))$',
+                regex=r'^([*]|(([*][.])?([a-z0-9_-]{1,63}[.])*[a-z0-9_-]{1,63}))$',
                 message='Subname can only use (lowercase) a-z, 0-9, ., -, and _, '
                 message='Subname can only use (lowercase) a-z, 0-9, ., -, and _, '
-                        'may start with a \'*.\', or just be \'*\'.',
+                        'may start with a \'*.\', or just be \'*\'. Components may not exceed 63 characters.',
                 code='invalid_subname'
                 code='invalid_subname'
             )
             )
         ]
         ]

+ 7 - 2
api/desecapi/tests/test_rrsets.py

@@ -33,11 +33,16 @@ class AuthenticatedRRSetTestCase(AuthenticatedRRSetBaseTestCase):
         for subname in [
         for subname in [
             'aEroport',
             'aEroport',
             'AEROPORT',
             'AEROPORT',
-            'aéroport'
+            'aéroport',
+            'a' * 64,
         ]:
         ]:
             with self.assertRaises(ValidationError):
             with self.assertRaises(ValidationError):
                 RRset(domain=self.my_domain, subname=subname, ttl=60, type='A').save()
                 RRset(domain=self.my_domain, subname=subname, ttl=60, type='A').save()
-        RRset(domain=self.my_domain, subname='aeroport', ttl=60, type='A').save()
+        for subname in [
+            'aeroport',
+            'a' * 63,
+        ]:
+            RRset(domain=self.my_domain, subname=subname, ttl=60, type='A').save()
 
 
     def test_retrieve_my_rr_sets(self):
     def test_retrieve_my_rr_sets(self):
         for response in [
         for response in [

+ 5 - 0
test/e2e2/spec/test_api_rr_validation.py

@@ -326,3 +326,8 @@ def test_create_valid_non_canonical(api_user_domain: DeSECAPIV1Client, ns_lord:
 @pytest.mark.parametrize("rr_type,value", INVALID_RECORDS_PARAMS)
 @pytest.mark.parametrize("rr_type,value", INVALID_RECORDS_PARAMS)
 def test_create_invalid(api_user_domain: DeSECAPIV1Client, rr_type: str, value: str):
 def test_create_invalid(api_user_domain: DeSECAPIV1Client, rr_type: str, value: str):
     assert api_user_domain.rr_set_create(api_user_domain.domains[0], rr_type, [value]).status_code == 400
     assert api_user_domain.rr_set_create(api_user_domain.domains[0], rr_type, [value]).status_code == 400
+
+
+def test_create_long_subname(api_user_domain: DeSECAPIV1Client, ns_lord: NSClient):
+    assert api_user_domain.rr_set_create(api_user_domain.domains[0], "AAAA", ["::1"], subname="a"*63).status_code == 201
+    assert ns_lord.query(f"{'a'*63}.{api_user_domain.domains[0]}", "AAAA") == {"::1"}