2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-02 15:05:16 +00:00

[1351] Use TSIG key ring in b10-xfrin

instead of separately configured keys;

with this change, the Xfrin/zones[X]/tsig_key value is not interpreted as a full key string, but as the name to look up in the /tsig_keys/keys list (like acls do)
This commit is contained in:
Jelte Jansen
2012-12-06 19:04:32 +01:00
parent 181226ac0c
commit 331a48e08d
6 changed files with 105 additions and 27 deletions

View File

@@ -758,7 +758,7 @@ as a dependency earlier -->
If the configure fails, it may be due to missing or old If the configure fails, it may be due to missing or old
dependencies. dependencies.
</para> </para>
<note> <note>
<para>For notes on configuring and building DHCPv6 with MySQL see <xref linkend="dhcp6-install">.</xref></para> <para>For notes on configuring and building DHCPv6 with MySQL see <xref linkend="dhcp6-install">.</xref></para>
</note> </note>
@@ -1841,10 +1841,8 @@ config set /Boss/components/b10-zonemgr/kind dispensable
<para> <para>
The key ring lives in the configuration in "tsig_keys/keys". Most of The key ring lives in the configuration in "tsig_keys/keys". Most of
the system uses the keys from there &mdash; ACLs, authoritative server to the system uses the keys from there &mdash; ACLs, authoritative server to
sign responses to signed queries, and <command>b10-xfrout</command> sign responses to signed queries, and <command>b10-xfrin</command>
to sign transfers. The <command>b10-xfrin</command> uses its own and <command>b10-xfrout</command> to sign transfers.
configuration for keys, but that will be fixed in Trac ticket
<ulink url="http://bind10.isc.org/ticket/1351">#1351</ulink>.
</para> </para>
<para> <para>
@@ -2721,6 +2719,15 @@ TODO
</para> </para>
</section> </section>
<section>
<title>TSIG</title>
If you want to use TSIG for incoming transfers, a system wide TSIG
key ring must be configured (see <xref linkend="tsig-key-ring"/>).
To specify a key to use, set tsig_key value to the name of the key
to use from the key ring.
&gt; <userinput>config set Xfrin/zones[0]/tsig_key "<option>example.key</option>"</userinput>
</section>
<section> <section>
<title>Enabling IXFR</title> <title>Enabling IXFR</title>
<para> <para>

View File

@@ -112,20 +112,18 @@ in separate zonemgr process.
<varname>master_addr</varname> (the zone master to transfer from), <varname>master_addr</varname> (the zone master to transfer from),
<varname>master_port</varname> (defaults to 53), <varname>master_port</varname> (defaults to 53),
<varname>use_ixfr</varname> (defaults to false), and <varname>use_ixfr</varname> (defaults to false), and
<varname>tsig_key</varname> (optional TSIG key to use). <varname>tsig_key</varname> (optional TSIG key name to use).
The <varname>tsig_key</varname> is specified using a full string The <varname>tsig_key</varname> is specified using a name that
colon-delimited name:key:algorithm representation (e.g. corresponds to one of the TSIG keys configured in the global
<quote>foo.example.org:EvABsfU2h7uofnmqaRCrhHunGsd=:hmac-sha1</quote>). TSIG key ring (/tsig_keys/keys).</quote>).
</para> </para>
<!-- TODO: document this better --> <!-- TODO: document this better -->
<!-- TODO: the tsig_key format may change -->
<para> <para>
(The site-wide <varname>master_addr</varname> and (The site-wide <varname>master_addr</varname> and
<varname>master_port</varname> configurations are deprecated; <varname>master_port</varname> configurations are deprecated;
use the <varname>zones</varname> list configuration instead.) use the <varname>zones</varname> list configuration instead.)
</para> </para>
<!-- NOTE: also tsig_key but not mentioning since so short lived. -->
<!-- TODO: formating --> <!-- TODO: formating -->
<para> <para>

View File

