From e2c66ae3e9eef0d59cbd2f509bad25292b9ee66f Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 13 Aug 2024 10:59:49 +0700 Subject: [PATCH] chore: deprecate a setting platform-user in favour of whitelist --- doc/release-notes-6209.md | 3 + src/init.cpp | 2 +- src/rpc/server.cpp | 2 +- ...r.py => rpc_deprecated_platform_filter.py} | 19 ---- test/functional/rpc_external_queue.py | 92 +++++++++++++++++++ test/functional/test_runner.py | 3 +- 6 files changed, 99 insertions(+), 22 deletions(-) create mode 100644 doc/release-notes-6209.md rename test/functional/{rpc_platform_filter.py => rpc_deprecated_platform_filter.py} (82%) create mode 100644 test/functional/rpc_external_queue.py diff --git a/doc/release-notes-6209.md b/doc/release-notes-6209.md new file mode 100644 index 0000000000..06b99f2724 --- /dev/null +++ b/doc/release-notes-6209.md @@ -0,0 +1,3 @@ +## Command-line options + +- `-platform-user` is deprecated in favor of the whitelist feature. In releases 22.x of Dash Core it has been renamed to `-deprecated-platform-user` and will be removed in version 23.x diff --git a/src/init.cpp b/src/init.cpp index fe971a52cc..773f4b54a2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -736,7 +736,7 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-llmq-data-recovery=", strprintf("Enable automated quorum data recovery (default: %u)", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY), ArgsManager::ALLOW_ANY, OptionsCategory::MASTERNODE); argsman.AddArg("-llmq-qvvec-sync=:", strprintf("Defines from which LLMQ type the masternode should sync quorum verification vectors. Can be used multiple times with different LLMQ types. : %d (sync always from all quorums of the type defined by ), %d (sync from all quorums of the type defined by if a member of any of the quorums)", (int32_t)llmq::QvvecSyncMode::Always, (int32_t)llmq::QvvecSyncMode::OnlyIfTypeMember), ArgsManager::ALLOW_ANY, OptionsCategory::MASTERNODE); argsman.AddArg("-masternodeblsprivkey=", "Set the masternode BLS private key and enable the client to act as a masternode", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::MASTERNODE); - argsman.AddArg("-platform-user=", "Set the username for the \"platform user\", a restricted user intended to be used by Dash Platform, to the specified username.", ArgsManager::ALLOW_ANY, OptionsCategory::MASTERNODE); + argsman.AddArg("-deprecated-platform-user=", "Set the username for the \"platform user\", a restricted user intended to be used by Dash Platform, to the specified username.", ArgsManager::ALLOW_ANY, OptionsCategory::MASTERNODE); argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); argsman.AddArg("-dustrelayfee=", strprintf("Fee rate (in %s/kB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 7af6478c0f..0206f6c5b7 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -551,7 +551,7 @@ static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& req { const NodeContext& node = EnsureAnyNodeContext(request.context); // Before executing the RPC Command, filter commands from platform rpc user - if (node.mn_activeman && request.authUser == gArgs.GetArg("-platform-user", defaultPlatformUser)) { + if (node.mn_activeman && request.authUser == gArgs.GetArg("-deprecated-platform-user", defaultPlatformUser)) { // replace this with structured binding in c++20 std::string command_name = command.name; const auto& it = mapPlatformRestrictions.equal_range(command_name); diff --git a/test/functional/rpc_platform_filter.py b/test/functional/rpc_deprecated_platform_filter.py similarity index 82% rename from test/functional/rpc_platform_filter.py rename to test/functional/rpc_deprecated_platform_filter.py index 200ed96f48..fab38c4dcc 100755 --- a/test/functional/rpc_platform_filter.py +++ b/test/functional/rpc_deprecated_platform_filter.py @@ -114,24 +114,5 @@ class HTTPBasicsTest(BitcoinTestFramework): test_command("debug", ["1"], rpcuser_authpair_operator, 200) - self.log.info("Restart node with -rpcexternaluser") - self.restart_node(0, extra_args=["-rpcexternaluser=platform-user"]) - - external_log_str = "HTTP: Calling handler for external user" - expected_log_str = "ThreadRPCServer method=" - with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_str, external_log_str]): - test_command("getbestblockhash", [], rpcuser_authpair_platform, 200) - with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_str], unexpected_msgs = [external_log_str]): - test_command("getbestblockhash", [], rpcuser_authpair_operator, 200) - - self.log.info("Restart node with multiple external users") - self.restart_node(0, extra_args=["-rpcexternaluser=platform-user,operator"]) - with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_str, external_log_str]): - test_command("getbestblockhash", [], rpcuser_authpair_platform, 200) - with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_str, external_log_str]): - test_command("getbestblockhash", [], rpcuser_authpair_operator, 200) - - - if __name__ == '__main__': HTTPBasicsTest().main() diff --git a/test/functional/rpc_external_queue.py b/test/functional/rpc_external_queue.py new file mode 100644 index 0000000000..750084bf0d --- /dev/null +++ b/test/functional/rpc_external_queue.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 The Dash Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test that commands submitted by the platform user are filtered.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import str_to_b64str, assert_equal + +import http.client +import json +import os +import urllib.parse + + +class HTTPBasicsTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.supports_cli = False + + def setup_nodes(self): + self.add_nodes(self.num_nodes) + self.start_nodes() + + def setup_chain(self): + super().setup_chain() + # Append rpcauth to dash.conf before initialization + rpcauthplatform = "rpcauth=platform-user:dd88fd676186f48553775d6fb5a2d344$bc1f7898698ead19c6ec7ff47055622dd7101478f1ff6444103d3dc03cd77c13" + # rpcuser : platform-user + # rpcpassword : password123 + rpcauthoperator = "rpcauth=operator:e9b45dd0b61a7be72155535435365a3a$8fb7470bc6f74d8ceaf9a23f49b06127723bd563b3ed5d9cea776ef01803d191" + # rpcuser : operator + # rpcpassword : otherpassword + + masternodeblskey="masternodeblsprivkey=58af6e39bb4d86b22bda1a02b134c2f5b71caffa1377540b02f7f1ad122f59e0" + + with open(os.path.join(self.options.tmpdir+"/node0", "dash.conf"), 'a', encoding='utf8') as f: + f.write(masternodeblskey+"\n") + f.write(rpcauthplatform+"\n") + f.write(rpcauthoperator+"\n") + + def run_test(self): + url = urllib.parse.urlparse(self.nodes[0].url) + + def send_command(method, params, auth, expected_status, should_not_match=False): + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + body = {"method": method} + if len(params): + body["params"] = params + conn.request('POST', '/', json.dumps(body), {"Authorization": "Basic " + str_to_b64str(auth)}) + resp = conn.getresponse() + if should_not_match: + assert resp.status != expected_status + else: + assert_equal(resp.status, expected_status) + conn.close() + + rpcuser_authpair_platform = "platform-user:password123" + rpcuser_authpair_operator = "operator:otherpassword" + rpcuser_authpair_wrong = "platform-user:rpcpasswordwrong" + + external_log_str = "HTTP: Calling handler for external user" + always_expected_log_str = "ThreadRPCServer method=" + + self.log.info('Try using a incorrect password for platform-user...') + send_command("getbestblockhash", [], rpcuser_authpair_wrong, 401) + + self.log.info("Check that there's no external queue by default") + with self.nodes[0].assert_debug_log(expected_msgs=[always_expected_log_str], unexpected_msgs = [external_log_str]): + send_command("getbestblockhash", [], rpcuser_authpair_platform, 200) + with self.nodes[0].assert_debug_log(expected_msgs=[always_expected_log_str], unexpected_msgs = [external_log_str]): + send_command("getbestblockhash", [], rpcuser_authpair_operator, 200) + + self.log.info("Restart node with -rpcexternaluser") + self.restart_node(0, extra_args=["-rpcexternaluser=platform-user"]) + + with self.nodes[0].assert_debug_log(expected_msgs=[always_expected_log_str, external_log_str]): + send_command("getbestblockhash", [], rpcuser_authpair_platform, 200) + with self.nodes[0].assert_debug_log(expected_msgs=[always_expected_log_str], unexpected_msgs = [external_log_str]): + send_command("getbestblockhash", [], rpcuser_authpair_operator, 200) + + self.log.info("Restart node with multiple external users") + self.restart_node(0, extra_args=["-rpcexternaluser=platform-user,operator"]) + with self.nodes[0].assert_debug_log(expected_msgs=[always_expected_log_str, external_log_str]): + send_command("getbestblockhash", [], rpcuser_authpair_platform, 200) + with self.nodes[0].assert_debug_log(expected_msgs=[always_expected_log_str, external_log_str]): + send_command("getbestblockhash", [], rpcuser_authpair_operator, 200) + + +if __name__ == '__main__': + HTTPBasicsTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index bc2eb8fc62..565ae8dacc 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -321,7 +321,8 @@ BASE_SCRIPTS = [ 'wallet_send.py --descriptors', 'wallet_create_tx.py --descriptors', 'p2p_fingerprint.py', - 'rpc_platform_filter.py', + 'rpc_deprecated_platform_filter.py', + 'rpc_external_queue.py', 'rpc_wipewallettxes.py', 'feature_dip0020_activation.py', 'feature_uacomment.py',