Skip to content

Commit edc1b31

Browse files
s.logvinenkos.logvinenko
authored andcommitted
Add auth_test. Test pg_probackup with user authentification.
1 parent dd6a1f4 commit edc1b31

File tree

2 files changed

+152
-1
lines changed

2 files changed

+152
-1
lines changed

tests/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
ptrack_vacuum_bits_frozen, ptrack_vacuum_bits_visibility, \
88
ptrack_vacuum_full, ptrack_vacuum_truncate, pgpro560, pgpro589, \
99
false_positive, replica, compression, page, ptrack, archive, \
10-
exclude, cfs_backup, cfs_restore, cfs_validate_backup
10+
exclude, cfs_backup, cfs_restore, cfs_validate_backup, auth_test
1111

1212

1313
def load_tests(loader, tests, pattern):
@@ -42,6 +42,7 @@ def load_tests(loader, tests, pattern):
4242
suite.addTests(loader.loadTestsFromModule(validate_test))
4343
suite.addTests(loader.loadTestsFromModule(pgpro560))
4444
suite.addTests(loader.loadTestsFromModule(pgpro589))
45+
suite.addTests(loader.loadTestsFromModule(auth_test))
4546

4647
return suite
4748

tests/auth_test.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
"""
2+
Need to install pexpect.
3+
pip install pexpect
4+
"""
5+
6+
import os
7+
import unittest
8+
import tempfile
9+
import signal
10+
11+
from .helpers.ptrack_helpers import ProbackupTest
12+
from testgres import StartNodeException, configure_testgres
13+
14+
module_name = 'auth_test'
15+
skip_test = False
16+
17+
18+
try:
19+
from pexpect import *
20+
except ImportError:
21+
skip_test = True
22+
23+
24+
class AuthTest(unittest.TestCase):
25+
pb = None
26+
node = None
27+
28+
@classmethod
29+
def setUpClass(cls):
30+
31+
super(AuthTest, cls).setUpClass()
32+
33+
cls.pb = ProbackupTest()
34+
cls.backup_dir = os.path.join(cls.pb.tmp_path, module_name, 'backup')
35+
36+
configure_testgres(cache_pg_config=False, cache_initdb=False)
37+
cls.node = cls.pb.make_simple_node(
38+
base_dir="{}/node".format(module_name),
39+
set_replication=True,
40+
initdb_params=['--data-checksums', '--auth-host=md5'],
41+
pg_options={
42+
'wal_level': 'replica'
43+
}
44+
)
45+
modify_pg_hba(cls.node)
46+
47+
cls.backup_dir = os.path.join(tempfile.tempdir, "backups")
48+
cls.pb.init_pb(cls.backup_dir)
49+
cls.pb.add_instance(cls.backup_dir, cls.node.name, cls.node)
50+
cls.pb.set_archiving(cls.backup_dir, cls.node.name, cls.node)
51+
try:
52+
cls.node.start()
53+
except StartNodeException:
54+
raise unittest.skip("Node hasn't started")
55+
56+
cls.node.safe_psql("postgres",
57+
"CREATE ROLE backup WITH LOGIN PASSWORD 'password'; \
58+
GRANT USAGE ON SCHEMA pg_catalog TO backup; \
59+
GRANT EXECUTE ON FUNCTION current_setting(text) TO backup; \
60+
GRANT EXECUTE ON FUNCTION pg_is_in_recovery() TO backup; \
61+
GRANT EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) TO backup; \
62+
GRANT EXECUTE ON FUNCTION pg_stop_backup() TO backup; \
63+
GRANT EXECUTE ON FUNCTION pg_stop_backup(boolean) TO backup; \
64+
GRANT EXECUTE ON FUNCTION pg_create_restore_point(text) TO backup; \
65+
GRANT EXECUTE ON FUNCTION pg_switch_xlog() TO backup; \
66+
GRANT EXECUTE ON FUNCTION txid_current() TO backup; \
67+
GRANT EXECUTE ON FUNCTION txid_current_snapshot() TO backup; \
68+
GRANT EXECUTE ON FUNCTION txid_snapshot_xmax(txid_snapshot) TO backup; \
69+
GRANT EXECUTE ON FUNCTION pg_ptrack_clear() TO backup; \
70+
GRANT EXECUTE ON FUNCTION pg_ptrack_get_and_clear(oid, oid) TO backup;")
71+
72+
@classmethod
73+
def tearDownClass(cls):
74+
cls.node.cleanup()
75+
cls.pb.del_test_dir(module_name, '')
76+
77+
@unittest.skipIf(skip_test, "Module pexpect isn't installed. You need to install it.")
78+
def setUp(self):
79+
self.cmd = [self.pb.probackup_path, 'backup',
80+
'-B', self.backup_dir,
81+
'--instance', self.node.name,
82+
'-h', '127.0.0.1',
83+
'-p', str(self.node.port),
84+
'-U', 'backup',
85+
'-b', 'FULL'
86+
]
87+
88+
def tearDown(self):
89+
pass
90+
91+
def test_empty_password(self):
92+
try:
93+
self.assertIn("ERROR: no password supplied",
94+
"".join(map(lambda x: x.decode("utf-8"),
95+
run_pb_with_auth(self.cmd, '\0\r\n'))
96+
)
97+
)
98+
except (TIMEOUT, ExceptionPexpect) as e:
99+
self.fail(e.value)
100+
101+
def test_wrong_password(self):
102+
try:
103+
self.assertIn("password authentication failed",
104+
"".join(map(lambda x: x.decode("utf-8"),
105+
run_pb_with_auth(self.cmd, 'wrong_password\r\n'))
106+
)
107+
)
108+
except (TIMEOUT, ExceptionPexpect) as e:
109+
self.fail(e.value)
110+
111+
def test_right_password(self):
112+
try:
113+
self.assertIn("completed",
114+
"".join(map(lambda x: x.decode("utf-8"),
115+
run_pb_with_auth(self.cmd, 'password\r\n'))
116+
)
117+
)
118+
except (TIMEOUT, ExceptionPexpect) as e:
119+
self.fail(e.value)
120+
121+
def test_ctrl_c_event(self):
122+
try:
123+
run_pb_with_auth(self.cmd, kill=True)
124+
except TIMEOUT:
125+
self.fail("Error: CTRL+C event ignored")
126+
127+
128+
def modify_pg_hba(node):
129+
hba_conf = os.path.join(node.data_dir, "pg_hba.conf")
130+
with open(hba_conf, 'r+') as fio:
131+
data = fio.read()
132+
fio.seek(0)
133+
fio.write('host\tall\tpostgres\t127.0.0.1/0\ttrust\n' + data)
134+
135+
136+
def run_pb_with_auth(cmd, password=None, kill=False):
137+
try:
138+
with spawn(" ".join(cmd), timeout=10) as probackup:
139+
result = probackup.expect("Password for user .*:", 5)
140+
if kill:
141+
probackup.kill(signal.SIGINT)
142+
elif result == 0:
143+
probackup.sendline(password)
144+
return probackup.readlines()
145+
else:
146+
raise TIMEOUT("")
147+
except TIMEOUT:
148+
raise TIMEOUT("Timeout error.")
149+
except ExceptionPexpect:
150+
raise ExceptionPexpect("Pexpect error.")

0 commit comments

Comments
 (0)