From fc101fb99c8c47e7422d3348ad824458b05c0ec3 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Fri, 9 May 2025 20:05:13 +0200 Subject: [PATCH] auth-py tests: allow backend choice, add lmdb testing --- regression-tests.auth-py/authtests.py | 93 +++++++++++++------ regression-tests.auth-py/test_ALIAS.py | 2 +- regression-tests.auth-py/test_AnyBind.py | 2 +- regression-tests.auth-py/test_Carbon.py | 2 +- regression-tests.auth-py/test_Cookies.py | 2 +- .../test_DirectDNSKEYSignature.py | 2 +- regression-tests.auth-py/test_GSSTSIG.py | 2 + regression-tests.auth-py/test_IXFR.py | 4 +- regression-tests.auth-py/test_LuaRecords.py | 10 +- .../test_LuaRecordsLMDB.py | 36 +------ .../test_ProxyProtocol.py | 32 +++++-- .../test_ResolveAcrossZones.py | 2 +- regression-tests.auth-py/test_SVCB.py | 19 +--- .../test_XFRIncomplete.py | 5 +- tasks.py | 5 +- 15 files changed, 122 insertions(+), 96 deletions(-) diff --git a/regression-tests.auth-py/authtests.py b/regression-tests.auth-py/authtests.py index 9e9e9c999e..03c08fb33e 100644 --- a/regression-tests.auth-py/authtests.py +++ b/regression-tests.auth-py/authtests.py @@ -24,13 +24,20 @@ class AuthTest(AssertEqualDNSMessageMixin, unittest.TestCase): _confdir = 'auth' _authPort = 5300 + _backend = os.getenv("AUTH_BACKEND", "bind") + + _backend_configs = dict( + bind=""" +bind-config={confdir}/named.conf +bind-dnssec-db={bind_dnssec_db} +""", lmdb="", + gsqlite3="") + _config_params = [] _config_template_default = """ module-dir={PDNS_MODULE_DIR} daemon=no -bind-config={confdir}/named.conf -bind-dnssec-db={bind_dnssec_db} socket-dir={confdir} cache-ttl=0 negquery-cache-ttl=0 @@ -117,25 +124,33 @@ options { params = tuple([getattr(cls, param) for param in cls._config_params]) with open(os.path.join(confdir, 'pdns.conf'), 'w') as pdnsconf: - pdnsconf.write(cls._config_template_default.format( - confdir=confdir, prefix=cls._PREFIX, - bind_dnssec_db=bind_dnssec_db, - PDNS_MODULE_DIR=cls._PDNS_MODULE_DIR, - )) - pdnsconf.write(cls._config_template % params) + args = dict(backend=cls._backend, + confdir=confdir, + prefix=cls._PREFIX, + bind_dnssec_db=bind_dnssec_db, + PDNS_MODULE_DIR=cls._PDNS_MODULE_DIR + ) - os.system("sqlite3 ./configs/auth/powerdns.sqlite < ../modules/gsqlite3backend/schema.sqlite3.sql") + pdnsconf.write((cls._config_template_default + cls._backend_configs[cls._backend]).format(**args)) + pdnsconf.write(cls._config_template.format(**args) % params) - pdnsutilCmd = [os.environ['PDNSUTIL'], - '--config-dir=%s' % confdir, - 'create-bind-db', - bind_dnssec_db] + if cls._backend == 'gsqlite3': + os.system("sqlite3 ./configs/auth/powerdns.sqlite < ../modules/gsqlite3backend/schema.sqlite3.sql") - print(' '.join(pdnsutilCmd)) - try: - subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - raise AssertionError('%s failed (%d): %s' % (pdnsutilCmd, e.returncode, e.output)) + if cls._backend == 'lmdb': + os.system("rm -f pdns.lmdb*") + + if cls._backend == 'bind': + pdnsutilCmd = [os.environ['PDNSUTIL'], + '--config-dir=%s' % confdir, + 'create-bind-db', + bind_dnssec_db] + + print(' '.join(pdnsutilCmd)) + try: + subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + raise AssertionError('%s failed (%d): %s' % (pdnsutilCmd, e.returncode, e.output)) @classmethod def secureZone(cls, confdir, zonename, key=None): @@ -167,14 +182,40 @@ options { @classmethod def generateAllAuthConfig(cls, confdir): cls.generateAuthConfig(confdir) - cls.generateAuthNamedConf(confdir, cls._zones.keys()) - - for zonename, zonecontent in cls._zones.items(): - cls.generateAuthZone(confdir, - zonename, - zonecontent) - if cls._zone_keys.get(zonename, None): - cls.secureZone(confdir, zonename, cls._zone_keys.get(zonename)) + + if cls._backend == 'bind': + cls.generateAuthNamedConf(confdir, cls._zones.keys()) + + for zonename, zonecontent in cls._zones.items(): + cls.generateAuthZone(confdir, + zonename, + zonecontent) + if cls._zone_keys.get(zonename, None): + cls.secureZone(confdir, zonename, cls._zone_keys.get(zonename)) + elif cls._backend == 'lmdb': + for zonename, zonecontent in cls._zones.items(): + cls.generateAuthZone(confdir, + zonename, + zonecontent) + pdnsutilCmd = [os.environ['PDNSUTIL'], + '--config-dir=%s' % confdir, + 'load-zone', + zonename, + os.path.join(confdir, '%s.zone' % zonename)] + + print(' '.join(pdnsutilCmd)) + try: + subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + raise AssertionError('%s failed (%d): %s' % (pdnsutilCmd, e.returncode, e.output)) + if cls._zone_keys.get(zonename, None): + cls.secureZone(confdir, zonename, cls._zone_keys.get(zonename)) + elif cls._backend == 'gsqlite3': + # this is not a supported config from the user, but some of the test_*.py files use gsqlite3 + return + else: + raise RuntimeError("unknown backend " + cls._backend + " specified") + @classmethod def waitForTCPSocket(cls, ipaddress, port): diff --git a/regression-tests.auth-py/test_ALIAS.py b/regression-tests.auth-py/test_ALIAS.py index 8cd7f4f3de..441ffa49e4 100644 --- a/regression-tests.auth-py/test_ALIAS.py +++ b/regression-tests.auth-py/test_ALIAS.py @@ -20,7 +20,7 @@ class TestALIAS(AuthTest): expand-alias=yes resolver=%s.1:5301 any-to-tcp=no -launch=bind +launch={backend} edns-subnet-processing=yes """ diff --git a/regression-tests.auth-py/test_AnyBind.py b/regression-tests.auth-py/test_AnyBind.py index e0b6c4c8a5..1b85f3ebeb 100644 --- a/regression-tests.auth-py/test_AnyBind.py +++ b/regression-tests.auth-py/test_AnyBind.py @@ -8,7 +8,7 @@ from authtests import AuthTest class TestBindAny(AuthTest): _config_template = """ -launch=bind +launch={backend} """ _zones = { diff --git a/regression-tests.auth-py/test_Carbon.py b/regression-tests.auth-py/test_Carbon.py index 6718b15ad5..41b53cf67f 100644 --- a/regression-tests.auth-py/test_Carbon.py +++ b/regression-tests.auth-py/test_Carbon.py @@ -19,7 +19,7 @@ class TestCarbon(AuthTest): _carbonQueue2 = Queue() _carbonCounters = {} _config_template = """ - launch=bind + launch={backend} carbon-namespace=%s carbon-instance=%s carbon-interval=%s diff --git a/regression-tests.auth-py/test_Cookies.py b/regression-tests.auth-py/test_Cookies.py index ba67da8978..ac85c3312b 100644 --- a/regression-tests.auth-py/test_Cookies.py +++ b/regression-tests.auth-py/test_Cookies.py @@ -6,7 +6,7 @@ from authtests import AuthTest class TestEdnsCookies(AuthTest): _config_template = """ -launch=bind +launch={backend} edns-cookie-secret=aabbccddeeff11223344556677889900 """ diff --git a/regression-tests.auth-py/test_DirectDNSKEYSignature.py b/regression-tests.auth-py/test_DirectDNSKEYSignature.py index bb63eda2a6..b11a641ab5 100644 --- a/regression-tests.auth-py/test_DirectDNSKEYSignature.py +++ b/regression-tests.auth-py/test_DirectDNSKEYSignature.py @@ -7,7 +7,7 @@ from authtests import AuthTest class TestDirectDNSKEYSignature(AuthTest): _config_template = """ - launch=bind + launch={backend} direct-dnskey=yes direct-dnskey-signature=yes """ diff --git a/regression-tests.auth-py/test_GSSTSIG.py b/regression-tests.auth-py/test_GSSTSIG.py index d7da3f45dd..78e6d3b1ef 100644 --- a/regression-tests.auth-py/test_GSSTSIG.py +++ b/regression-tests.auth-py/test_GSSTSIG.py @@ -7,6 +7,8 @@ from authtests import AuthTest class GSSTSIGBase(AuthTest): + _backend = 'gsqlite3' + _config_template_default = """ module-dir={PDNS_MODULE_DIR} daemon=no diff --git a/regression-tests.auth-py/test_IXFR.py b/regression-tests.auth-py/test_IXFR.py index 6247dc04b7..daaef1ca1d 100644 --- a/regression-tests.auth-py/test_IXFR.py +++ b/regression-tests.auth-py/test_IXFR.py @@ -59,8 +59,10 @@ xfrServerPort = 4244 xfrServer = AXFRServer(xfrServerPort, zones) class TestIXFR(AuthTest): + _backend = 'gsqlite3' + _config_template = """ -launch=gsqlite3 bind +launch=gsqlite3 gsqlite3-database=configs/auth/powerdns.sqlite gsqlite3-dnssec secondary diff --git a/regression-tests.auth-py/test_LuaRecords.py b/regression-tests.auth-py/test_LuaRecords.py index a8df4b25c9..6ea2ef1622 100644 --- a/regression-tests.auth-py/test_LuaRecords.py +++ b/regression-tests.auth-py/test_LuaRecords.py @@ -42,7 +42,7 @@ class BaseLuaTest(AuthTest): _config_template = """ geoip-database-files=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb edns-subnet-processing=yes -launch=bind geoip +launch={backend} geoip any-to-tcp=no enable-lua-records lua-records-insert-whitespace=yes @@ -1245,7 +1245,7 @@ class TestLuaRecordsShared(TestLuaRecords): _config_template = """ geoip-database-files=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb edns-subnet-processing=yes -launch=bind geoip +launch={backend} geoip any-to-tcp=no enable-lua-records=shared lua-records-insert-whitespace=yes @@ -1268,7 +1268,7 @@ class TestLuaRecordsNoWhiteSpace(TestLuaRecords): _config_template = """ geoip-database-files=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb edns-subnet-processing=yes -launch=bind geoip +launch={backend} geoip any-to-tcp=no enable-lua-records lua-records-insert-whitespace=no @@ -1284,7 +1284,7 @@ class TestLuaRecordsSlowTimeouts(BaseLuaTest): _config_template = """ geoip-database-files=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb edns-subnet-processing=yes -launch=bind geoip +launch={backend} geoip any-to-tcp=no enable-lua-records lua-records-insert-whitespace=yes @@ -1412,7 +1412,7 @@ class TestLuaRecordsExecLimit(BaseLuaTest): _config_template = """ geoip-database-files=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb edns-subnet-processing=yes -launch=bind geoip +launch={backend} geoip any-to-tcp=no enable-lua-records lua-records-insert-whitespace=yes diff --git a/regression-tests.auth-py/test_LuaRecordsLMDB.py b/regression-tests.auth-py/test_LuaRecordsLMDB.py index 942dd3d946..633704da47 100644 --- a/regression-tests.auth-py/test_LuaRecordsLMDB.py +++ b/regression-tests.auth-py/test_LuaRecordsLMDB.py @@ -7,18 +7,7 @@ import subprocess from authtests import AuthTest class TestLuaRecordsLMDB(AuthTest): - # Copied from AuthTest, without the bind-config and bind-dnssec fields, - # since these tests target LMDB an a backend. - _config_template_default = """ -daemon=no -socket-dir={confdir} -cache-ttl=0 -negquery-cache-ttl=0 -query-cache-ttl=0 -log-dns-queries=yes -log-dns-details=yes -loglevel=9 -distributor-threads=1""" + _backend = 'lmdb' _config_template = """ launch=lmdb @@ -45,29 +34,6 @@ nested-lua.example.org. 3600 IN LUA A ( ";include('config') " """ } - @classmethod - def generateAllAuthConfig(cls, confdir): - # This is very similar to AuthTest.generateAllAuthConfig, - # but for lmdb backend, we ignore auth keys but need to load-zone - # into lmdb storage. - cls.generateAuthConfig(confdir) - - for zonename, zonecontent in cls._zones.items(): - cls.generateAuthZone(confdir, - zonename, - zonecontent) - pdnsutilCmd = [os.environ['PDNSUTIL'], - '--config-dir=%s' % confdir, - 'load-zone', - zonename, - os.path.join(confdir, '%s.zone' % zonename)] - - print(' '.join(pdnsutilCmd)) - try: - subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - raise AssertionError('%s failed (%d): %s' % (pdnsutilCmd, e.returncode, e.output)) - def testPickRandomWithNestedLua(self): """ Basic pickrandom() test with a set of A records, with a bit of lua inclusion diff --git a/regression-tests.auth-py/test_ProxyProtocol.py b/regression-tests.auth-py/test_ProxyProtocol.py index 60127f22ff..8a03ab4844 100644 --- a/regression-tests.auth-py/test_ProxyProtocol.py +++ b/regression-tests.auth-py/test_ProxyProtocol.py @@ -3,6 +3,7 @@ import dns import os import socket import struct +import subprocess import threading import time import unittest @@ -12,7 +13,7 @@ from proxyprotocol import ProxyProtocol class TestProxyProtocolLuaRecords(AuthTest): _config_template = """ -launch=bind +launch={backend} any-to-tcp=no proxy-protocol-from=127.0.0.1 enable-lua-records @@ -113,16 +114,18 @@ myip.example.org. 3600 IN LUA TXT "who:toString()..'/'..bestwho: class TestProxyProtocolNOTIFY(AuthTest): _config_template = """ -launch=bind +launch={backend} any-to-tcp=no proxy-protocol-from=127.0.0.1 secondary """ - _zones = { 'example.org': '192.0.2.1', + _secondary_zones = { 'example.org': '192.0.2.1', 'example.com': '192.0.2.2' } + _zones = {} + @classmethod def generateAuthZone(cls, confdir, zonename, zonecontent): try: @@ -130,6 +133,23 @@ secondary except: pass + @classmethod + def generateAuthConfig(cls, confdir): + super(TestProxyProtocolNOTIFY, cls).generateAuthConfig(confdir) + if cls._backend == 'lmdb': + for zonename in cls._secondary_zones: + pdnsutilCmd = [os.environ['PDNSUTIL'], + '--config-dir=%s' % confdir, + 'create-secondary-zone', + zonename, + cls._secondary_zones[zonename]] + + print(' '.join(pdnsutilCmd)) + try: + subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + raise AssertionError('%s failed (%d): %s' % (pdnsutilCmd, e.returncode, e.output)) + @classmethod def generateAuthNamedConf(cls, confdir, zones): with open(os.path.join(confdir, 'named.conf'), 'w') as namedconf: @@ -137,7 +157,7 @@ secondary options { directory "%s"; };""" % confdir) - for zonename in zones: + for zonename in cls._secondary_zones: zone = '.' if zonename == 'ROOT' else zonename namedconf.write(""" @@ -145,7 +165,7 @@ options { type secondary; file "%s.zone"; masters { %s; }; - };""" % (zone, zonename, cls._zones[zone])) + };""" % (zone, zonename, cls._secondary_zones[zone])) @classmethod @@ -187,7 +207,7 @@ options { class TestProxyProtocolAXFRACL(AuthTest): _config_template = """ -launch=bind +launch={backend} any-to-tcp=no proxy-protocol-from=127.0.0.1 allow-axfr-ips=192.0.2.53 diff --git a/regression-tests.auth-py/test_ResolveAcrossZones.py b/regression-tests.auth-py/test_ResolveAcrossZones.py index 00207ef54c..7d753e3a11 100644 --- a/regression-tests.auth-py/test_ResolveAcrossZones.py +++ b/regression-tests.auth-py/test_ResolveAcrossZones.py @@ -10,7 +10,7 @@ from authtests import AuthTest class CrossZoneResolveBase(AuthTest): _config_template = """ any-to-tcp=no -launch=bind +launch={backend} edns-subnet-processing=yes """ target_otherzone_ip = "192.0.2.2" diff --git a/regression-tests.auth-py/test_SVCB.py b/regression-tests.auth-py/test_SVCB.py index 12f35c4b67..db4ea8bb90 100644 --- a/regression-tests.auth-py/test_SVCB.py +++ b/regression-tests.auth-py/test_SVCB.py @@ -4,19 +4,6 @@ import os import subprocess class SVCBRecordsBase(AuthTest): - # Copied from AuthTest, without the bind-config and bind-dnssec fields. - _config_template_default = """ -module-dir={PDNS_MODULE_DIR} -daemon=no -socket-dir={confdir} -cache-ttl=0 -negquery-cache-ttl=0 -query-cache-ttl=0 -log-dns-queries=yes -log-dns-details=yes -loglevel=9 -distributor-threads=1""" - _config_template = """ svc-autohints """ @@ -157,6 +144,8 @@ auto-aaaa.example.org. 3600 IN AAAA 2001:db8::80 self.assertEqual(len(res.additional), 2) class TestSVCBRecordsBind(SVCBRecordsBase): + _backend = "bind" + _config_template_default = ( SVCBRecordsBase._config_template_default + """ @@ -168,7 +157,7 @@ bind-dnssec-db={bind_dnssec_db} _config_template = ( SVCBRecordsBase._config_template + """ -launch=bind +launch={backend} """ ) @@ -212,6 +201,8 @@ launch=bind self.impl_testAutoAAAA() class TestSVCBRecordsLMDB(SVCBRecordsBase): + _backend='lmdb' + _config_template = ( SVCBRecordsBase._config_template + """ diff --git a/regression-tests.auth-py/test_XFRIncomplete.py b/regression-tests.auth-py/test_XFRIncomplete.py index 3db145e293..efe10059d0 100644 --- a/regression-tests.auth-py/test_XFRIncomplete.py +++ b/regression-tests.auth-py/test_XFRIncomplete.py @@ -140,8 +140,11 @@ class XFRIncompleteAuthTest(AuthTest): """ global badxfrServerPort + + _backend = 'gsqlite3' + _config_template = """ -launch=gsqlite3 bind +launch=gsqlite3 gsqlite3-database=configs/auth/powerdns.sqlite gsqlite3-dnssec secondary diff --git a/tasks.py b/tasks.py index 47a6fa5b5f..049770f37f 100644 --- a/tasks.py +++ b/tasks.py @@ -1114,8 +1114,9 @@ def test_auth_backend(c, backend): if backend == 'authpy': c.sudo(f'sh -c \'echo "{auth_backend_ip_addr} kerberos-server" | tee -a /etc/hosts\'') - with c.cd('regression-tests.auth-py'): - c.run(f'{pdns_auth_env_vars} WITHKERBEROS=YES ./runtests') + for auth_backend in ('bind', 'lmdb'): + with c.cd('regression-tests.auth-py'): + c.run(f'{pdns_auth_env_vars} AUTH_BACKEND={auth_backend} WITHKERBEROS=YES ./runtests') return if backend == 'bind': -- 2.47.2