|
# 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.
"""
Tests for isc.server_common.tsig_keyring.
"""
import unittest
import isc.log
from isc.server_common.tsig_keyring import *
import isc.dns
from isc.testutils.ccsession_mock import MockModuleCCSession
class Session(MockModuleCCSession):
"""
A class pretending to be the config session.
"""
def __init__(self):
MockModuleCCSession.__init__(self)
self._name = None
self._callback = None
self._remove_name = None
self._data = None
def add_remote_config_by_name(self, name, callback):
self._name = name
self._callback = callback
def remove_remote_config(self, name):
self._remove_name = name
def get_remote_config_value(self, module, name):
46 if module != 'tsig_keys' or name != 'keys':
raise Exception("Asked for bad data element")
return (self._data, False)
class TSIGKeyRingTest(unittest.TestCase):
"""
Tests for the isc.server_common.tsig_keyring module.
"""
def setUp(self):
self.__session = Session()
self.__sha1name = isc.dns.Name('hmac-sha1')
self.__md5name = isc.dns.Name('hmac-md5.sig-alg.reg.int')
def tearDown(self):
deinit_keyring()
def __do_init(self):
init_keyring(self.__session)
# Some initialization happened
self.assertEqual('tsig_keys', self.__session._name)
def test_initialization(self):
"""
Test we can initialize and deintialize the keyring. It also
tests the interaction with the keyring() function.
"""
# The keyring function raises until initialized
self.assertRaises(Unexpected, get_keyring)
self.__do_init()
current_keyring = get_keyring()
self.assertTrue(isinstance(current_keyring, isc.dns.TSIGKeyRing))
# Another initialization does nothing
self.__do_init()
self.assertEqual(current_keyring, get_keyring())
# When we deinitialize it, it no longer provides the keyring
deinit_keyring()
self.assertEqual('tsig_keys', self.__session._remove_name)
self.__session._remove_name = None
self.assertRaises(Unexpected, get_keyring)
# Another deinitialization doesn't change anything
deinit_keyring()
self.assertRaises(Unexpected, get_keyring)
self.assertIsNone(self.__session._remove_name)
# Test we can init it again (not expected, but not forbidden)
self.__do_init()
self.assertTrue(isinstance(get_keyring(), isc.dns.TSIGKeyRing))
def test_load(self):
"""
Test it can load the keys from the configuration and reload them
when the data change.
"""
# Initial load
self.__session._data = ['key:MTIzNAo=:hmac-sha1']
self.__do_init()
keys = get_keyring()
self.assertEqual(1, keys.size())
(rcode, key) = keys.find(isc.dns.Name('key'), self.__sha1name)
self.assertEqual(isc.dns.TSIGKeyRing.SUCCESS, rcode)
self.assertEqual(isc.dns.Name('key'), key.get_key_name())
# There's a change in the configuration
# (The key has a different name)
self.__session._data = ['key.example:MTIzNAo=:hmac-sha1']
self.__session._callback()
orig_keys = keys
keys = get_keyring()
self.assertNotEqual(keys, orig_keys)
self.assertEqual(1, keys.size())
# The old key is not here
(rcode, key) = keys.find(isc.dns.Name('key'), self.__sha1name)
self.assertEqual(isc.dns.TSIGKeyRing.NOTFOUND, rcode)
self.assertIsNone(key)
# But the new one is
(rcode, key) = keys.find(isc.dns.Name('key.example'), self.__sha1name)
self.assertEqual(isc.dns.TSIGKeyRing.SUCCESS, rcode)
self.assertEqual(isc.dns.Name('key.example'), key.get_key_name())
def test_empty_update(self):
"""
Test an update that doesn't carry the correct element doesn't change
anything.
"""
self.__session._data = ['key:MTIzNAo=:hmac-sha1']
self.__do_init()
keys = get_keyring()
self.__session._data = None
self.__session._callback()
self.assertEqual(keys, get_keyring())
def test_no_keys_update(self):
"""
Test we can update the keyring to be empty.
"""
self.__session._data = ['key:MTIzNAo=:hmac-sha1']
self.__do_init()
keys = get_keyring()
self.assertEqual(1, keys.size())
self.__session._data = []
self.__session._callback()
keys = get_keyring()
self.assertEqual(0, keys.size())
def test_update_multi(self):
"""
Test we can handle multiple keys in startup/update.
"""
# Init
self.__session._data = ['key:MTIzNAo=:hmac-sha1', 'key2:MTIzNAo=']
self.__do_init()
keys = get_keyring()
self.assertEqual(2, keys.size())
(rcode, key) = keys.find(isc.dns.Name('key'), self.__sha1name)
self.assertEqual(isc.dns.TSIGKeyRing.SUCCESS, rcode)
self.assertEqual(isc.dns.Name('key'), key.get_key_name())
(rcode, key) = keys.find(isc.dns.Name('key2'), self.__md5name)
self.assertEqual(isc.dns.TSIGKeyRing.SUCCESS, rcode)
self.assertEqual(isc.dns.Name('key2'), key.get_key_name())
# Update
self.__session._data = ['key1:MTIzNAo=:hmac-sha1', 'key3:MTIzNAo=']
self.__session._callback()
keys = get_keyring()
self.assertEqual(2, keys.size())
(rcode, key) = keys.find(isc.dns.Name('key1'), self.__sha1name)
self.assertEqual(isc.dns.TSIGKeyRing.SUCCESS, rcode)
self.assertEqual(isc.dns.Name('key1'), key.get_key_name())
(rcode, key) = keys.find(isc.dns.Name('key3'), self.__md5name)
self.assertEqual(isc.dns.TSIGKeyRing.SUCCESS, rcode)
self.assertEqual(isc.dns.Name('key3'), key.get_key_name())
def test_update_bad(self):
"""
Test it raises on bad updates and doesn't change anything.
"""
self.__session._data = ['key:MTIzNAo=:hmac-sha1']
self.__do_init()
keys = get_keyring()
# Bad TSIG string
self.__session._data = ['key:this makes no sense:really']
self.assertRaises(isc.dns.InvalidParameter, self.__session._callback)
self.assertEqual(keys, get_keyring())
# A duplicity
self.__session._data = ['key:MTIzNAo=:hmac-sha1', 'key:MTIzNAo=:hmac-sha1']
self.assertRaises(AddError, self.__session._callback)
self.assertEqual(keys, get_keyring())
exitif __name__ == "__main__":
isc.log.init("bind10") # FIXME Should this be needed?
isc.log.resetUnitTestRootLogger()
unittest.main()
|