Skip to content

Commit d083bd9

Browse files
committed
Merge #10533: [tests] Use cookie auth instead of rpcuser and rpcpassword
279fde5 Check for rpcuser/rpcpassword first then for cookie (Andrew Chow) 3ec5ad8 Add test for rpcuser/rpcpassword (Andrew Chow) c53c983 Replace cookie auth in tests (Andrew Chow) Tree-SHA512: 21efb84c87080a895cac8a7fe4766738c34eebe9686c7d10af1bf91ed4ae422e2d5dbbebffd00d34744eb6bb2d0195ea3aca86deebf085bbdeeb1d8b474241ed
2 parents b3eb0d6 + 279fde5 commit d083bd9

File tree

6 files changed

+98
-31
lines changed

6 files changed

+98
-31
lines changed

test/functional/multi_rpc.py

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,21 @@ class HTTPBasicsTest (BitcoinTestFramework):
1616
def __init__(self):
1717
super().__init__()
1818
self.setup_clean_chain = False
19-
self.num_nodes = 1
19+
self.num_nodes = 2
2020

2121
def setup_chain(self):
2222
super().setup_chain()
2323
#Append rpcauth to bitcoin.conf before initialization
2424
rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144"
2525
rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e"
26+
rpcuser = "rpcuser=rpcuser💻"
27+
rpcpassword = "rpcpassword=rpcpassword🔑"
2628
with open(os.path.join(self.options.tmpdir+"/node0", "bitcoin.conf"), 'a', encoding='utf8') as f:
2729
f.write(rpcauth+"\n")
2830
f.write(rpcauth2+"\n")
31+
with open(os.path.join(self.options.tmpdir+"/node1", "bitcoin.conf"), 'a', encoding='utf8') as f:
32+
f.write(rpcuser+"\n")
33+
f.write(rpcpassword+"\n")
2934

3035
def run_test(self):
3136

@@ -50,7 +55,7 @@ def run_test(self):
5055
conn.connect()
5156
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
5257
resp = conn.getresponse()
53-
assert_equal(resp.status==401, False)
58+
assert_equal(resp.status, 200)
5459
conn.close()
5560

5661
#Use new authpair to confirm both work
@@ -60,7 +65,7 @@ def run_test(self):
6065
conn.connect()
6166
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
6267
resp = conn.getresponse()
63-
assert_equal(resp.status==401, False)
68+
assert_equal(resp.status, 200)
6469
conn.close()
6570

6671
#Wrong login name with rt's password
@@ -71,7 +76,7 @@ def run_test(self):
7176
conn.connect()
7277
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
7378
resp = conn.getresponse()
74-
assert_equal(resp.status==401, True)
79+
assert_equal(resp.status, 401)
7580
conn.close()
7681

7782
#Wrong password for rt
@@ -82,7 +87,7 @@ def run_test(self):
8287
conn.connect()
8388
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
8489
resp = conn.getresponse()
85-
assert_equal(resp.status==401, True)
90+
assert_equal(resp.status, 401)
8691
conn.close()
8792

8893
#Correct for rt2
@@ -93,7 +98,7 @@ def run_test(self):
9398
conn.connect()
9499
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
95100
resp = conn.getresponse()
96-
assert_equal(resp.status==401, False)
101+
assert_equal(resp.status, 200)
97102
conn.close()
98103

99104
#Wrong password for rt2
@@ -104,7 +109,46 @@ def run_test(self):
104109
conn.connect()
105110
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
106111
resp = conn.getresponse()
107-
assert_equal(resp.status==401, True)
112+
assert_equal(resp.status, 401)
113+
conn.close()
114+
115+
###############################################################
116+
# Check correctness of the rpcuser/rpcpassword config options #
117+
###############################################################
118+
url = urllib.parse.urlparse(self.nodes[1].url)
119+
120+
# rpcuser and rpcpassword authpair
121+
rpcuserauthpair = "rpcuser💻:rpcpassword🔑"
122+
123+
headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)}
124+
125+
conn = http.client.HTTPConnection(url.hostname, url.port)
126+
conn.connect()
127+
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
128+
resp = conn.getresponse()
129+
assert_equal(resp.status, 200)
130+
conn.close()
131+
132+
#Wrong login name with rpcuser's password
133+
rpcuserauthpair = "rpcuserwrong:rpcpassword"
134+
headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)}
135+
136+
conn = http.client.HTTPConnection(url.hostname, url.port)
137+
conn.connect()
138+
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
139+
resp = conn.getresponse()
140+
assert_equal(resp.status, 401)
141+
conn.close()
142+
143+
#Wrong password for rpcuser
144+
rpcuserauthpair = "rpcuser:rpcpasswordwrong"
145+
headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)}
146+
147+
conn = http.client.HTTPConnection(url.hostname, url.port)
148+
conn.connect()
149+
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
150+
resp = conn.getresponse()
151+
assert_equal(resp.status, 401)
108152
conn.close()
109153

