11"""
2- Need to install pexpect .
3- pip install pexpect
2+ The Test suite check behavior of pg_probackup utility, if password is required for connection to PostgreSQL instance .
3+ - https://confluence.postgrespro.ru/pages/viewpage.action?pageId=16777522
44"""
55
66import os
77import unittest
8- import tempfile
98import signal
109
11- from .helpers .ptrack_helpers import ProbackupTest
12- from testgres import StartNodeException , configure_testgres
10+ from .helpers .ptrack_helpers import ProbackupTest , ProbackupException
11+ from testgres import ClusterException as StartNodeException
1312
1413module_name = 'auth_test'
1514skip_test = False
@@ -33,7 +32,6 @@ def setUpClass(cls):
3332 cls .pb = ProbackupTest ()
3433 cls .backup_dir = os .path .join (cls .pb .tmp_path , module_name , 'backup' )
3534
36- configure_testgres (cache_pg_config = False , cache_initdb = False )
3735 cls .node = cls .pb .make_simple_node (
3836 base_dir = "{}/node" .format (module_name ),
3937 set_replication = True ,
@@ -44,7 +42,6 @@ def setUpClass(cls):
4442 )
4543 modify_pg_hba (cls .node )
4644
47- cls .backup_dir = os .path .join (tempfile .tempdir , "backups" )
4845 cls .pb .init_pb (cls .backup_dir )
4946 cls .pb .add_instance (cls .backup_dir , cls .node .name , cls .node )
5047 cls .pb .set_archiving (cls .backup_dir , cls .node .name , cls .node )
@@ -68,6 +65,7 @@ def setUpClass(cls):
6865 GRANT EXECUTE ON FUNCTION txid_snapshot_xmax(txid_snapshot) TO backup; \
6966 GRANT EXECUTE ON FUNCTION pg_ptrack_clear() TO backup; \
7067 GRANT EXECUTE ON FUNCTION pg_ptrack_get_and_clear(oid, oid) TO backup;" )
68+ cls .pgpass_file = os .path .join (os .path .expanduser ('~' ), '.pgpass' )
7169
7270 @classmethod
7371 def tearDownClass (cls ):
@@ -76,7 +74,7 @@ def tearDownClass(cls):
7674
7775 @unittest .skipIf (skip_test , "Module pexpect isn't installed. You need to install it." )
7876 def setUp (self ):
79- self .cmd = [self . pb . probackup_path , 'backup' ,
77+ self .cmd = ['backup' ,
8078 '-B' , self .backup_dir ,
8179 '--instance' , self .node .name ,
8280 '-h' , '127.0.0.1' ,
@@ -86,51 +84,115 @@ def setUp(self):
8684 ]
8785
8886 def tearDown (self ):
89- pass
87+ if "PGPASSWORD" in self .pb .test_env .keys ():
88+ del self .pb .test_env ["PGPASSWORD" ]
89+
90+ if "PGPASSWORD" in self .pb .test_env .keys ():
91+ del self .pb .test_env ["PGPASSFILE" ]
92+
93+ try :
94+ os .remove (self .pgpass_file )
95+ except OSError :
96+ pass
9097
9198 def test_empty_password (self ):
99+ """ Test case: PGPB_AUTH03 - zero password length """
92100 try :
93101 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- )
102+ str (run_pb_with_auth ([self .pb .probackup_path ] + self .cmd , '\0 \r \n ' ))
97103 )
98104 except (TIMEOUT , ExceptionPexpect ) as e :
99105 self .fail (e .value )
100106
101107 def test_wrong_password (self ):
108+ """ Test case: PGPB_AUTH04 - incorrect password """
102109 try :
103110 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- )
111+ str (run_pb_with_auth ([self .pb .probackup_path ] + self .cmd , 'wrong_password\r \n ' ))
107112 )
108113 except (TIMEOUT , ExceptionPexpect ) as e :
109114 self .fail (e .value )
110115
111116 def test_right_password (self ):
117+ """ Test case: PGPB_AUTH01 - correct password """
112118 try :
113119 self .assertIn ("completed" ,
114- "" .join (map (lambda x : x .decode ("utf-8" ),
115- run_pb_with_auth (self .cmd , 'password\r \n ' ))
116- )
120+ str (run_pb_with_auth ([self .pb .probackup_path ] + self .cmd , 'password\r \n ' ))
121+ )
122+ except (TIMEOUT , ExceptionPexpect ) as e :
123+ self .fail (e .value )
124+
125+ def test_right_password_and_wrong_pgpass (self ):
126+ """ Test case: PGPB_AUTH05 - correct password and incorrect .pgpass"""
127+ line = ":" .join (['127.0.0.1' , str (self .node .port ), 'postgres' , 'backup' , 'wrong_password' ])
128+ create_pgpass (self .pgpass_file , line )
129+ try :
130+ self .assertIn ("completed" ,
131+ str (run_pb_with_auth ([self .pb .probackup_path ] + self .cmd , 'password\r \n ' ))
117132 )
118133 except (TIMEOUT , ExceptionPexpect ) as e :
119134 self .fail (e .value )
120135
121136 def test_ctrl_c_event (self ):
137+ """ Test case: PGPB_AUTH02 - send interrupt signal """
122138 try :
123- run_pb_with_auth (self .cmd , kill = True )
139+ run_pb_with_auth ([ self . pb . probackup_path ] + self .cmd , kill = True )
124140 except TIMEOUT :
125141 self .fail ("Error: CTRL+C event ignored" )
126142
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\t all\t postgres\t 127.0.0.1/0\t trust\n ' + data )
143+ def test_pgpassfile_env (self ):
144+ """ Test case: PGPB_AUTH06 - set environment var PGPASSFILE """
145+ path = os .path .join (self .pb .tmp_path , module_name , 'pgpass.conf' )
146+ line = ":" .join (['127.0.0.1' , str (self .node .port ), 'postgres' , 'backup' , 'password' ])
147+ create_pgpass (path , line )
148+ self .pb .test_env ["PGPASSFILE" ] = path
149+ try :
150+ self .assertEqual (
151+ "OK" ,
152+ self .pb .show_pb (self .backup_dir , self .node .name , self .pb .run_pb (self .cmd + ['-w' ]))["status" ],
153+ "ERROR: Full backup status is not valid."
154+ )
155+ except ProbackupException as e :
156+ self .fail (e )
157+
158+ def test_pgpass (self ):
159+ """ Test case: PGPB_AUTH07 - Create file .pgpass in home dir. """
160+ line = ":" .join (['127.0.0.1' , str (self .node .port ), 'postgres' , 'backup' , 'password' ])
161+ create_pgpass (self .pgpass_file , line )
162+ try :
163+ self .assertEqual (
164+ "OK" ,
165+ self .pb .show_pb (self .backup_dir , self .node .name , self .pb .run_pb (self .cmd + ['-w' ]))["status" ],
166+ "ERROR: Full backup status is not valid."
167+ )
168+ except ProbackupException as e :
169+ self .fail (e )
170+
171+ def test_pgpassword (self ):
172+ """ Test case: PGPB_AUTH08 - set environment var PGPASSWORD """
173+ self .pb .test_env ["PGPASSWORD" ] = "password"
174+ try :
175+ self .assertEqual (
176+ "OK" ,
177+ self .pb .show_pb (self .backup_dir , self .node .name , self .pb .run_pb (self .cmd + ['-w' ]))["status" ],
178+ "ERROR: Full backup status is not valid."
179+ )
180+ except ProbackupException as e :
181+ self .fail (e )
182+
183+ def test_pgpassword_and_wrong_pgpass (self ):
184+ """ Test case: PGPB_AUTH09 - Check priority between PGPASSWORD and .pgpass file"""
185+ line = ":" .join (['127.0.0.1' , str (self .node .port ), 'postgres' , 'backup' , 'wrong_password' ])
186+ create_pgpass (self .pgpass_file , line )
187+ self .pb .test_env ["PGPASSWORD" ] = "password"
188+ try :
189+ self .assertEqual (
190+ "OK" ,
191+ self .pb .show_pb (self .backup_dir , self .node .name , self .pb .run_pb (self .cmd + ['-w' ]))["status" ],
192+ "ERROR: Full backup status is not valid."
193+ )
194+ except ProbackupException as e :
195+ self .fail (e )
134196
135197
136198def run_pb_with_auth (cmd , password = None , kill = False ):
@@ -141,10 +203,32 @@ def run_pb_with_auth(cmd, password=None, kill=False):
141203 probackup .kill (signal .SIGINT )
142204 elif result == 0 :
143205 probackup .sendline (password )
144- return probackup .readlines ()
206+ probackup .expect (EOF )
207+ return probackup .before
145208 else :
146- raise TIMEOUT ( " " )
209+ raise ExceptionPexpect ( "Other pexpect errors. " )
147210 except TIMEOUT :
148211 raise TIMEOUT ("Timeout error." )
149212 except ExceptionPexpect :
150213 raise ExceptionPexpect ("Pexpect error." )
214+
215+
216+ def modify_pg_hba (node ):
217+ """
218+ Description:
219+ Add trust authentication for user postgres. Need for add new role and set grant.
220+ :param node:
221+ :return None:
222+ """
223+ hba_conf = os .path .join (node .data_dir , "pg_hba.conf" )
224+ with open (hba_conf , 'r+' ) as fio :
225+ data = fio .read ()
226+ fio .seek (0 )
227+ fio .write ('host\t all\t postgres\t 127.0.0.1/0\t trust\n ' + data )
228+
229+
230+ def create_pgpass (path , line ):
231+ with open (path , 'w' ) as passfile :
232+ # host:port:db:username:password
233+ passfile .write (line )
234+ os .chmod (path , 0o600 )
0 commit comments