testdyndns12update.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import random
  2. from rest_framework import status
  3. from desecapi.tests.base import DynDomainOwnerTestCase
  4. class DynDNS12UpdateTest(DynDomainOwnerTestCase):
  5. def assertRRSet(self, name, subname, type_, content):
  6. response = self.client_token_authorized.get(self.reverse('v1:rrset', name=name, subname=subname, type=type_))
  7. if content:
  8. self.assertStatus(response, status.HTTP_200_OK)
  9. self.assertEqual(response.data['records'][0], content)
  10. self.assertEqual(response.data['ttl'], 60)
  11. else:
  12. self.assertStatus(response, status.HTTP_404_NOT_FOUND)
  13. def assertIP(self, ipv4=None, ipv6=None, name=None):
  14. name = name or self.my_domain.name.lower()
  15. self.assertRRSet(name, '', 'A', ipv4)
  16. self.assertRRSet(name, '', 'AAAA', ipv6)
  17. def test_identification_by_domain_name(self):
  18. self.client.set_credentials_basic_auth(self.my_domain.name + '.invalid', self.token.key)
  19. response = self.assertDynDNS12NoUpdate(mock_remote_addr='10.5.5.6')
  20. self.assertStatus(response, status.HTTP_404_NOT_FOUND)
  21. def test_identification_by_query_params(self):
  22. # /update?username=foobar.dedyn.io&password=secret
  23. self.client.set_credentials_basic_auth(None, None)
  24. response = self.assertDynDNS12Update(username=self.my_domain.name, password=self.token.key)
  25. self.assertStatus(response, status.HTTP_200_OK)
  26. self.assertEqual(response.data, 'good')
  27. self.assertIP(ipv4='127.0.0.1')
  28. def test_deviant_ttl(self):
  29. """
  30. The dynamic update will try to set the TTL to 60. Here, we create
  31. a record with a different TTL beforehand and then make sure that
  32. updates still work properly.
  33. """
  34. with self.assertPdnsRequests(
  35. self.request_pdns_zone_update(self.my_domain.name),
  36. self.request_pdns_zone_notify(self.my_domain.name),
  37. ):
  38. response = self.client_token_authorized.patch_rr_set(
  39. self.my_domain.name.lower(), subname='', type_='A', ttl=3600)
  40. self.assertStatus(response, status.HTTP_200_OK)
  41. response = self.assertDynDNS12Update(self.my_domain.name)
  42. self.assertStatus(response, status.HTTP_200_OK)
  43. self.assertEqual(response.data, 'good')
  44. self.assertIP(ipv4='127.0.0.1')
  45. def test_ddclient_dyndns1_v4_success(self):
  46. # /nic/dyndns?action=edit&started=1&hostname=YES&host_id=foobar.dedyn.io&myip=10.1.2.3
  47. with self.assertPdnsRequests(
  48. self.request_pdns_zone_update(self.my_domain.name),
  49. self.request_pdns_zone_notify(self.my_domain.name),
  50. ):
  51. response = self.client.get(
  52. self.reverse('v1:dyndns12update'),
  53. {
  54. 'action': 'edit',
  55. 'started': 1,
  56. 'hostname': 'YES',
  57. 'host_id': self.my_domain.name,
  58. 'myip': '10.1.2.3'
  59. }
  60. )
  61. self.assertStatus(response, status.HTTP_200_OK)
  62. self.assertEqual(response.data, 'good')
  63. self.assertIP(ipv4='10.1.2.3')
  64. def test_ddclient_dyndns1_v6_success(self):
  65. # /nic/dyndns?action=edit&started=1&hostname=YES&host_id=foobar.dedyn.io&myipv6=::1337
  66. response = self.assertDynDNS12Update(
  67. domain_name=self.my_domain.name,
  68. action='edit',
  69. started=1,
  70. hostname='YES',
  71. host_id=self.my_domain.name,
  72. myipv6='::1337'
  73. )
  74. self.assertStatus(response, status.HTTP_200_OK)
  75. self.assertEqual(response.data, 'good')
  76. self.assertIP(ipv4='127.0.0.1', ipv6='::1337')
  77. def test_ddclient_dyndns2_v4_success(self):
  78. # /nic/update?system=dyndns&hostname=foobar.dedyn.io&myip=10.2.3.4
  79. response = self.assertDynDNS12Update(
  80. domain_name=self.my_domain.name,
  81. system='dyndns',
  82. hostname=self.my_domain.name,
  83. myip='10.2.3.4',
  84. )
  85. self.assertStatus(response, status.HTTP_200_OK)
  86. self.assertEqual(response.data, 'good')
  87. self.assertIP(ipv4='10.2.3.4')
  88. def test_ddclient_dyndns2_v6_success(self):
  89. # /nic/update?system=dyndns&hostname=foobar.dedyn.io&myipv6=::1338
  90. response = self.assertDynDNS12Update(
  91. domain_name=self.my_domain.name,
  92. system='dyndns',
  93. hostname=self.my_domain.name,
  94. myipv6='::666',
  95. )
  96. self.assertStatus(response, status.HTTP_200_OK)
  97. self.assertEqual(response.data, 'good')
  98. self.assertIP(ipv4='127.0.0.1', ipv6='::666')
  99. def test_fritz_box(self):
  100. # /
  101. response = self.assertDynDNS12Update(self.my_domain.name)
  102. self.assertStatus(response, status.HTTP_200_OK)
  103. self.assertEqual(response.data, 'good')
  104. self.assertIP(ipv4='127.0.0.1')
  105. def test_unset_ip(self):
  106. for (v4, v6) in [
  107. ('127.0.0.1', '::1'),
  108. ('127.0.0.1', ''),
  109. ('', '::1'),
  110. ('', ''),
  111. ]:
  112. response = self.assertDynDNS12Update(self.my_domain.name, ip=v4, ipv6=v6)
  113. self.assertStatus(response, status.HTTP_200_OK)
  114. self.assertEqual(response.data, 'good')
  115. self.assertIP(ipv4=v4, ipv6=v6)
  116. class SingleDomainDynDNS12UpdateTest(DynDNS12UpdateTest):
  117. NUM_OWNED_DOMAINS = 1
  118. def test_identification_by_token(self):
  119. self.client.set_credentials_basic_auth('', self.token.key)
  120. response = self.assertDynDNS12Update(self.my_domain.name, mock_remote_addr='10.5.5.6')
  121. self.assertStatus(response, status.HTTP_200_OK)
  122. self.assertEqual(response.data, 'good')
  123. self.assertIP(ipv4='10.5.5.6')
  124. class MultipleDomainDynDNS12UpdateTest(DynDNS12UpdateTest):
  125. NUM_OWNED_DOMAINS = 4
  126. def test_identification_by_token(self):
  127. """
  128. Test if the conflict of having multiple domains, but not specifying which to update is correctly recognized.
  129. """
  130. self.client.set_credentials_basic_auth('', self.token.key)
  131. response = self.client.get(self.reverse('v1:dyndns12update'), REMOTE_ADDR='10.5.5.7')
  132. self.assertStatus(response, status.HTTP_409_CONFLICT)
  133. class MixedCaseDynDNS12UpdateTestCase(DynDNS12UpdateTest):
  134. @staticmethod
  135. def random_casing(s):
  136. return ''.join([c.lower() if random.choice([True, False]) else c.upper() for c in s])
  137. def setUp(self):
  138. super().setUp()
  139. self.my_domain.name = self.random_casing(self.my_domain.name)
  140. class UppercaseDynDNS12UpdateTestCase(DynDNS12UpdateTest):
  141. def setUp(self):
  142. super().setUp()
  143. self.my_domain.name = self.my_domain.name.upper()