@@ -139,6 +139,14 @@ class MockCC(MockModuleCCSession):
if identifier == "zones/use_ixfr": if identifier == "zones/use_ixfr":
return False return False
def get_remote_config_value(self, module, identifier):
if module == 'tsig_keys' and identifier == 'keys':
return (['example.com.key.:EvAAsfU2h7uofnmqaTCrhHunGsc=',
'bad.key.:EvAAsfU2h7uofnmqaTCrhHu' ], True)
else:
raise Exception('MockCC requested for unknown config value ' +
+ module + "/" + identifier)
def remove_remote_config(self, module_name): def remove_remote_config(self, module_name):
pass pass
@@ -2427,9 +2435,10 @@ class TestXfrin(unittest.TestCase):
self.assertEqual(str(zone_info.master_addr), zone_config['master_addr']) self.assertEqual(str(zone_info.master_addr), zone_config['master_addr'])
self.assertEqual(zone_info.master_port, zone_config['master_port']) self.assertEqual(zone_info.master_port, zone_config['master_port'])
if 'tsig_key' in zone_config: if 'tsig_key' in zone_config:
self.assertEqual(zone_info.tsig_key.to_text(), TSIGKey(zone_config['tsig_key']).to_text()) self.assertEqual(zone_info.tsig_key_name.to_text(),
Name(zone_config['tsig_key']).to_text())
else: else:
self.assertIsNone(zone_info.tsig_key) self.assertIsNone(zone_info.tsig_key_name)
if 'use_ixfr' in zone_config and\ if 'use_ixfr' in zone_config and\
zone_config.get('use_ixfr'): zone_config.get('use_ixfr'):
self.assertTrue(zone_info.use_ixfr) self.assertTrue(zone_info.use_ixfr)
@@ -2562,7 +2571,7 @@ class TestXfrin(unittest.TestCase):
{ 'name': 'test2.example.', { 'name': 'test2.example.',
'master_addr': '192.0.2.9', 'master_addr': '192.0.2.9',
'master_port': 53, 'master_port': 53,
'tsig_key': 'badkey' 'tsig_key': 'badkey..'
} }
]} ]}
self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1) self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
@@ -2581,13 +2590,14 @@ class TestXfrin(unittest.TestCase):
self.assertEqual(self.xfr.config_handler(config)['result'][0], 0) self.assertEqual(self.xfr.config_handler(config)['result'][0], 0)
self._check_zones_config(config) self._check_zones_config(config)
def common_ixfr_setup(self, xfr_mode, use_ixfr): def common_ixfr_setup(self, xfr_mode, use_ixfr, tsig_key_str = None):
# This helper method explicitly sets up a zone configuration with # This helper method explicitly sets up a zone configuration with
# use_ixfr, and invokes either retransfer or refresh. # use_ixfr, and invokes either retransfer or refresh.
# Shared by some of the following test cases. # Shared by some of the following test cases.
config = {'zones': [ config = {'zones': [
{'name': 'example.com.', {'name': 'example.com.',
'master_addr': '192.0.2.1', 'master_addr': '192.0.2.1',
'tsig_key': tsig_key_str,
'use_ixfr': use_ixfr}]} 'use_ixfr': use_ixfr}]}
self.assertEqual(self.xfr.config_handler(config)['result'][0], 0) self.assertEqual(self.xfr.config_handler(config)['result'][0], 0)
self.assertEqual(self.xfr.command_handler(xfr_mode, self.assertEqual(self.xfr.command_handler(xfr_mode,
@@ -2603,6 +2613,34 @@ class TestXfrin(unittest.TestCase):
self.common_ixfr_setup('refresh', True) self.common_ixfr_setup('refresh', True)
self.assertEqual(RRType.IXFR(), self.xfr.xfrin_started_request_type) self.assertEqual(RRType.IXFR(), self.xfr.xfrin_started_request_type)
def test_command_handler_retransfer_with_tsig(self):
self.common_ixfr_setup('retransfer', False, 'example.com.key')
self.assertEqual(RRType.AXFR(), self.xfr.xfrin_started_request_type)
def test_command_handler_retransfer_with_tsig_bad_key(self):
# bad keys should not reach xfrin, but should they somehow,
# they are ignored (and result in 'key not found' + error log).
self.assertRaises(XfrinZoneInfoException, self.common_ixfr_setup,
'retransfer', False, 'bad.key')
def test_command_handler_retransfer_with_tsig_unknown_key(self):
self.assertRaises(XfrinZoneInfoException, self.common_ixfr_setup,
'retransfer', False, 'no.such.key')
def test_command_handler_refresh_with_tsig(self):
self.common_ixfr_setup('refresh', False, 'example.com.key')
self.assertEqual(RRType.AXFR(), self.xfr.xfrin_started_request_type)
def test_command_handler_refresh_with_tsig_bad_key(self):
# bad keys should not reach xfrin, but should they somehow,
# they are ignored (and result in 'key not found' + error log).
self.assertRaises(XfrinZoneInfoException, self.common_ixfr_setup,
'refresh', False, 'bad.key')
def test_command_handler_refresh_with_tsig_unknown_key(self):
self.assertRaises(XfrinZoneInfoException, self.common_ixfr_setup,
'refresh', False, 'no.such.key')
def test_command_handler_retransfer_ixfr_disabled(self): def test_command_handler_retransfer_ixfr_disabled(self):
# Similar to the previous case, but explicitly disabled. AXFR should # Similar to the previous case, but explicitly disabled. AXFR should
# be used. # be used.

View File

@@ -69,7 +69,12 @@ AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + "/auth.spec"
AUTH_MODULE_NAME = 'Auth' AUTH_MODULE_NAME = 'Auth'
XFROUT_MODULE_NAME = 'Xfrout' XFROUT_MODULE_NAME = 'Xfrout'
# Remote module and identifiers (according to their spec files)
ZONE_MANAGER_MODULE_NAME = 'Zonemgr' ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
TSIG_KEYS_MODULE_NAME = 'tsig_keys'
TSIG_KEYS_IDENTIFIER = 'keys'
REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr' REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
# Constants for debug levels. # Constants for debug levels.
@@ -1179,7 +1184,7 @@ class ZoneInfo:
self.set_master_port(config_data.get('master_port')) self.set_master_port(config_data.get('master_port'))
self.set_zone_class(config_data.get('class')) self.set_zone_class(config_data.get('class'))
self.set_tsig_key(config_data.get('tsig_key')) self.set_tsig_key_name(config_data.get('tsig_key'))
self.set_use_ixfr(config_data.get('use_ixfr')) self.set_use_ixfr(config_data.get('use_ixfr'))
def set_name(self, name_str): def set_name(self, name_str):
@@ -1240,20 +1245,42 @@ class ZoneInfo:
errmsg = "invalid zone class: " + zone_class_str errmsg = "invalid zone class: " + zone_class_str
raise XfrinZoneInfoException(errmsg) raise XfrinZoneInfoException(errmsg)
def set_tsig_key(self, tsig_key_str): def set_tsig_key_name(self, tsig_key_str):
"""Set the tsig_key for this zone, given a TSIG key string """Set the tsig_key for this zone, given a TSIG key string
representation. If tsig_key_str is None, no TSIG key will representation. If tsig_key_str is None, no TSIG key will
be set. Raises XfrinZoneInfoException if tsig_key_str cannot be set. Raises XfrinZoneInfoException if tsig_key_str cannot
be parsed.""" be parsed. TODO UPDATE"""
if tsig_key_str is None: if tsig_key_str is None:
self.tsig_key = None self.tsig_key_name = None
else: else:
# can throw a number of exceptions but it is just one
# call, so Exception should be OK here
try: try:
self.tsig_key = TSIGKey(tsig_key_str) self.tsig_key_name = Name(tsig_key_str)
except Exception as exc:
raise XfrinZoneInfoException("Bad TSIG key name: " + str(exc))
def get_tsig_key(self):
if self.tsig_key_name is None:
return None
key_strings, _ = self._module_cc.get_remote_config_value(
TSIG_KEYS_MODULE_NAME,
TSIG_KEYS_IDENTIFIER)
# Find the TSIG key in the keyring
for possible_key_string in key_strings:
try:
key = TSIGKey(possible_key_string)
except InvalidParameter as ipe: except InvalidParameter as ipe:
logger.error(XFRIN_BAD_TSIG_KEY_STRING, tsig_key_str) # In theory, bad keys should never end up here (but be refused
errmsg = "bad TSIG key string: " + tsig_key_str # by the validator for TSIG keys config. However,
raise XfrinZoneInfoException(errmsg) # should they do, we simply log and ignore them
logger.error(XFRIN_BAD_TSIG_KEY_STRING, possible_key_string)
if key.get_key_name() == self.tsig_key_name:
return key
logger.error(XFRIN_TSIG_KEY_NOT_FOUND, self.tsig_key_name.to_text())
errmsg = "TSIG key not found in keyring: " +\
self.tsig_key_name.to_text()
raise XfrinZoneInfoException(errmsg)
def set_use_ixfr(self, use_ixfr): def set_use_ixfr(self, use_ixfr):
"""Set use_ixfr. If set to True, it will use """Set use_ixfr. If set to True, it will use
@@ -1308,6 +1335,7 @@ class Xfrin:
self.config_handler(config_data) self.config_handler(config_data)
self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION, self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION,
self._auth_config_handler) self._auth_config_handler)
self._module_cc.add_remote_config_by_name(TSIG_KEYS_MODULE_NAME)
def _cc_check_command(self): def _cc_check_command(self):
'''This is a straightforward wrapper for cc.check_command, '''This is a straightforward wrapper for cc.check_command,
@@ -1468,7 +1496,7 @@ class Xfrin:
rrclass, rrclass,
self._get_db_file(), self._get_db_file(),
master_addr, master_addr,
zone_info.tsig_key, request_type, zone_info.get_tsig_key(), request_type,
True) True)
answer = create_answer(ret[0], ret[1]) answer = create_answer(ret[0], ret[1])
else: else:
@@ -1491,7 +1519,7 @@ class Xfrin:
tsig_key = None tsig_key = None
request_type = RRType.AXFR() request_type = RRType.AXFR()
if zone_info: if zone_info:
tsig_key = zone_info.tsig_key tsig_key = zone_info.get_tsig_key()
if zone_info.use_ixfr: if zone_info.use_ixfr:
request_type = RRType.IXFR() request_type = RRType.IXFR()
db_file = args.get('db_file') or self._get_db_file() db_file = args.get('db_file') or self._get_db_file()

