From: Remi Gacogne Date: Wed, 13 Sep 2023 14:27:51 +0000 (+0200) Subject: dnsdist: Fix a race in TLS certificate generation in the tests X-Git-Tag: dnsdist-1.9.0-alpha1~2^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=58ae5410e204c3775831b501be3cc92fd4595ea2;p=thirdparty%2Fpdns.git dnsdist: Fix a race in TLS certificate generation in the tests The OCSP and TLS tests are generating new TLS certificate and key, so there was a time window for a certificate/key mismatch if a test is starting right at the moment the OCSP and TLS tests are generating new material. This commit fixes it by using different file names for these tests. --- diff --git a/regression-tests.dnsdist/.gitignore b/regression-tests.dnsdist/.gitignore index bde839b044..78d7bc1ccb 100644 --- a/regression-tests.dnsdist/.gitignore +++ b/regression-tests.dnsdist/.gitignore @@ -14,8 +14,18 @@ /server.csr /server.key /server.pem -/server.ocsp /server.p12 +/server-ocsp.chain +/server-ocsp.csr +/server-ocsp.key +/server-ocsp.pem +/server-ocsp.p12 +/server-tls.chain +/server-tls.csr +/server-tls.key +/server-tls.pem +/server-tls.p12 +/server.ocsp /configs /dnsdist.log /dnsdist_test.conf diff --git a/regression-tests.dnsdist/dnsdisttests.py b/regression-tests.dnsdist/dnsdisttests.py index c82f2b9ac9..75f12e6202 100644 --- a/regression-tests.dnsdist/dnsdisttests.py +++ b/regression-tests.dnsdist/dnsdisttests.py @@ -905,16 +905,17 @@ class DNSDistTest(AssertEqualDNSMessageMixin, unittest.TestCase): def checkResponseNoEDNS(self, expected, received): self.checkMessageNoEDNS(expected, received) - def generateNewCertificateAndKey(self): + @staticmethod + def generateNewCertificateAndKey(filePrefix): # generate and sign a new cert - cmd = ['openssl', 'req', '-new', '-newkey', 'rsa:2048', '-nodes', '-keyout', 'server.key', '-out', 'server.csr', '-config', 'configServer.conf'] + cmd = ['openssl', 'req', '-new', '-newkey', 'rsa:2048', '-nodes', '-keyout', filePrefix + '.key', '-out', filePrefix + '.csr', '-config', 'configServer.conf'] output = None try: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) output = process.communicate(input='') except subprocess.CalledProcessError as exc: raise AssertionError('openssl req failed (%d): %s' % (exc.returncode, exc.output)) - cmd = ['openssl', 'x509', '-req', '-days', '1', '-CA', 'ca.pem', '-CAkey', 'ca.key', '-CAcreateserial', '-in', 'server.csr', '-out', 'server.pem', '-extfile', 'configServer.conf', '-extensions', 'v3_req'] + cmd = ['openssl', 'x509', '-req', '-days', '1', '-CA', 'ca.pem', '-CAkey', 'ca.key', '-CAcreateserial', '-in', filePrefix + '.csr', '-out', filePrefix + '.pem', '-extfile', 'configServer.conf', '-extensions', 'v3_req'] output = None try: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) @@ -922,12 +923,12 @@ class DNSDistTest(AssertEqualDNSMessageMixin, unittest.TestCase): except subprocess.CalledProcessError as exc: raise AssertionError('openssl x509 failed (%d): %s' % (exc.returncode, exc.output)) - with open('server.chain', 'w') as outFile: - for inFileName in ['server.pem', 'ca.pem']: + with open(filePrefix + '.chain', 'w') as outFile: + for inFileName in [filePrefix + '.pem', 'ca.pem']: with open(inFileName) as inFile: outFile.write(inFile.read()) - cmd = ['openssl', 'pkcs12', '-export', '-passout', 'pass:passw0rd', '-clcerts', '-in', 'server.pem', '-CAfile', 'ca.pem', '-inkey', 'server.key', '-out', 'server.p12'] + cmd = ['openssl', 'pkcs12', '-export', '-passout', 'pass:passw0rd', '-clcerts', '-in', filePrefix + '.pem', '-CAfile', 'ca.pem', '-inkey', filePrefix + '.key', '-out', filePrefix + '.p12'] output = None try: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) diff --git a/regression-tests.dnsdist/test_OCSP.py b/regression-tests.dnsdist/test_OCSP.py index de520dcdaf..695863151c 100644 --- a/regression-tests.dnsdist/test_OCSP.py +++ b/regression-tests.dnsdist/test_OCSP.py @@ -35,13 +35,20 @@ class DNSDistOCSPStaplingTest(DNSDistTest): def getTLSProvider(self): return self.sendConsoleCommand("getBind(0):getEffectiveTLSProvider()").rstrip() + @classmethod + def setUpClass(cls): + cls.generateNewCertificateAndKey('server-ocsp') + cls.startResponders() + cls.startDNSDist() + cls.setUpSockets() + @unittest.skipIf('SKIP_DOH_TESTS' in os.environ, 'DNS over HTTPS tests are disabled') class TestOCSPStaplingDOH(DNSDistOCSPStaplingTest): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-ocsp.key' + _serverCert = 'server-ocsp.chain' _serverName = 'tls.tests.dnsdist.org' _ocspFile = 'server.ocsp' _caCert = 'ca.pem' @@ -67,6 +74,7 @@ class TestOCSPStaplingDOH(DNSDistOCSPStaplingTest): if 'SKIP_DOH_TESTS' in os.environ: raise unittest.SkipTest('DNS over HTTPS tests are disabled') + cls.generateNewCertificateAndKey('server-ocsp') cls.startResponders() cls.startDNSDist() cls.setUpSockets() @@ -84,7 +92,7 @@ class TestOCSPStaplingDOH(DNSDistOCSPStaplingTest): serialNumber = self.getOCSPSerial(output) self.assertTrue(serialNumber) - self.generateNewCertificateAndKey() + self.generateNewCertificateAndKey('server-ocsp') self.sendConsoleCommand("generateOCSPResponse('%s', '%s', '%s', '%s', 1, 0)" % (self._serverCert, self._caCert, self._caKey, self._ocspFile)) self.sendConsoleCommand("reloadAllCertificates()") @@ -98,8 +106,8 @@ class TestBrokenOCSPStaplingDoH(DNSDistOCSPStaplingTest): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-ocsp.key' + _serverCert = 'server-ocsp.chain' _serverName = 'tls.tests.dnsdist.org' _caCert = 'ca.pem' # invalid OCSP file! @@ -129,8 +137,8 @@ class TestOCSPStaplingTLSGnuTLS(DNSDistOCSPStaplingTest): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-ocsp.key' + _serverCert = 'server-ocsp.chain' _serverName = 'tls.tests.dnsdist.org' _ocspFile = 'server.ocsp' _caCert = 'ca.pem' @@ -158,7 +166,7 @@ class TestOCSPStaplingTLSGnuTLS(DNSDistOCSPStaplingTest): serialNumber = self.getOCSPSerial(output) self.assertTrue(serialNumber) - self.generateNewCertificateAndKey() + self.generateNewCertificateAndKey('server-ocsp') self.sendConsoleCommand("generateOCSPResponse('%s', '%s', '%s', '%s', 1, 0)" % (self._serverCert, self._caCert, self._caKey, self._ocspFile)) self.sendConsoleCommand("reloadAllCertificates()") @@ -172,8 +180,8 @@ class TestBrokenOCSPStaplingTLSGnuTLS(DNSDistOCSPStaplingTest): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-ocsp.key' + _serverCert = 'server-ocsp.chain' _serverName = 'tls.tests.dnsdist.org' _caCert = 'ca.pem' # invalid OCSP file! @@ -200,8 +208,8 @@ class TestOCSPStaplingTLSOpenSSL(DNSDistOCSPStaplingTest): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-ocsp.key' + _serverCert = 'server-ocsp.chain' _serverName = 'tls.tests.dnsdist.org' _ocspFile = 'server.ocsp' _caCert = 'ca.pem' @@ -229,7 +237,7 @@ class TestOCSPStaplingTLSOpenSSL(DNSDistOCSPStaplingTest): serialNumber = self.getOCSPSerial(output) self.assertTrue(serialNumber) - self.generateNewCertificateAndKey() + self.generateNewCertificateAndKey('server-ocsp') self.sendConsoleCommand("generateOCSPResponse('%s', '%s', '%s', '%s', 1, 0)" % (self._serverCert, self._caCert, self._caKey, self._ocspFile)) self.sendConsoleCommand("reloadAllCertificates()") @@ -243,8 +251,8 @@ class TestBrokenOCSPStaplingTLSOpenSSL(DNSDistOCSPStaplingTest): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-ocsp.key' + _serverCert = 'server-ocsp.chain' _serverName = 'tls.tests.dnsdist.org' _caCert = 'ca.pem' # invalid OCSP file! diff --git a/regression-tests.dnsdist/test_TLS.py b/regression-tests.dnsdist/test_TLS.py index 12db463945..9803ed550f 100644 --- a/regression-tests.dnsdist/test_TLS.py +++ b/regression-tests.dnsdist/test_TLS.py @@ -58,7 +58,7 @@ class TLSTests(object): self.assertEqual(names, ['tls.tests.dnsdist.org', 'powerdns.com', '127.0.0.1']) serialNumber = cert['serialNumber'] - self.generateNewCertificateAndKey() + self.generateNewCertificateAndKey('server-tls') self.sendConsoleCommand("reloadAllCertificates()") conn.close() @@ -268,8 +268,8 @@ class TestOpenSSL(DNSDistTest, TLSTests): _extraStartupSleep = 1 _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-tls.key' + _serverCert = 'server-tls.chain' _serverName = 'tls.tests.dnsdist.org' _caCert = 'ca.pem' _tlsServerPort = pickAvailablePort() @@ -283,6 +283,13 @@ class TestOpenSSL(DNSDistTest, TLSTests): """ _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey'] + @classmethod + def setUpClass(cls): + cls.generateNewCertificateAndKey('server-tls') + cls.startResponders() + cls.startDNSDist() + cls.setUpSockets() + def testProvider(self): self.assertEqual(self.getTLSProvider(), "openssl") @@ -290,8 +297,8 @@ class TestGnuTLS(DNSDistTest, TLSTests): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverKey = 'server.key' - _serverCert = 'server.chain' + _serverKey = 'server-tls.key' + _serverCert = 'server-tls.chain' _serverName = 'tls.tests.dnsdist.org' _caCert = 'ca.pem' _tlsServerPort = pickAvailablePort() @@ -305,6 +312,13 @@ class TestGnuTLS(DNSDistTest, TLSTests): """ _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey'] + @classmethod + def setUpClass(cls): + cls.generateNewCertificateAndKey('server-tls') + cls.startResponders() + cls.startDNSDist() + cls.setUpSockets() + def testProvider(self): self.assertEqual(self.getTLSProvider(), "gnutls") @@ -481,7 +495,7 @@ class TestProtocols(DNSDistTest): class TestPKCSTLSCertificate(DNSDistTest, TLSTests): _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _serverCert = 'server.p12' + _serverCert = 'server-tls.p12' _pkcsPassphrase = 'passw0rd' _serverName = 'tls.tests.dnsdist.org' _caCert = 'ca.pem' @@ -495,3 +509,10 @@ class TestPKCSTLSCertificate(DNSDistTest, TLSTests): addAction(SNIRule("powerdns.com"), SpoofAction("1.2.3.4")) """ _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_serverCert', '_pkcsPassphrase', '_tlsServerPort'] + + @classmethod + def setUpClass(cls): + cls.generateNewCertificateAndKey('server-tls') + cls.startResponders() + cls.startDNSDist() + cls.setUpSockets()