diff options
| -rwxr-xr-x | smoketest/scripts/cli/test_service_dhcp-server.py | 80 | ||||
| -rwxr-xr-x | src/conf_mode/service_dhcp-server.py | 37 |
2 files changed, 73 insertions, 44 deletions
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py index a4def234c..4a1e5ff64 100755 --- a/smoketest/scripts/cli/test_service_dhcp-server.py +++ b/smoketest/scripts/cli/test_service_dhcp-server.py @@ -1356,16 +1356,6 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): 'SXQncyBXZWRuZXNkYXkgbWFoIGR1ZGVzIQ==', ] ) - self.cli_set(ddns + ['tsig-key', 'reverse-0-168-192', 'algorithm', 'sha256']) - self.cli_set( - ddns - + [ - 'tsig-key', - 'reverse-0-168-192', - 'secret', - 'VGhhbmsgR29kIGl0J3MgRnJpZGF5IQ==', - ] - ) self.cli_set( ddns + [ @@ -1413,6 +1403,31 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): '1053', ] ) + + shared = base_path + ['shared-network-name', shared_net_name] + + self.cli_set(shared + ['dynamic-dns-update', 'send-updates', 'enable']) + self.cli_set(shared + ['dynamic-dns-update', 'conflict-resolution', 'enable']) + self.cli_set(shared + ['dynamic-dns-update', 'ttl-percent', '75']) + + pool = shared + ['subnet', subnet] + + self.cli_set(pool + ['subnet-id', '1']) + + self.cli_set(pool + ['range', '0', 'start', range_0_start]) + self.cli_set(pool + ['range', '0', 'stop', range_0_stop]) + + self.cli_set(pool + ['dynamic-dns-update', 'send-updates', 'enable']) + self.cli_set(pool + ['dynamic-dns-update', 'generated-prefix', 'myfunnyprefix']) + self.cli_set(pool + ['dynamic-dns-update', 'qualifying-suffix', 'suffix.lan']) + self.cli_set(pool + ['dynamic-dns-update', 'hostname-char-set', 'xXyYzZ']) + self.cli_set( + pool + ['dynamic-dns-update', 'hostname-char-replacement', '_xXx_'] + ) + + self.cli_commit() + + # DNS server without an IP address must be rejected self.cli_set( ddns + [ @@ -1420,10 +1435,14 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): '0.168.192.in-addr.arpa', 'dns-server', '2', - 'address', - '100.100.0.1', + 'port', + '1153', ] ) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + # Fix missing address — commit must now succeed self.cli_set( ddns + [ @@ -1431,10 +1450,13 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): '0.168.192.in-addr.arpa', 'dns-server', '2', - 'port', - '1153', + 'address', + '100.100.0.1', ] ) + self.cli_commit() + + # key-name referencing a non-existent tsig-key must be rejected self.cli_set( ddns + [ @@ -1444,28 +1466,20 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): 'reverse-0-168-192', ] ) + with self.assertRaises(ConfigSessionError): + self.cli_commit() - shared = base_path + ['shared-network-name', shared_net_name] - - self.cli_set(shared + ['dynamic-dns-update', 'send-updates', 'enable']) - self.cli_set(shared + ['dynamic-dns-update', 'conflict-resolution', 'enable']) - self.cli_set(shared + ['dynamic-dns-update', 'ttl-percent', '75']) - - pool = shared + ['subnet', subnet] - - self.cli_set(pool + ['subnet-id', '1']) - - self.cli_set(pool + ['range', '0', 'start', range_0_start]) - self.cli_set(pool + ['range', '0', 'stop', range_0_stop]) - - self.cli_set(pool + ['dynamic-dns-update', 'send-updates', 'enable']) - self.cli_set(pool + ['dynamic-dns-update', 'generated-prefix', 'myfunnyprefix']) - self.cli_set(pool + ['dynamic-dns-update', 'qualifying-suffix', 'suffix.lan']) - self.cli_set(pool + ['dynamic-dns-update', 'hostname-char-set', 'xXyYzZ']) + # Define the missing tsig-key — commit must now succeed + self.cli_set(ddns + ['tsig-key', 'reverse-0-168-192', 'algorithm', 'sha256']) self.cli_set( - pool + ['dynamic-dns-update', 'hostname-char-replacement', '_xXx_'] + ddns + + [ + 'tsig-key', + 'reverse-0-168-192', + 'secret', + 'VGhhbmsgR29kIGl0J3MgRnJpZGF5IQ==', + ] ) - self.cli_commit() config = read_file(KEA4_CONF) diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py index 24df20bb7..2727559fc 100755 --- a/src/conf_mode/service_dhcp-server.py +++ b/src/conf_mode/service_dhcp-server.py @@ -232,15 +232,28 @@ def get_config(config=None): return dhcp -def verify_ddns_domain_servers(domain_type, domain): - if 'dns_server' in domain: - invalid_servers = [] - for server_no, server_config in domain['dns_server'].items(): - if 'address' not in server_config: - invalid_servers.append(server_no) - if len(invalid_servers) > 0: - raise ConfigError(f'{domain_type} DNS servers {", ".join(invalid_servers)} in DDNS configuration need to have an IP address') - return None + +def verify_ddns_domain(domain_type, domains, tsig_keys): + for domain_name, domain_config in domains.items(): + if 'dns_server' in domain_config: + invalid_servers = [] + for server_no, server_config in domain_config['dns_server'].items(): + if 'address' not in server_config: + invalid_servers.append(server_no) + if len(invalid_servers) > 0: + raise ConfigError( + f'{domain_type} domain "{domain_name}" DNS servers {", ".join(invalid_servers)} ' + 'in DDNS configuration need to have an IP address' + ) + + if 'key_name' in domain_config: + key_name = domain_config['key_name'] + if key_name not in tsig_keys: + raise ConfigError( + f'DDNS {domain_type} domain "{domain_name}" key-name "{key_name}" ' + 'is not defined in dynamic-dns-update tsig-key' + ) + def verify(dhcp): # bail out early - looks like removal from running config @@ -515,11 +528,13 @@ def verify(dhcp): if len(invalid_keys) > 0: raise ConfigError(f'Both algorithm and secret need to be set for TSIG keys: {", ".join(invalid_keys)}') + defined_tsig_keys = ddns.get('tsig_key', {}).keys() + if 'forward_domain' in ddns: - verify_ddns_domain_servers('Forward', ddns['forward_domain']) + verify_ddns_domain('Forward', ddns['forward_domain'], defined_tsig_keys) if 'reverse_domain' in ddns: - verify_ddns_domain_servers('Reverse', ddns['reverse_domain']) + verify_ddns_domain('Reverse', ddns['reverse_domain'], defined_tsig_keys) if 'client_class' in dhcp: # Check client class values are valid |