110154

test/functional/p2p-segwit.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,7 +1486,7 @@ def test_p2sh_witness(self, segwit_activated):
14861486
# nodes would have stored, this requires special handling.
14871487
# To enable this test, pass --oldbinary=<path-to-pre-segwit-bitcoind> to
14881488
# the test.
1489-
def test_upgrade_after_activation(self, node, node_id):
1489+
def test_upgrade_after_activation(self, node_id):
14901490
self.log.info("Testing software upgrade after softfork activation")
14911491

14921492
assert(node_id != 0) # node0 is assumed to be a segwit-active bitcoind
@@ -1502,14 +1502,14 @@ def test_upgrade_after_activation(self, node, node_id):
15021502
sync_blocks(self.nodes)
15031503

15041504
# Make sure that this peer thinks segwit has activated.
1505-
assert(get_bip9_status(node, 'segwit')['status'] == "active")
1505+
assert(get_bip9_status(self.nodes[node_id], 'segwit')['status'] == "active")
15061506

15071507
# Make sure this peers blocks match those of node0.
1508-
height = node.getblockcount()
1508+
height = self.nodes[node_id].getblockcount()
15091509
while height >= 0:
1510-
block_hash = node.getblockhash(height)
1510+
block_hash = self.nodes[node_id].getblockhash(height)
15111511
assert_equal(block_hash, self.nodes[0].getblockhash(height))
1512-
assert_equal(self.nodes[0].getblock(block_hash), node.getblock(block_hash))
1512+
assert_equal(self.nodes[0].getblock(block_hash), self.nodes[node_id].getblock(block_hash))
15131513
height -= 1
15141514

15151515

@@ -1944,7 +1944,7 @@ def run_test(self):
19441944
self.test_signature_version_1()
19451945
self.test_non_standard_witness()
19461946
sync_blocks(self.nodes)
1947-
self.test_upgrade_after_activation(self.nodes[2], 2)
1947+
self.test_upgrade_after_activation(node_id=2)
19481948
self.test_witness_sigops()
19491949

19501950

test/functional/pruning.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ def wallet_test(self):
315315
# check that the pruning node's wallet is still in good shape
316316
self.log.info("Stop and start pruning node to trigger wallet rescan")
317317
self.stop_node(2)
318-
self.start_node(2, self.options.tmpdir, ["-prune=550"])
318+
self.nodes[2] = self.start_node(2, self.options.tmpdir, ["-prune=550"])
319319
self.log.info("Success")
320320

321321
# check that wallet loads loads successfully when restarting a pruned node after IBD.
@@ -325,7 +325,7 @@ def wallet_test(self):
325325
nds = [self.nodes[0], self.nodes[5]]
326326
sync_blocks(nds, wait=5, timeout=300)
327327
self.stop_node(5) #stop and start to trigger rescan
328-
self.start_node(5, self.options.tmpdir, ["-prune=550"])
328+
self.nodes[5] = self.start_node(5, self.options.tmpdir, ["-prune=550"])
329329
self.log.info("Success")
330330

331331
def run_test(self):

test/functional/rpcbind_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport):
4949
base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips]
5050
self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [base_args])
5151
# connect to node through non-loopback interface
52-
node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0)
52+
node = get_rpc_proxy(rpc_url(get_datadir_path(self.options.tmpdir, 0), 0, "%s:%d" % (rpchost, rpcport)), 0)
5353
node.getnetworkinfo()
5454
self.stop_nodes()
5555

test/functional/test_framework/test_framework.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
get_mocktime,
2929
get_rpc_proxy,
3030
initialize_datadir,
31+
get_datadir_path,
3132
log_filename,
3233
p2p_port,
3334
rpc_url,
@@ -300,13 +301,13 @@ def _initialize_chain(self, test_dir, num_nodes, cachedir):
300301
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
301302
bitcoind_processes[i] = subprocess.Popen(args)
302303
self.log.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
303-
wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
304+
wait_for_bitcoind_start(bitcoind_processes[i], datadir, i)
304305
self.log.debug("initialize_chain: RPC successfully started")
305306

306307
self.nodes = []
307308
for i in range(MAX_NODES):
308309
try:
309-
self.nodes.append(get_rpc_proxy(rpc_url(i), i))
310+
self.nodes.append(get_rpc_proxy(rpc_url(get_datadir_path(cachedir, i), i), i))
310311
except:
311312
self.log.exception("Error connecting to node %d" % i)
312313
sys.exit(1)