View File

@@ -43,7 +43,7 @@ The master port as read from the configuration is not a valid port number.
% XFRIN_BAD_TSIG_KEY_STRING bad TSIG key string: %1 % XFRIN_BAD_TSIG_KEY_STRING bad TSIG key string: %1
The TSIG key string as read from the configuration does not represent The TSIG key string as read from the configuration does not represent
a valid TSIG key. a valid TSIG key. The key is ignored.
% XFRIN_BAD_ZONE_CLASS Invalid zone class: %1 % XFRIN_BAD_ZONE_CLASS Invalid zone class: %1
The zone class as read from the configuration is not a valid DNS class. The zone class as read from the configuration is not a valid DNS class.
@@ -160,6 +160,13 @@ run time: Time (in seconds) the complete axfr took
bytes/second: Transfer speed bytes/second: Transfer speed
% XFRIN_TSIG_KEY_NOT_FOUND TSIG key not found in key ring: %1
An attempt to start a transfer with TSIG was made, but the configured TSIG
key name was not found in the TSIG key ring (configuration option
tsig_keys/keys). The transfer is aborted. The key name that could not be
found is shown in the log message. Check the configuration and the
TSIG key ring.
% XFRIN_UNKNOWN_ERROR unknown error: %1 % XFRIN_UNKNOWN_ERROR unknown error: %1
An uncaught exception was raised while running the xfrin daemon. The An uncaught exception was raised while running the xfrin daemon. The
exception message is printed in the log message. exception message is printed in the log message.

View File

@@ -79,7 +79,7 @@ Feature: Xfrin
When I send bind10 the following commands: When I send bind10 the following commands:
""" """
config add tsig_keys/keys "example.key.:c2VjcmV0" config add tsig_keys/keys "example.key.:c2VjcmV0"
config set Xfrin/zones[0]/tsig_key "example.key.:c2VjcmV0" config set Xfrin/zones[0]/tsig_key "example.key."
config commit config commit
""" """