tsig_keyring.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  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. """
  16. This module conveniently keeps a copy of TSIG keyring loaded from the
  17. tsig_keys module.
  18. """
  19. import isc.dns
  20. updater = None
  21. class Unexpected(Exception):
  22. """
  23. Raised when an unexpected operation is requested by the user of this
  24. module. For example if calling keyring() before init_keyring().
  25. """
  26. pass
  27. class AddError(Exception):
  28. """
  29. Raised when an key can not be added. This usually means there's a
  30. duplicity.
  31. """
  32. pass
  33. class Updater:
  34. """
  35. The updater of tsig key ring. Not to be used directly.
  36. """
  37. def __init__(self, session):
  38. """
  39. Constructor. Pass the ccsession object so the key ring can be
  40. downloaded.
  41. """
  42. self._session = session
  43. self._keyring = isc.dns.TSIGKeyRing()
  44. session.add_remote_config_by_name('tsig_keys', self._update)
  45. self._update()
  46. def _update(self):
  47. """
  48. Update the key ring by the configuration.
  49. Note that this function is used as a callback, but can raise
  50. on bad data. The bad data is expected to be handled by the
  51. configuration plugin and not be allowed as far as here.
  52. """
  53. data = self._session.get_remote_config_value('tsig_keys', 'keys')
  54. if data is not None: # There's an update
  55. keyring = isc.dns.TSIGKeyRing()
  56. for key_data in data:
  57. key = isc.dns.TSIGKey(key_data)
  58. if keyring.add(key) != isc.dns.TSIGKeyRing.SUCCESS:
  59. raise AddError("Can't add key " + str(key))
  60. self._keyring = keyring
  61. def get_keyring(self):
  62. """
  63. Return the current key ring.
  64. """
  65. return self._keyring
  66. def deinit(self):
  67. """
  68. Unregister from getting updates. The object will not be
  69. usable any more after this.
  70. """
  71. self._session.remove_remote_config('tsig_keys')
  72. def keyring():
  73. """
  74. Get the current key ring. You need to call init_keyring first.
  75. """
  76. if updater is None:
  77. raise Unexpected("You need to initialize the keyring first by " +
  78. "init_keyring()")
  79. return updater.get_keyring()
  80. def init_keyring(session):
  81. """
  82. Initialize the key ring for future use. It does nothing if already
  83. initialized.
  84. """
  85. global updater
  86. if updater is None:
  87. updater = Updater(session)
  88. def deinit_keyring():
  89. """
  90. Deinit key ring. Yoeu can no longer access keyring() after this.
  91. Does nothing if not initialized.
  92. """
  93. global updater
  94. if updater is not None:
  95. updater.deinit()
  96. updater = None