test/functional/test_framework/util.py

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,21 +181,40 @@ def initialize_datadir(dirname, n):
181181
datadir = os.path.join(dirname, "node"+str(n))
182182
if not os.path.isdir(datadir):
183183
os.makedirs(datadir)
184-
rpc_u, rpc_p = rpc_auth_pair(n)
185184
with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f:
186185
f.write("regtest=1\n")
187-
f.write("rpcuser=" + rpc_u + "\n")
188-
f.write("rpcpassword=" + rpc_p + "\n")
189186
f.write("port="+str(p2p_port(n))+"\n")
190187
f.write("rpcport="+str(rpc_port(n))+"\n")
191188
f.write("listenonion=0\n")
192189
return datadir
193190

194-
def rpc_auth_pair(n):
195-
return 'rpcuser💻' + str(n), 'rpcpass🔑' + str(n)
196-
197-
def rpc_url(i, rpchost=None):
198-
rpc_u, rpc_p = rpc_auth_pair(i)
191+
def get_datadir_path(dirname, n):
192+
return os.path.join(dirname, "node"+str(n))
193+
194+
def get_auth_cookie(datadir, n):
195+
user = None
196+
password = None
197+
if os.path.isfile(os.path.join(datadir, "bitcoin.conf")):
198+
with open(os.path.join(datadir, "bitcoin.conf"), 'r') as f:
199+
for line in f:
200+
if line.startswith("rpcuser="):
201+
assert user is None # Ensure that there is only one rpcuser line
202+
user = line.split("=")[1].strip("\n")
203+
if line.startswith("rpcpassword="):
204+
assert password is None # Ensure that there is only one rpcpassword line
205+
password = line.split("=")[1].strip("\n")
206+
if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")):
207+
with open(os.path.join(datadir, "regtest", ".cookie"), 'r') as f:
208+
userpass = f.read()
209+
split_userpass = userpass.split(':')
210+
user = split_userpass[0]
211+
password = split_userpass[1]
212+
if user is None or password is None:
213+
raise ValueError("No RPC credentials")
214+
return user, password
215+
216+
def rpc_url(datadir, i, rpchost=None):
217+
rpc_u, rpc_p = get_auth_cookie(datadir, i)
199218
host = '127.0.0.1'
200219
port = rpc_port(i)
201220
if rpchost:
@@ -206,7 +225,7 @@ def rpc_url(i, rpchost=None):
206225
host = rpchost
207226
return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port))
208227

209-
def wait_for_bitcoind_start(process, url, i):
228+
def wait_for_bitcoind_start(process, datadir, i, rpchost=None):
210229
'''
211230
Wait for bitcoind to start. This means that RPC is accessible and fully initialized.
212231
Raise an exception if bitcoind exits during initialization.
@@ -215,7 +234,8 @@ def wait_for_bitcoind_start(process, url, i):
215234
if process.poll() is not None:
216235
raise Exception('bitcoind exited with status %i during initialization' % process.returncode)
217236
try:
218-
rpc = get_rpc_proxy(url, i)
237+
# Check if .cookie file to be created
238+
rpc = get_rpc_proxy(rpc_url(datadir, i, rpchost), i)
219239
blocks = rpc.getblockcount()
220240
break # break out of loop on success
221241
except IOError as e:
@@ -224,6 +244,9 @@ def wait_for_bitcoind_start(process, url, i):
224244
except JSONRPCException as e: # Initialization phase
225245
if e.error['code'] != -28: # RPC in warmup?
226246
raise # unknown JSON RPC exception
247+
except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting
248+
if "No RPC credentials" not in str(e):
249+
raise
227250
time.sleep(0.25)
228251

229252

@@ -239,10 +262,9 @@ def _start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary
239262
if extra_args is not None: args.extend(extra_args)
240263
bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr)
241264
logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
242-
url = rpc_url(i, rpchost)
243-
wait_for_bitcoind_start(bitcoind_processes[i], url, i)
265+
wait_for_bitcoind_start(bitcoind_processes[i], datadir, i, rpchost)
244266
logger.debug("initialize_chain: RPC successfully started")
245-
proxy = get_rpc_proxy(url, i, timeout=timewait)
267+
proxy = get_rpc_proxy(rpc_url(datadir, i, rpchost), i, timeout=timewait)
246268

247269
if COVERAGE_DIR:
248270
coverage.write_all_rpc_commands(COVERAGE_DIR, proxy)

0 commit comments

Comments
 (0)