From: Remi Gacogne Date: Tue, 9 Mar 2021 17:27:56 +0000 (+0100) Subject: dnsdist: Move to hashed passwords for the web interface X-Git-Tag: dnsdist-1.7.0-alpha1~12^2~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72bf42cd71e1edf76f957425420343d634a183e5;p=thirdparty%2Fpdns.git dnsdist: Move to hashed passwords for the web interface It is not very good practice to keep the password in plaintext in the configuration file as well as in memory at runtime. --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index e4c0eb896a..2600cd46d4 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -472,6 +472,7 @@ const std::vector g_consoleKeywords{ { "getTLSFrontend", true, "n", "returns the TLS frontend with index n" }, { "getTLSFrontendCount", true, "", "returns the number of DoT listeners" }, { "grepq", true, "Netmask|DNS Name|100ms|{\"::1\", \"powerdns.com\", \"100ms\"} [, n]", "shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms" }, + { "hashPassword", true, "password", "Returns a hashed and salted version of the supplied password, usable with 'setWebserverConfig()'"}, { "HTTPHeaderRule", true, "name, regex", "matches DoH queries with a HTTP header 'name' whose content matches the regular expression 'regex'"}, { "HTTPPathRegexRule", true, "regex", "matches DoH queries whose HTTP path matches 'regex'"}, { "HTTPPathRule", true, "path", "matches DoH queries whose HTTP path is an exact match to 'path'"}, @@ -628,7 +629,7 @@ const std::vector g_consoleKeywords{ { "setUDPMultipleMessagesVectorSize", true, "n", "set the size of the vector passed to recvmmsg() to receive UDP messages. Default to 1 which means that the feature is disabled and recvmsg() is used instead" }, { "setUDPTimeout", true, "n", "set the maximum time dnsdist will wait for a response from a backend over UDP, in seconds" }, { "setVerboseHealthChecks", true, "bool", "set whether health check errors will be logged" }, - { "setWebserverConfig", true, "[{password=string, apiKey=string, customHeaders, statsRequireAuthentication}]", "Updates webserver configuration" }, + { "setWebserverConfig", true, "[{hashedPassword=string, apiKey=string, customHeaders, statsRequireAuthentication}]", "Updates webserver configuration" }, { "setWeightedBalancingFactor", true, "factor", "Set the balancing factor for bounded-load weighted policies (whashed, wrandom)" }, { "setWHashedPertubation", true, "value", "Set the hash perturbation value to be used in the whashed policy instead of a random one, allowing to have consistent whashed results on different instance" }, { "show", true, "string", "outputs `string`" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index b06ea8b8ee..20b6237b12 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -944,7 +944,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) SListen(sock, 5); auto launch=[sock, local, password, apiKey, customHeaders, acl]() { if (password) { - setWebserverPassword(*password); + warnlog("Passing a plain-text password to 'webserver()' is deprecated, please use 'setWebserverConfig()' instead."); + auto hashed = hashPassword(*password); + setWebserverPassword(std::move(hashed)); } if (apiKey) { @@ -985,9 +987,18 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } if (vars->count("password")) { + warnlog("Passing a plain-text password via the 'password' parameter to 'setWebserverConfig()' is deprecated, please generate a hashed one using 'hashPassword()' and pass it via 'hashedPassword' instead."); + const std::string password = boost::get(vars->at("password")); + auto hashed = hashPassword(password); + setWebserverPassword(std::move(hashed)); + } + + if (vars->count("hashedPassword")) { + std::string hashedPassword = boost::get(vars->at("hashedPassword")); + sodium_mlock(hashedPassword.data(), hashedPassword.size()); - setWebserverPassword(password); + setWebserverPassword(std::move(hashedPassword)); } if (vars->count("apiKey")) { @@ -1017,6 +1028,10 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } }); + luaCtx.writeFunction("hashPassword", [](const std::string& password) { + return hashPassword(password); + }); + luaCtx.writeFunction("controlSocket", [client,configCheck](const std::string& str) { setLuaSideEffect(); ComboAddress local(str, 5199); diff --git a/pdns/dnsdist-web.cc b/pdns/dnsdist-web.cc index 051df2a587..d416b1a25c 100644 --- a/pdns/dnsdist-web.cc +++ b/pdns/dnsdist-web.cc @@ -40,6 +40,7 @@ #include "gettime.hh" #include "htmlfiles.h" #include "threadname.hh" +#include "sodcrypto.hh" #include "sstuff.hh" struct WebserverConfig @@ -226,7 +227,7 @@ static bool checkWebPassword(const YaHTTP::Request& req, const string &expected_ stringtok(cparts, plain, ":"); if (cparts.size() == 2) { - return cparts[1] == expected_password; + return verifyPassword(g_webserverConfig.password, cparts.at(1)); } } @@ -1468,9 +1469,9 @@ void setWebserverAPIKey(const boost::optional apiKey) } } -void setWebserverPassword(const std::string& password) +void setWebserverPassword(std::string&& password) { - g_webserverConfig.lock()->password = password; + g_webserverConfig.lock()->password = std::move(password); } void setWebserverACL(const std::string& acl) diff --git a/pdns/dnsdistdist/dnsdist-web.hh b/pdns/dnsdistdist/dnsdist-web.hh index ea869274c4..937d33c1e0 100644 --- a/pdns/dnsdistdist/dnsdist-web.hh +++ b/pdns/dnsdistdist/dnsdist-web.hh @@ -1,7 +1,7 @@ #pragma once void setWebserverAPIKey(const boost::optional apiKey); -void setWebserverPassword(const std::string& password); +void setWebserverPassword(std::string&& password); void setWebserverACL(const std::string& acl); void setWebserverCustomHeaders(const boost::optional > customHeaders); void setWebserverStatsRequireAuthentication(bool); diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 5670c65072..b34fc1a03d 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -290,6 +290,14 @@ Control Socket, Console and Webserver Webserver configuration ~~~~~~~~~~~~~~~~~~~~~~~ +.. function:: hashPassword(password) + + .. versionadded:: 1.7.0 + + Hash the supplied password using a random salt, and returns a string that can be used with :func:`setWebserverConfig`. + + :param string - password: The password to hash + .. function:: webserver(listen_address [, password[, apikey[, custom_headers[, acl]]]]) .. versionchanged:: 1.5.0 @@ -325,13 +333,17 @@ Webserver configuration .. versionchanged:: 1.6.0 ``statsRequireAuthentication``, ``maxConcurrentConnections`` optional parameters added. + .. versionchanged:: 1.7.0 + The ``password``, optional parameter has been deprecated, ``hashedPassword`` added instead. + Setup webserver configuration. See :func:`webserver`. :param table options: A table with key: value pairs with webserver options. Options: - * ``password=newPassword``: string - Changes the API password + * ``password=newPassword``: string - Changes the password used to access the internal webserver. Deprecated, please use ``hashedPassword`` instead + * ``hashedPassword=newPassword``: string - Set the password used to access the internal webserver. The new password needs to be hashed and salted via the :func:`hashPassword` command * ``apiKey=newKey``: string - Changes the API Key (set to an empty string do disable it) * ``custom_headers={[str]=str,...}``: map of string - Allows setting custom headers and removing the defaults. * ``acl=newACL``: string - List of IP addresses, as a string, that are allowed to open a connection to the web server. Defaults to "127.0.0.1, ::1". diff --git a/pdns/sodcrypto.cc b/pdns/sodcrypto.cc index b92c6e0e53..6ca218b7b7 100644 --- a/pdns/sodcrypto.cc +++ b/pdns/sodcrypto.cc @@ -352,3 +352,32 @@ std::string Base64Encode (const std::string& vby) }; return retval; }; + +std::string hashPassword(const std::string& password) +{ + std::string result; + result.resize(crypto_pwhash_STRBYTES); + sodium_mlock(result.data(), result.size()); + + int res = crypto_pwhash_str(const_cast(result.c_str()), + password.c_str(), + password.size(), + crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE); + if (res != 0) { + throw std::runtime_error("Error while hashing the supplied password"); + } + + return result; +} + +bool verifyPassword(const std::string& hash, const std::string& password) +{ + if (hash.size() > crypto_pwhash_STRBYTES) { + throw std::runtime_error("Invalid password hash supplied for verification, size is " + std::to_string(hash.size()) + ", expected at most " + std::to_string(crypto_pwhash_STRBYTES)); + } + + return crypto_pwhash_str_verify(hash.c_str(), + password.c_str(), + password.size()) == 0; +} diff --git a/pdns/sodcrypto.hh b/pdns/sodcrypto.hh index ca35631455..69c05a29f4 100644 --- a/pdns/sodcrypto.hh +++ b/pdns/sodcrypto.hh @@ -76,3 +76,6 @@ std::string sodEncryptSym(const std::string& msg, const std::string& key, Sodium std::string sodDecryptSym(const std::string& msg, const std::string& key, SodiumNonce&); std::string newKey(); bool sodIsValidKey(const std::string& key); + +std::string hashPassword(const std::string& password); +bool verifyPassword(const std::string& hash, const std::string& password); diff --git a/regression-tests.dnsdist/test_API.py b/regression-tests.dnsdist/test_API.py index e4272fa06e..8cc83e18f8 100644 --- a/regression-tests.dnsdist/test_API.py +++ b/regression-tests.dnsdist/test_API.py @@ -8,25 +8,30 @@ import socket import time from dnsdisttests import DNSDistTest -class TestAPIBasics(DNSDistTest): - +class APITestsBase(DNSDistTest): + __test__ = False _webTimeout = 2.0 _webServerPort = 8083 _webServerBasicAuthPassword = 'secret' + _webServerBasicAuthPasswordHashed = '$argon2id$v=19$m=65536,t=2,p=1$mTJBHtI/KyO8oVDy8wyizg$8NK4ap5ohC7ylY8Dua61iBqhQw0cbcmXUaOpotC2hC0' _webServerAPIKey = 'apisecret' + _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] + _config_template = """ + setACL({"127.0.0.1/32", "::1/128"}) + newServer{address="127.0.0.1:%s", pool={'', 'mypool'}} + webserver("127.0.0.1:%s") + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) + """ + +class TestAPIBasics(APITestsBase): + # paths accessible using the API key only _apiOnlyPaths = ['/api/v1/servers/localhost/config', '/api/v1/servers/localhost/config/allow-from', '/api/v1/servers/localhost/statistics'] # paths accessible using an API key or basic auth _statsPaths = [ '/jsonstat?command=stats', '/jsonstat?command=dynblocklist', '/api/v1/servers/localhost'] # paths accessible using basic auth only (list not exhaustive) _basicOnlyPaths = ['/', '/index.html'] - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] - _config_template = """ - setACL({"127.0.0.1/32", "::1/128"}) - newServer{address="127.0.0.1:%s", pool={'', 'mypool'}} - webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) - """ + __test__ = True def testBasicAuth(self): """ @@ -337,20 +342,14 @@ class TestAPIBasics(DNSDistTest): for key in ['blocks']: self.assertTrue(content[key] >= 0) -class TestAPIServerDown(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' - _webServerAPIKey = 'apisecret' - # paths accessible using the API key - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] +class TestAPIServerDown(APITestsBase): + __test__ = True _config_template = """ setACL({"127.0.0.1/32", "::1/128"}) newServer{address="127.0.0.1:%s"} getServer(0):setDown() webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ def testServerDownNoLatencyLocalhost(self): @@ -367,19 +366,15 @@ class TestAPIServerDown(DNSDistTest): self.assertEqual(content['servers'][0]['latency'], None) -class TestAPIWritable(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' - _webServerAPIKey = 'apisecret' +class TestAPIWritable(APITestsBase): + __test__ = True _APIWriteDir = '/tmp' - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey', '_APIWriteDir'] + _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey', '_APIWriteDir'] _config_template = """ setACL({"127.0.0.1/32", "::1/128"}) newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) setAPIWritable(true, "%s") """ @@ -440,26 +435,22 @@ class TestAPIWritable(DNSDistTest): """setACL({"203.0.113.0/24", "198.51.100.0/24", "192.0.2.0/24"})\n""" }) -class TestAPICustomHeaders(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' - _webServerAPIKey = 'apisecret' +class TestAPICustomHeaders(APITestsBase): + __test__ = True # paths accessible using the API key only _apiOnlyPath = '/api/v1/servers/localhost/config' # paths accessible using basic auth only (list not exhaustive) _basicOnlyPath = '/' _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] _config_template = """ setKey("%s") controlSocket("127.0.0.1:%s") setACL({"127.0.0.1/32", "::1/128"}) newServer({address="127.0.0.1:%s"}) webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s", customHeaders={["X-Frame-Options"]="", ["X-Custom"]="custom"} }) + setWebserverConfig({hashedPassword="%s", apiKey="%s", customHeaders={["X-Frame-Options"]="", ["X-Custom"]="custom"} }) """ def testBasicHeaders(self): @@ -488,12 +479,8 @@ class TestAPICustomHeaders(DNSDistTest): self.assertEqual(r.headers.get('x-powered-by'), "dnsdist") self.assertTrue("x-frame-options" in r.headers) -class TestStatsWithoutAuthentication(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' - _webServerAPIKey = 'apisecret' +class TestStatsWithoutAuthentication(APITestsBase): + __test__ = True # paths accessible using the API key only _apiOnlyPath = '/api/v1/servers/localhost/config' # paths accessible using basic auth only (list not exhaustive) @@ -501,14 +488,14 @@ class TestStatsWithoutAuthentication(DNSDistTest): _noAuthenticationPaths = [ '/metrics', '/jsonstat?command=dynblocklist' ] _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] _config_template = """ setKey("%s") controlSocket("127.0.0.1:%s") setACL({"127.0.0.1/32", "::1/128"}) newServer({address="127.0.0.1:%s"}) webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s", statsRequireAuthentication=false }) + setWebserverConfig({hashedPassword="%s", apiKey="%s", statsRequireAuthentication=false }) """ def testAuth(self): @@ -546,13 +533,10 @@ class TestStatsWithoutAuthentication(DNSDistTest): self.assertTrue(r) self.assertEqual(r.status_code, 200) -class TestAPIAuth(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' +class TestAPIAuth(APITestsBase): + __test__ = True _webServerBasicAuthPasswordNew = 'password' - _webServerAPIKey = 'apisecret' + _webServerBasicAuthPasswordNewHashed = '$argon2id$v=19$m=65536,t=2,p=1$AYiZGEPogz3849qG//YsjA$ZG39i+yK8Pet8yNU8lJ9ktMbDyF2TuxC32TR74/Mx68' _webServerAPIKeyNew = 'apipassword' # paths accessible using the API key only _apiOnlyPath = '/api/v1/servers/localhost/config' @@ -560,14 +544,14 @@ class TestAPIAuth(DNSDistTest): _basicOnlyPath = '/' _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] _config_template = """ setKey("%s") controlSocket("127.0.0.1:%s") setACL({"127.0.0.1/32", "::1/128"}) newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ def testBasicAuthChange(self): @@ -576,7 +560,7 @@ class TestAPIAuth(DNSDistTest): """ url = 'http://127.0.0.1:' + str(self._webServerPort) + self._basicOnlyPath - self.sendConsoleCommand('setWebserverConfig({{password="{}"}})'.format(self._webServerBasicAuthPasswordNew)) + self.sendConsoleCommand('setWebserverConfig({{hashedPassword="{}"}})'.format(self._webServerBasicAuthPasswordNewHashed)) r = requests.get(url, auth=('whatever', self._webServerBasicAuthPasswordNew), timeout=self._webTimeout) self.assertTrue(r) @@ -623,22 +607,18 @@ class TestAPIAuth(DNSDistTest): r = requests.get(url, headers=headers, timeout=self._webTimeout) self.assertEqual(r.status_code, 401) -class TestAPIACL(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' - _webServerAPIKey = 'apisecret' +class TestAPIACL(APITestsBase): + __test__ = True _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') - _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] _config_template = """ setKey("%s") controlSocket("127.0.0.1:%s") setACL({"127.0.0.1/32", "::1/128"}) newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s", acl="192.0.2.1"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s", acl="192.0.2.1"}) """ def testACLChange(self): @@ -660,15 +640,13 @@ class TestAPIACL(DNSDistTest): self.assertTrue(r) self.assertEqual(r.status_code, 200) -class TestCustomLuaEndpoint(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' +class TestCustomLuaEndpoint(APITestsBase): + __test__ = True _config_template = """ setACL({"127.0.0.1/32", "::1/128"}) newServer{address="127.0.0.1:%s"} - webserver("127.0.0.1:%s", "%s") + webserver("127.0.0.1:%s") + setWebserverConfig({hashedPassword="%s"}) function customHTTPHandler(req, resp) if req.path ~= '/foo' then @@ -704,7 +682,7 @@ class TestCustomLuaEndpoint(DNSDistTest): end registerWebHandler('/foo', customHTTPHandler) """ - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPassword'] + _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed'] def testBasic(self): """ @@ -718,19 +696,15 @@ class TestCustomLuaEndpoint(DNSDistTest): self.assertEqual(r.content, b'It works!') self.assertEqual(r.headers.get('foo'), "Bar") -class TestWebConcurrentConnectionsL(DNSDistTest): - - _webTimeout = 2.0 - _webServerPort = 8083 - _webServerBasicAuthPassword = 'secret' - _webServerAPIKey = 'apisecret' +class TestWebConcurrentConnections(APITestsBase): + __test__ = True _maxConns = 2 - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey', '_maxConns'] + _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey', '_maxConns'] _config_template = """ newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s", maxConcurrentConnections=%d}) + setWebserverConfig({hashedPassword="%s", apiKey="%s", maxConcurrentConnections=%d}) """ def testConcurrentConnections(self): diff --git a/regression-tests.dnsdist/test_DynBlocks.py b/regression-tests.dnsdist/test_DynBlocks.py index 26801a54e5..d0c5f34c86 100644 --- a/regression-tests.dnsdist/test_DynBlocks.py +++ b/regression-tests.dnsdist/test_DynBlocks.py @@ -15,6 +15,7 @@ class DynBlocksTest(DNSDistTest): _webTimeout = 2.0 _webServerPort = 8083 _webServerBasicAuthPassword = 'secret' + _webServerBasicAuthPasswordHashed = '$argon2id$v=19$m=65536,t=2,p=1$mTJBHtI/KyO8oVDy8wyizg$8NK4ap5ohC7ylY8Dua61iBqhQw0cbcmXUaOpotC2hC0' _webServerAPIKey = 'apisecret' def doTestDynBlockViaAPI(self, range, reason, minSeconds, maxSeconds, minBlocks, maxBlocks): @@ -566,9 +567,9 @@ class TestDynBlockQPS(DynBlocksTest): end newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ - _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] def testDynBlocksQRate(self): """ @@ -591,9 +592,9 @@ class TestDynBlockGroupQPS(DynBlocksTest): end newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ - _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] def testDynBlocksQRate(self): """ @@ -1147,9 +1148,9 @@ class TestDynBlockGroupNoOp(DynBlocksTest): newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ - _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] def testNoOp(self): """ @@ -1211,9 +1212,9 @@ class TestDynBlockGroupWarning(DynBlocksTest): newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ - _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_dynBlockWarningQPS', '_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_dynBlockWarningQPS', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] def testWarning(self): """ diff --git a/regression-tests.dnsdist/test_Prometheus.py b/regression-tests.dnsdist/test_Prometheus.py index 121764a093..50176e1367 100644 --- a/regression-tests.dnsdist/test_Prometheus.py +++ b/regression-tests.dnsdist/test_Prometheus.py @@ -11,12 +11,13 @@ class TestPrometheus(DNSDistTest): _webTimeout = 2.0 _webServerPort = 8083 _webServerBasicAuthPassword = 'secret' + _webServerBasicAuthPasswordHashed = '$argon2id$v=19$m=65536,t=2,p=1$mTJBHtI/KyO8oVDy8wyizg$8NK4ap5ohC7ylY8Dua61iBqhQw0cbcmXUaOpotC2hC0' _webServerAPIKey = 'apisecret' - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] _config_template = """ newServer{address="127.0.0.1:%s"} webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ def checkPrometheusContentBasic(self, content): diff --git a/regression-tests.dnsdist/test_TCPFastOpen.py b/regression-tests.dnsdist/test_TCPFastOpen.py index 5e050902ae..3a5025f446 100644 --- a/regression-tests.dnsdist/test_TCPFastOpen.py +++ b/regression-tests.dnsdist/test_TCPFastOpen.py @@ -18,12 +18,13 @@ class TestBrokenTCPFastOpen(DNSDistTest): _webTimeout = 2.0 _webServerPort = 8083 _webServerBasicAuthPassword = 'secret' + _webServerBasicAuthPasswordHashed = '$argon2id$v=19$m=65536,t=2,p=1$mTJBHtI/KyO8oVDy8wyizg$8NK4ap5ohC7ylY8Dua61iBqhQw0cbcmXUaOpotC2hC0' _webServerAPIKey = 'apisecret' - _config_params = ['_testServerPort', '_testServerRetries', '_webServerPort', '_webServerBasicAuthPassword', '_webServerAPIKey'] + _config_params = ['_testServerPort', '_testServerRetries', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKey'] _config_template = """ newServer{address="127.0.0.1:%s", useClientSubnet=true, tcpFastOpen=true, retries=%d } webserver("127.0.0.1:%s") - setWebserverConfig({password="%s", apiKey="%s"}) + setWebserverConfig({hashedPassword="%s", apiKey="%s"}) """ @classmethod