# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ This module conveniently keeps a copy of TSIG keyring loaded from the tsig_keys module. """ import isc.dns updater = None class Unexpected(Exception): """ Raised when an unexpected operation is requested by the user of this module. For example if calling keyring() before init_keyring(). """ pass class AddError(Exception): """ Raised when an key can not be added. This usually means there's a duplicity. """ pass class Updater: """ The updater of tsig key ring. Not to be used directly. """ def __init__(self, session): """ Constructor. Pass the ccsession object so the key ring can be downloaded. """ self._session = session self._keyring = isc.dns.TSIGKeyRing() session.add_remote_config_by_name('tsig_keys', self._update) self._update() def _update(self): """ Update the key ring by the configuration. Note that this function is used as a callback, but can raise on bad data. The bad data is expected to be handled by the configuration plugin and not be allowed as far as here. """ data = self._session.get_remote_config_value('tsig_keys', 'keys') if data is not None: # There's an update keyring = isc.dns.TSIGKeyRing() for key_data in data: key = isc.dns.TSIGKey(key_data) if keyring.add(key) != isc.dns.TSIGKeyRing.SUCCESS: raise AddError("Can't add key " + str(key)) self._keyring = keyring def get_keyring(self): """ Return the current key ring. """ return self._keyring def deinit(self): """ Unregister from getting updates. The object will not be usable any more after this. """ self._session.remove_remote_config('tsig_keys') def keyring(): """ Get the current key ring. You need to call init_keyring first. """ if updater is None: raise Unexpected("You need to initialize the keyring first by " + "init_keyring()") return updater.get_keyring() def init_keyring(session): """ Initialize the key ring for future use. It does nothing if already initialized. """ global updater if updater is None: updater = Updater(session) def deinit_keyring(): """ Deinit key ring. Yoeu can no longer access keyring() after this. Does nothing if not initialized. """ global updater if updater is not None: updater.deinit() updater = None