]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Move to hashed passwords for the web interface
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 9 Mar 2021 17:27:56 +0000 (18:27 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 16 Sep 2021 12:12:16 +0000 (14:12 +0200)
It is not very good practice to keep the password in plaintext in
the configuration file as well as in memory at runtime.

pdns/dnsdist-console.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-web.cc
pdns/dnsdistdist/dnsdist-web.hh
pdns/dnsdistdist/docs/reference/config.rst
pdns/sodcrypto.cc
pdns/sodcrypto.hh
regression-tests.dnsdist/test_API.py
regression-tests.dnsdist/test_DynBlocks.py
regression-tests.dnsdist/test_Prometheus.py
regression-tests.dnsdist/test_TCPFastOpen.py

index e4c0eb896a3e04f5766f75b0bcd34af780fbea82..2600cd46d414ebb0ce6dbb4b649103803d988560 100644 (file)
@@ -472,6 +472,7 @@ const std::vector<ConsoleKeyword> 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<ConsoleKeyword> 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`" },
index b06ea8b8eeb896e85a50b2f887ad6e865940906e..20b6237b12be611445f8d2705dc6b0c2caf158b5 100644 (file)
@@ -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<std::string>(vars->at("password"));
+        auto hashed = hashPassword(password);
+        setWebserverPassword(std::move(hashed));
+      }
+
+      if (vars->count("hashedPassword")) {
+        std::string hashedPassword = boost::get<std::string>(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);
index 051df2a5872e28195eb1af05504eea9e174b35bb..d416b1a25c75f29df459d18284d1431054b74ec2 100644 (file)
@@ -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<std::string> 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)
index ea869274c475de44d612bc3ab620c34f0b0479a5..937d33c1e0d0d65fe0840e922e011e54bc81f4f6 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 void setWebserverAPIKey(const boost::optional<std::string> apiKey);
-void setWebserverPassword(const std::string& password);
+void setWebserverPassword(std::string&& password);
 void setWebserverACL(const std::string& acl);
 void setWebserverCustomHeaders(const boost::optional<std::map<std::string, std::string> > customHeaders);
 void setWebserverStatsRequireAuthentication(bool);
index 5670c65072482a8ede287a991193e7b1edd90cfb..b34fc1a03d2868d6a2bf5916b32b3f3e003120b4 100644 (file)
@@ -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".
index b92c6e0e53bb716f3649be5ab6ae7814b6b6336a..6ca218b7b799ae3b0878159e9de8393fdbfb12f0 100644 (file)
@@ -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<char*>(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;
+}
index ca35631455de7cc3f5afb3724fd4ac5213d36289..69c05a29f4b395ae2dd7297087a098f5c732ce4d 100644 (file)
@@ -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);
index e4272fa06e0bc2cff17e28b8b6287c2414977db8..8cc83e18f8c4caba78add94483c6abbb7671071c 100644 (file)
@@ -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):
index 26801a54e5d487810dff87aba0b53149882b92b9..d0c5f34c86a09711a7db1d559bd92389164d6830 100644 (file)
@@ -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):
         """
index 121764a0933d501a6e082d56940efb6b2ebcea47..50176e13676e8c2382a726dac5d54582578d6bdd 100644 (file)
@@ -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):
index 5e050902aea02623c5664c95ea2c04a4d70f8546..3a5025f4463154b001c0bd13a566dc5a8bfd0d93 100644 (file)
@@ -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