zone_config_tests.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. # Copyright (C) 2012 Internet Systems Consortium.
  2. #
  3. # Permission to use, copy, modify, and distribute this software for any
  4. # purpose with or without fee is hereby granted, provided that the above
  5. # copyright notice and this permission notice appear in all copies.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
  8. # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  9. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  10. # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  12. # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  14. # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. import isc.log
  16. from isc.dns import *
  17. from isc.datasrc import DataSourceClient
  18. from isc.ddns.zone_config import *
  19. import isc.acl.dns
  20. from isc.acl.acl import ACCEPT, REJECT, DROP, LoaderError
  21. import unittest
  22. import socket
  23. # Some common test parameters
  24. TEST_ZONE_NAME = Name('example.org')
  25. TEST_SECONDARY_ZONE_NAME = Name('example.com')
  26. TEST_RRCLASS = RRClass.IN()
  27. TEST_TSIG_KEY = TSIGKey("example.com:SFuWd/q99SzF8Yzd1QbB9g==")
  28. TEST_ACL_CONTEXT = isc.acl.dns.RequestContext(
  29. socket.getaddrinfo("192.0.2.1", 1234, 0, socket.SOCK_DGRAM,
  30. socket.IPPROTO_UDP, socket.AI_NUMERICHOST)[0][4])
  31. class FakeDataSourceClient:
  32. '''Faked data source client used in the ZoneConfigTest.
  33. It emulates isc.datasrc.DataSourceClient, but only has to provide
  34. the find_zone() interface (and only the first element of the return
  35. value matters). By default it returns 'SUCCESS' (exact match) for
  36. any input. It can be dynamically customized via the set_find_result()
  37. method.
  38. '''
  39. def __init__(self):
  40. self.__find_result = DataSourceClient.SUCCESS
  41. def find_zone(self, zname):
  42. return (self.__find_result, None)
  43. def set_find_result(self, result):
  44. self.__find_result = result
  45. class ZoneConfigTest(unittest.TestCase):
  46. '''Some basic tests for the ZoneConfig class.'''
  47. def setUp(self):
  48. self.__datasrc_client = FakeDataSourceClient()
  49. self.zconfig = ZoneConfig({(TEST_SECONDARY_ZONE_NAME, TEST_RRCLASS)},
  50. TEST_RRCLASS, self.__datasrc_client)
  51. def test_find_zone(self):
  52. # Primay zone case: zone is in the data source, and not in secondaries
  53. self.assertEqual((ZONE_PRIMARY, self.__datasrc_client),
  54. (self.zconfig.find_zone(TEST_ZONE_NAME, TEST_RRCLASS)))
  55. # Secondary zone case: zone is in the data source and in secondaries.
  56. self.assertEqual((ZONE_SECONDARY, None),
  57. (self.zconfig.find_zone(TEST_SECONDARY_ZONE_NAME,
  58. TEST_RRCLASS)))
  59. # 'not found' case: zone not in the data source.
  60. self.__datasrc_client.set_find_result(DataSourceClient.NOTFOUND)
  61. self.assertEqual((ZONE_NOTFOUND, None),
  62. (self.zconfig.find_zone(Name('example'),
  63. TEST_RRCLASS)))
  64. # same for the partial match
  65. self.__datasrc_client.set_find_result(DataSourceClient.PARTIALMATCH)
  66. self.assertEqual((ZONE_NOTFOUND, None),
  67. (self.zconfig.find_zone(Name('example'),
  68. TEST_RRCLASS)))
  69. # a bit unusual case: zone not in the data source, but in secondaries.
  70. # this is probably a configuration error, but ZoneConfig doesn't do
  71. # this level check.
  72. self.__datasrc_client.set_find_result(DataSourceClient.NOTFOUND)
  73. self.assertEqual((ZONE_NOTFOUND, None),
  74. (self.zconfig.find_zone(TEST_ZONE_NAME,
  75. TEST_RRCLASS)))
  76. # zone class doesn't match (but zone name matches)
  77. self.__datasrc_client.set_find_result(DataSourceClient.SUCCESS)
  78. zconfig = ZoneConfig({(TEST_SECONDARY_ZONE_NAME, TEST_RRCLASS)},
  79. RRClass.CH(), self.__datasrc_client)
  80. self.assertEqual((ZONE_NOTFOUND, None),
  81. (zconfig.find_zone(TEST_ZONE_NAME, TEST_RRCLASS)))
  82. # similar to the previous case, but also in the secondary list
  83. zconfig = ZoneConfig({(TEST_ZONE_NAME, TEST_RRCLASS)},
  84. RRClass.CH(), self.__datasrc_client)
  85. self.assertEqual((ZONE_NOTFOUND, None),
  86. (zconfig.find_zone(TEST_ZONE_NAME, TEST_RRCLASS)))
  87. # check some basic tests varying the secondary list.
  88. # empty secondary list doesn't cause any disruption.
  89. zconfig = ZoneConfig(set(), TEST_RRCLASS, self.__datasrc_client)
  90. self.assertEqual((ZONE_PRIMARY, self.__datasrc_client),
  91. self.zconfig.find_zone(TEST_ZONE_NAME, TEST_RRCLASS))
  92. # adding some mulitle tuples, including subdomain of the test zone
  93. # name, and the same zone name but a different class
  94. zconfig = ZoneConfig({(TEST_SECONDARY_ZONE_NAME, TEST_RRCLASS),
  95. (Name('example'), TEST_RRCLASS),
  96. (Name('sub.example.org'), TEST_RRCLASS),
  97. (TEST_ZONE_NAME, RRClass.CH())},
  98. TEST_RRCLASS, self.__datasrc_client)
  99. self.assertEqual((ZONE_PRIMARY, self.__datasrc_client),
  100. self.zconfig.find_zone(TEST_ZONE_NAME, TEST_RRCLASS))
  101. class ACLConfigTest(unittest.TestCase):
  102. def setUp(self):
  103. self.__datasrc_client = FakeDataSourceClient()
  104. self.__zconfig = ZoneConfig({(TEST_SECONDARY_ZONE_NAME, TEST_RRCLASS)},
  105. TEST_RRCLASS, self.__datasrc_client)
  106. def test_get_update_acl(self):
  107. # By default, no ACL is set, and the default ACL is "reject all"
  108. acl = self.__zconfig.get_update_acl(TEST_ZONE_NAME, TEST_RRCLASS)
  109. self.assertEqual(REJECT, acl.execute(TEST_ACL_CONTEXT))
  110. # Add a map entry that would match the request, and it should now be
  111. # accepted.
  112. acl_map = {(TEST_ZONE_NAME, TEST_RRCLASS):
  113. REQUEST_LOADER.load([{"action": "ACCEPT"}])}
  114. self.__zconfig.set_update_acl_map(acl_map)
  115. acl = self.__zconfig.get_update_acl(TEST_ZONE_NAME, TEST_RRCLASS)
  116. self.assertEqual(ACCEPT, acl.execute(TEST_ACL_CONTEXT))
  117. # 'All reject' ACL will still apply for any other zones
  118. acl = self.__zconfig.get_update_acl(Name('example.com'), TEST_RRCLASS)
  119. self.assertEqual(REJECT, acl.execute(TEST_ACL_CONTEXT))
  120. acl = self.__zconfig.get_update_acl(TEST_ZONE_NAME, RRClass.CH())
  121. self.assertEqual(REJECT, acl.execute(TEST_ACL_CONTEXT))
  122. # Test with a map with a few more ACL entries. Should be nothing
  123. # special.
  124. acl_map = {(Name('example.com'), TEST_RRCLASS):
  125. REQUEST_LOADER.load([{"action": "REJECT"}]),
  126. (TEST_ZONE_NAME, TEST_RRCLASS):
  127. REQUEST_LOADER.load([{"action": "ACCEPT"}]),
  128. (TEST_ZONE_NAME, RRClass.CH()):
  129. REQUEST_LOADER.load([{"action": "DROP"}])}
  130. self.__zconfig.set_update_acl_map(acl_map)
  131. acl = self.__zconfig.get_update_acl(TEST_ZONE_NAME, TEST_RRCLASS)
  132. self.assertEqual(ACCEPT, acl.execute(TEST_ACL_CONTEXT))
  133. acl = self.__zconfig.get_update_acl(Name('example.com'), TEST_RRCLASS)
  134. self.assertEqual(REJECT, acl.execute(TEST_ACL_CONTEXT))
  135. acl = self.__zconfig.get_update_acl(TEST_ZONE_NAME, RRClass.CH())
  136. self.assertEqual(DROP, acl.execute(TEST_ACL_CONTEXT))
  137. if __name__ == "__main__":
  138. isc.log.init("bind10")
  139. isc.log.resetUnitTestRootLogger()
  140. unittest.main()