11356St.nateldemoura@f5.comimport io 2781Szelenkov@nginx.comimport re 3781Szelenkov@nginx.comimport ssl 4781Szelenkov@nginx.comimport subprocess 51886Szelenkov@nginx.comimport time 61477Szelenkov@nginx.com 71635Szelenkov@nginx.comimport pytest 81019Szelenkov@nginx.comfrom unit.applications.tls import TestApplicationTLS 91863Szelenkov@nginx.comfrom unit.option import option 10781Szelenkov@nginx.com 111017Szelenkov@nginx.com 121019Szelenkov@nginx.comclass TestTLS(TestApplicationTLS): 131467Szelenkov@nginx.com prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}} 14781Szelenkov@nginx.com 15781Szelenkov@nginx.com def openssl_date_to_sec_epoch(self, date): 16781Szelenkov@nginx.com return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z') 17781Szelenkov@nginx.com 18781Szelenkov@nginx.com def add_tls(self, application='empty', cert='default', port=7080): 191775Szelenkov@nginx.com assert 'success' in self.conf( 201041Svbart@nginx.com { 211041Svbart@nginx.com "pass": "applications/" + application, 221848Szelenkov@nginx.com "tls": {"certificate": cert}, 231041Svbart@nginx.com }, 241017Szelenkov@nginx.com 'listeners/*:' + str(port), 251017Szelenkov@nginx.com ) 26781Szelenkov@nginx.com 27781Szelenkov@nginx.com def remove_tls(self, application='empty', port=7080): 281775Szelenkov@nginx.com assert 'success' in self.conf( 291041Svbart@nginx.com {"pass": "applications/" + application}, 'listeners/*:' + str(port) 301041Svbart@nginx.com ) 31781Szelenkov@nginx.com 321863Szelenkov@nginx.com def req(self, name='localhost', subject=None, x509=False): 331863Szelenkov@nginx.com subj = subject if subject is not None else '/CN=' + name + '/' 341863Szelenkov@nginx.com 35*2004Szelenkov@nginx.com subprocess.check_output( 361863Szelenkov@nginx.com [ 371863Szelenkov@nginx.com 'openssl', 381863Szelenkov@nginx.com 'req', 391863Szelenkov@nginx.com '-new', 401863Szelenkov@nginx.com '-subj', 411863Szelenkov@nginx.com subj, 421863Szelenkov@nginx.com '-config', 431863Szelenkov@nginx.com option.temp_dir + '/openssl.conf', 441863Szelenkov@nginx.com '-out', 451863Szelenkov@nginx.com option.temp_dir + '/' + name + '.csr', 461863Szelenkov@nginx.com '-keyout', 471863Szelenkov@nginx.com option.temp_dir + '/' + name + '.key', 481863Szelenkov@nginx.com ], 491863Szelenkov@nginx.com stderr=subprocess.STDOUT, 501863Szelenkov@nginx.com ) 511863Szelenkov@nginx.com 521863Szelenkov@nginx.com def generate_ca_conf(self): 531863Szelenkov@nginx.com with open(option.temp_dir + '/ca.conf', 'w') as f: 541863Szelenkov@nginx.com f.write( 551863Szelenkov@nginx.com """[ ca ] 561863Szelenkov@nginx.comdefault_ca = myca 571863Szelenkov@nginx.com 581863Szelenkov@nginx.com[ myca ] 591863Szelenkov@nginx.comnew_certs_dir = %(dir)s 601863Szelenkov@nginx.comdatabase = %(database)s 611863Szelenkov@nginx.comdefault_md = sha256 621863Szelenkov@nginx.compolicy = myca_policy 631863Szelenkov@nginx.comserial = %(certserial)s 641863Szelenkov@nginx.comdefault_days = 1 651863Szelenkov@nginx.comx509_extensions = myca_extensions 661863Szelenkov@nginx.comcopy_extensions = copy 671863Szelenkov@nginx.com 681863Szelenkov@nginx.com[ myca_policy ] 691863Szelenkov@nginx.comcommonName = optional 701863Szelenkov@nginx.com 711863Szelenkov@nginx.com[ myca_extensions ] 721863Szelenkov@nginx.combasicConstraints = critical,CA:TRUE""" 731863Szelenkov@nginx.com % { 741863Szelenkov@nginx.com 'dir': option.temp_dir, 751863Szelenkov@nginx.com 'database': option.temp_dir + '/certindex', 761863Szelenkov@nginx.com 'certserial': option.temp_dir + '/certserial', 771863Szelenkov@nginx.com } 781863Szelenkov@nginx.com ) 791863Szelenkov@nginx.com 801863Szelenkov@nginx.com with open(option.temp_dir + '/certserial', 'w') as f: 811863Szelenkov@nginx.com f.write('1000') 821863Szelenkov@nginx.com 831863Szelenkov@nginx.com with open(option.temp_dir + '/certindex', 'w') as f: 841863Szelenkov@nginx.com f.write('') 851863Szelenkov@nginx.com 861863Szelenkov@nginx.com with open(option.temp_dir + '/certindex.attr', 'w') as f: 871863Szelenkov@nginx.com f.write('') 881863Szelenkov@nginx.com 891863Szelenkov@nginx.com def ca(self, cert='root', out='localhost'): 90*2004Szelenkov@nginx.com subprocess.check_output( 911863Szelenkov@nginx.com [ 921863Szelenkov@nginx.com 'openssl', 931863Szelenkov@nginx.com 'ca', 941863Szelenkov@nginx.com '-batch', 951863Szelenkov@nginx.com '-config', 961863Szelenkov@nginx.com option.temp_dir + '/ca.conf', 971863Szelenkov@nginx.com '-keyfile', 981863Szelenkov@nginx.com option.temp_dir + '/' + cert + '.key', 991863Szelenkov@nginx.com '-cert', 1001863Szelenkov@nginx.com option.temp_dir + '/' + cert + '.crt', 1011863Szelenkov@nginx.com '-in', 1021863Szelenkov@nginx.com option.temp_dir + '/' + out + '.csr', 1031863Szelenkov@nginx.com '-out', 1041863Szelenkov@nginx.com option.temp_dir + '/' + out + '.crt', 1051863Szelenkov@nginx.com ], 1061863Szelenkov@nginx.com stderr=subprocess.STDOUT, 1071863Szelenkov@nginx.com ) 1081863Szelenkov@nginx.com 1091863Szelenkov@nginx.com def set_certificate_req_context(self, cert='root'): 1101863Szelenkov@nginx.com self.context = ssl.create_default_context() 1111863Szelenkov@nginx.com self.context.check_hostname = False 1121863Szelenkov@nginx.com self.context.verify_mode = ssl.CERT_REQUIRED 1131863Szelenkov@nginx.com self.context.load_verify_locations( 1141863Szelenkov@nginx.com option.temp_dir + '/' + cert + '.crt' 1151863Szelenkov@nginx.com ) 1161863Szelenkov@nginx.com 117781Szelenkov@nginx.com def test_tls_listener_option_add(self): 118781Szelenkov@nginx.com self.load('empty') 119781Szelenkov@nginx.com 120781Szelenkov@nginx.com self.certificate() 121781Szelenkov@nginx.com 122781Szelenkov@nginx.com self.add_tls() 123781Szelenkov@nginx.com 1241596Szelenkov@nginx.com assert self.get_ssl()['status'] == 200, 'add listener option' 125781Szelenkov@nginx.com 126781Szelenkov@nginx.com def test_tls_listener_option_remove(self): 127781Szelenkov@nginx.com self.load('empty') 128781Szelenkov@nginx.com 129781Szelenkov@nginx.com self.certificate() 130781Szelenkov@nginx.com 131781Szelenkov@nginx.com self.add_tls() 132781Szelenkov@nginx.com 133781Szelenkov@nginx.com self.get_ssl() 134781Szelenkov@nginx.com 135781Szelenkov@nginx.com self.remove_tls() 136781Szelenkov@nginx.com 1371596Szelenkov@nginx.com assert self.get()['status'] == 200, 'remove listener option' 138781Szelenkov@nginx.com 139781Szelenkov@nginx.com def test_tls_certificate_remove(self): 140781Szelenkov@nginx.com self.load('empty') 141781Szelenkov@nginx.com 142781Szelenkov@nginx.com self.certificate() 143781Szelenkov@nginx.com 1441596Szelenkov@nginx.com assert 'success' in self.conf_delete( 1451596Szelenkov@nginx.com '/certificates/default' 1461596Szelenkov@nginx.com ), 'remove certificate' 147781Szelenkov@nginx.com 148781Szelenkov@nginx.com def test_tls_certificate_remove_used(self): 149781Szelenkov@nginx.com self.load('empty') 150781Szelenkov@nginx.com 151781Szelenkov@nginx.com self.certificate() 152781Szelenkov@nginx.com 153781Szelenkov@nginx.com self.add_tls() 154781Szelenkov@nginx.com 1551596Szelenkov@nginx.com assert 'error' in self.conf_delete( 1561596Szelenkov@nginx.com '/certificates/default' 1571596Szelenkov@nginx.com ), 'remove certificate' 158781Szelenkov@nginx.com 159781Szelenkov@nginx.com def test_tls_certificate_remove_nonexisting(self): 160781Szelenkov@nginx.com self.load('empty') 161781Szelenkov@nginx.com 162781Szelenkov@nginx.com self.certificate() 163781Szelenkov@nginx.com 164781Szelenkov@nginx.com self.add_tls() 165781Szelenkov@nginx.com 1661596Szelenkov@nginx.com assert 'error' in self.conf_delete( 1671596Szelenkov@nginx.com '/certificates/blah' 1681596Szelenkov@nginx.com ), 'remove nonexistings certificate' 169781Szelenkov@nginx.com 1701596Szelenkov@nginx.com @pytest.mark.skip('not yet') 171781Szelenkov@nginx.com def test_tls_certificate_update(self): 172781Szelenkov@nginx.com self.load('empty') 173781Szelenkov@nginx.com 174781Szelenkov@nginx.com self.certificate() 175781Szelenkov@nginx.com 176781Szelenkov@nginx.com self.add_tls() 177781Szelenkov@nginx.com 178781Szelenkov@nginx.com cert_old = self.get_server_certificate() 179781Szelenkov@nginx.com 180781Szelenkov@nginx.com self.certificate() 181781Szelenkov@nginx.com 1821596Szelenkov@nginx.com assert cert_old != self.get_server_certificate(), 'update certificate' 183781Szelenkov@nginx.com 1841596Szelenkov@nginx.com @pytest.mark.skip('not yet') 185781Szelenkov@nginx.com def test_tls_certificate_key_incorrect(self): 186781Szelenkov@nginx.com self.load('empty') 187781Szelenkov@nginx.com 188781Szelenkov@nginx.com self.certificate('first', False) 189781Szelenkov@nginx.com self.certificate('second', False) 190781Szelenkov@nginx.com 1911596Szelenkov@nginx.com assert 'error' in self.certificate_load( 1921596Szelenkov@nginx.com 'first', 'second' 1931596Szelenkov@nginx.com ), 'key incorrect' 194781Szelenkov@nginx.com 195781Szelenkov@nginx.com def test_tls_certificate_change(self): 196781Szelenkov@nginx.com self.load('empty') 197781Szelenkov@nginx.com 198781Szelenkov@nginx.com self.certificate() 199781Szelenkov@nginx.com self.certificate('new') 200781Szelenkov@nginx.com 201781Szelenkov@nginx.com self.add_tls() 202781Szelenkov@nginx.com 203781Szelenkov@nginx.com cert_old = self.get_server_certificate() 204781Szelenkov@nginx.com 205781Szelenkov@nginx.com self.add_tls(cert='new') 206781Szelenkov@nginx.com 2071596Szelenkov@nginx.com assert cert_old != self.get_server_certificate(), 'change certificate' 208781Szelenkov@nginx.com 209781Szelenkov@nginx.com def test_tls_certificate_key_rsa(self): 210781Szelenkov@nginx.com self.load('empty') 211781Szelenkov@nginx.com 212781Szelenkov@nginx.com self.certificate() 213781Szelenkov@nginx.com 2141596Szelenkov@nginx.com assert ( 2151596Szelenkov@nginx.com self.conf_get('/certificates/default/key') == 'RSA (2048 bits)' 2161596Szelenkov@nginx.com ), 'certificate key rsa' 217781Szelenkov@nginx.com 2181654Szelenkov@nginx.com def test_tls_certificate_key_ec(self, temp_dir): 219807Spluknet@nginx.com self.load('empty') 220807Spluknet@nginx.com 2211100Szelenkov@nginx.com self.openssl_conf() 2221100Szelenkov@nginx.com 223*2004Szelenkov@nginx.com subprocess.check_output( 2241017Szelenkov@nginx.com [ 2251017Szelenkov@nginx.com 'openssl', 2261017Szelenkov@nginx.com 'ecparam', 2271017Szelenkov@nginx.com '-noout', 2281017Szelenkov@nginx.com '-genkey', 2291596Szelenkov@nginx.com '-out', 2301654Szelenkov@nginx.com temp_dir + '/ec.key', 2311596Szelenkov@nginx.com '-name', 2321596Szelenkov@nginx.com 'prime256v1', 2331388Szelenkov@nginx.com ], 2341388Szelenkov@nginx.com stderr=subprocess.STDOUT, 2351017Szelenkov@nginx.com ) 236781Szelenkov@nginx.com 237*2004Szelenkov@nginx.com subprocess.check_output( 2381017Szelenkov@nginx.com [ 2391017Szelenkov@nginx.com 'openssl', 2401017Szelenkov@nginx.com 'req', 2411017Szelenkov@nginx.com '-x509', 2421017Szelenkov@nginx.com '-new', 2431596Szelenkov@nginx.com '-subj', 2441596Szelenkov@nginx.com '/CN=ec/', 2451596Szelenkov@nginx.com '-config', 2461654Szelenkov@nginx.com temp_dir + '/openssl.conf', 2471596Szelenkov@nginx.com '-key', 2481654Szelenkov@nginx.com temp_dir + '/ec.key', 2491596Szelenkov@nginx.com '-out', 2501654Szelenkov@nginx.com temp_dir + '/ec.crt', 2511388Szelenkov@nginx.com ], 2521388Szelenkov@nginx.com stderr=subprocess.STDOUT, 2531017Szelenkov@nginx.com ) 254781Szelenkov@nginx.com 255781Szelenkov@nginx.com self.certificate_load('ec') 256781Szelenkov@nginx.com 2571596Szelenkov@nginx.com assert ( 2581596Szelenkov@nginx.com self.conf_get('/certificates/ec/key') == 'ECDH' 2591596Szelenkov@nginx.com ), 'certificate key ec' 260781Szelenkov@nginx.com 261781Szelenkov@nginx.com def test_tls_certificate_chain_options(self): 262781Szelenkov@nginx.com self.load('empty') 263781Szelenkov@nginx.com 264781Szelenkov@nginx.com self.certificate() 265781Szelenkov@nginx.com 266781Szelenkov@nginx.com chain = self.conf_get('/certificates/default/chain') 267781Szelenkov@nginx.com 2681596Szelenkov@nginx.com assert len(chain) == 1, 'certificate chain length' 269781Szelenkov@nginx.com 270781Szelenkov@nginx.com cert = chain[0] 271781Szelenkov@nginx.com 2721596Szelenkov@nginx.com assert ( 2731596Szelenkov@nginx.com cert['subject']['common_name'] == 'default' 2741596Szelenkov@nginx.com ), 'certificate subject common name' 2751596Szelenkov@nginx.com assert ( 2761596Szelenkov@nginx.com cert['issuer']['common_name'] == 'default' 2771596Szelenkov@nginx.com ), 'certificate issuer common name' 278781Szelenkov@nginx.com 2791596Szelenkov@nginx.com assert ( 2801017Szelenkov@nginx.com abs( 2811017Szelenkov@nginx.com self.sec_epoch() 2821017Szelenkov@nginx.com - self.openssl_date_to_sec_epoch(cert['validity']['since']) 2831596Szelenkov@nginx.com ) 2841803Szelenkov@nginx.com < 60 2851596Szelenkov@nginx.com ), 'certificate validity since' 2861596Szelenkov@nginx.com assert ( 2871017Szelenkov@nginx.com self.openssl_date_to_sec_epoch(cert['validity']['until']) 2881596Szelenkov@nginx.com - self.openssl_date_to_sec_epoch(cert['validity']['since']) 2891596Szelenkov@nginx.com == 2592000 2901596Szelenkov@nginx.com ), 'certificate validity until' 291781Szelenkov@nginx.com 2921654Szelenkov@nginx.com def test_tls_certificate_chain(self, temp_dir): 293781Szelenkov@nginx.com self.load('empty') 294781Szelenkov@nginx.com 295781Szelenkov@nginx.com self.certificate('root', False) 296781Szelenkov@nginx.com 2971863Szelenkov@nginx.com self.req('int') 2981863Szelenkov@nginx.com self.req('end') 299781Szelenkov@nginx.com 3001863Szelenkov@nginx.com self.generate_ca_conf() 301781Szelenkov@nginx.com 3021863Szelenkov@nginx.com self.ca(cert='root', out='int') 3031863Szelenkov@nginx.com self.ca(cert='int', out='end') 304781Szelenkov@nginx.com 3051654Szelenkov@nginx.com crt_path = temp_dir + '/end-int.crt' 3061654Szelenkov@nginx.com end_path = temp_dir + '/end.crt' 3071654Szelenkov@nginx.com int_path = temp_dir + '/int.crt' 3081017Szelenkov@nginx.com 3091596Szelenkov@nginx.com with open(crt_path, 'wb') as crt, open(end_path, 'rb') as end, open( 3101596Szelenkov@nginx.com int_path, 'rb' 3111596Szelenkov@nginx.com ) as int: 3121017Szelenkov@nginx.com crt.write(end.read() + int.read()) 313781Szelenkov@nginx.com 3141863Szelenkov@nginx.com self.set_certificate_req_context() 315781Szelenkov@nginx.com 316781Szelenkov@nginx.com # incomplete chain 317781Szelenkov@nginx.com 3181596Szelenkov@nginx.com assert 'success' in self.certificate_load( 3191596Szelenkov@nginx.com 'end', 'end' 3201596Szelenkov@nginx.com ), 'certificate chain end upload' 321781Szelenkov@nginx.com 322781Szelenkov@nginx.com chain = self.conf_get('/certificates/end/chain') 3231596Szelenkov@nginx.com assert len(chain) == 1, 'certificate chain end length' 3241596Szelenkov@nginx.com assert ( 3251596Szelenkov@nginx.com chain[0]['subject']['common_name'] == 'end' 3261596Szelenkov@nginx.com ), 'certificate chain end subject common name' 3271596Szelenkov@nginx.com assert ( 3281596Szelenkov@nginx.com chain[0]['issuer']['common_name'] == 'int' 3291596Szelenkov@nginx.com ), 'certificate chain end issuer common name' 330781Szelenkov@nginx.com 331781Szelenkov@nginx.com self.add_tls(cert='end') 332781Szelenkov@nginx.com 333781Szelenkov@nginx.com try: 334781Szelenkov@nginx.com resp = self.get_ssl() 335781Szelenkov@nginx.com except ssl.SSLError: 336781Szelenkov@nginx.com resp = None 337781Szelenkov@nginx.com 3381596Szelenkov@nginx.com assert resp == None, 'certificate chain incomplete chain' 339781Szelenkov@nginx.com 340781Szelenkov@nginx.com # intermediate 341781Szelenkov@nginx.com 3421596Szelenkov@nginx.com assert 'success' in self.certificate_load( 3431596Szelenkov@nginx.com 'int', 'int' 3441596Szelenkov@nginx.com ), 'certificate chain int upload' 345781Szelenkov@nginx.com 346781Szelenkov@nginx.com chain = self.conf_get('/certificates/int/chain') 3471596Szelenkov@nginx.com assert len(chain) == 1, 'certificate chain int length' 3481596Szelenkov@nginx.com assert ( 3491596Szelenkov@nginx.com chain[0]['subject']['common_name'] == 'int' 3501596Szelenkov@nginx.com ), 'certificate chain int subject common name' 3511596Szelenkov@nginx.com assert ( 3521596Szelenkov@nginx.com chain[0]['issuer']['common_name'] == 'root' 3531596Szelenkov@nginx.com ), 'certificate chain int issuer common name' 354781Szelenkov@nginx.com 355781Szelenkov@nginx.com self.add_tls(cert='int') 356781Szelenkov@nginx.com 3571596Szelenkov@nginx.com assert ( 3581596Szelenkov@nginx.com self.get_ssl()['status'] == 200 3591596Szelenkov@nginx.com ), 'certificate chain intermediate' 360781Szelenkov@nginx.com 361781Szelenkov@nginx.com # intermediate server 362781Szelenkov@nginx.com 3631596Szelenkov@nginx.com assert 'success' in self.certificate_load( 3641596Szelenkov@nginx.com 'end-int', 'end' 3651596Szelenkov@nginx.com ), 'certificate chain end-int upload' 366781Szelenkov@nginx.com 367781Szelenkov@nginx.com chain = self.conf_get('/certificates/end-int/chain') 3681596Szelenkov@nginx.com assert len(chain) == 2, 'certificate chain end-int length' 3691596Szelenkov@nginx.com assert ( 3701596Szelenkov@nginx.com chain[0]['subject']['common_name'] == 'end' 3711596Szelenkov@nginx.com ), 'certificate chain end-int int subject common name' 3721596Szelenkov@nginx.com assert ( 3731596Szelenkov@nginx.com chain[0]['issuer']['common_name'] == 'int' 3741596Szelenkov@nginx.com ), 'certificate chain end-int int issuer common name' 3751596Szelenkov@nginx.com assert ( 3761596Szelenkov@nginx.com chain[1]['subject']['common_name'] == 'int' 3771596Szelenkov@nginx.com ), 'certificate chain end-int end subject common name' 3781596Szelenkov@nginx.com assert ( 3791596Szelenkov@nginx.com chain[1]['issuer']['common_name'] == 'root' 3801596Szelenkov@nginx.com ), 'certificate chain end-int end issuer common name' 381781Szelenkov@nginx.com 382781Szelenkov@nginx.com self.add_tls(cert='end-int') 383781Szelenkov@nginx.com 3841596Szelenkov@nginx.com assert ( 3851596Szelenkov@nginx.com self.get_ssl()['status'] == 200 3861596Szelenkov@nginx.com ), 'certificate chain intermediate server' 387781Szelenkov@nginx.com 3881863Szelenkov@nginx.com def test_tls_certificate_empty_cn(self, temp_dir): 3891863Szelenkov@nginx.com self.certificate('root', False) 3901863Szelenkov@nginx.com 3911863Szelenkov@nginx.com self.req(subject='/') 3921863Szelenkov@nginx.com 3931863Szelenkov@nginx.com self.generate_ca_conf() 3941863Szelenkov@nginx.com self.ca() 3951863Szelenkov@nginx.com 3961863Szelenkov@nginx.com self.set_certificate_req_context() 3971863Szelenkov@nginx.com 3981863Szelenkov@nginx.com assert 'success' in self.certificate_load('localhost', 'localhost') 3991863Szelenkov@nginx.com 4001863Szelenkov@nginx.com cert = self.conf_get('/certificates/localhost') 4011863Szelenkov@nginx.com assert cert['chain'][0]['subject'] == {}, 'empty subject' 4021863Szelenkov@nginx.com assert cert['chain'][0]['issuer']['common_name'] == 'root', 'issuer' 4031863Szelenkov@nginx.com 4041863Szelenkov@nginx.com def test_tls_certificate_empty_cn_san(self, temp_dir): 4051863Szelenkov@nginx.com self.certificate('root', False) 4061863Szelenkov@nginx.com 4071863Szelenkov@nginx.com self.openssl_conf( 4081863Szelenkov@nginx.com rewrite=True, alt_names=["example.com", "www.example.net"] 4091863Szelenkov@nginx.com ) 4101863Szelenkov@nginx.com 4111863Szelenkov@nginx.com self.req(subject='/') 4121863Szelenkov@nginx.com 4131863Szelenkov@nginx.com self.generate_ca_conf() 4141863Szelenkov@nginx.com self.ca() 4151863Szelenkov@nginx.com 4161863Szelenkov@nginx.com self.set_certificate_req_context() 4171863Szelenkov@nginx.com 4181863Szelenkov@nginx.com assert 'success' in self.certificate_load('localhost', 'localhost') 4191863Szelenkov@nginx.com 4201863Szelenkov@nginx.com cert = self.conf_get('/certificates/localhost') 4211863Szelenkov@nginx.com assert cert['chain'][0]['subject'] == { 4221863Szelenkov@nginx.com 'alt_names': ['example.com', 'www.example.net'] 4231863Szelenkov@nginx.com }, 'subject alt_names' 4241863Szelenkov@nginx.com assert cert['chain'][0]['issuer']['common_name'] == 'root', 'issuer' 4251863Szelenkov@nginx.com 4261866Szelenkov@nginx.com def test_tls_certificate_empty_cn_san_ip(self): 4271866Szelenkov@nginx.com self.certificate('root', False) 4281866Szelenkov@nginx.com 4291866Szelenkov@nginx.com self.openssl_conf( 4301866Szelenkov@nginx.com rewrite=True, 4311866Szelenkov@nginx.com alt_names=['example.com', 'www.example.net', 'IP|10.0.0.1'], 4321866Szelenkov@nginx.com ) 4331866Szelenkov@nginx.com 4341866Szelenkov@nginx.com self.req(subject='/') 4351866Szelenkov@nginx.com 4361866Szelenkov@nginx.com self.generate_ca_conf() 4371866Szelenkov@nginx.com self.ca() 4381866Szelenkov@nginx.com 4391866Szelenkov@nginx.com self.set_certificate_req_context() 4401866Szelenkov@nginx.com 4411866Szelenkov@nginx.com assert 'success' in self.certificate_load('localhost', 'localhost') 4421866Szelenkov@nginx.com 4431866Szelenkov@nginx.com cert = self.conf_get('/certificates/localhost') 4441866Szelenkov@nginx.com assert cert['chain'][0]['subject'] == { 4451866Szelenkov@nginx.com 'alt_names': ['example.com', 'www.example.net'] 4461866Szelenkov@nginx.com }, 'subject alt_names' 4471866Szelenkov@nginx.com assert cert['chain'][0]['issuer']['common_name'] == 'root', 'issuer' 4481866Szelenkov@nginx.com 4491596Szelenkov@nginx.com @pytest.mark.skip('not yet') 450781Szelenkov@nginx.com def test_tls_reconfigure(self): 451781Szelenkov@nginx.com self.load('empty') 452781Szelenkov@nginx.com 4531596Szelenkov@nginx.com assert self.get()['status'] == 200, 'init' 4541029Szelenkov@nginx.com 455781Szelenkov@nginx.com self.certificate() 456781Szelenkov@nginx.com 4571017Szelenkov@nginx.com (resp, sock) = self.get( 4581017Szelenkov@nginx.com headers={'Host': 'localhost', 'Connection': 'keep-alive'}, 4591017Szelenkov@nginx.com start=True, 4601029Szelenkov@nginx.com read_timeout=1, 4611017Szelenkov@nginx.com ) 462898Szelenkov@nginx.com 4631596Szelenkov@nginx.com assert resp['status'] == 200, 'initial status' 464781Szelenkov@nginx.com 465781Szelenkov@nginx.com self.add_tls() 466781Szelenkov@nginx.com 4671596Szelenkov@nginx.com assert self.get(sock=sock)['status'] == 200, 'reconfigure status' 4681596Szelenkov@nginx.com assert self.get_ssl()['status'] == 200, 'reconfigure tls status' 469781Szelenkov@nginx.com 470781Szelenkov@nginx.com def test_tls_keepalive(self): 471781Szelenkov@nginx.com self.load('mirror') 472781Szelenkov@nginx.com 4731596Szelenkov@nginx.com assert self.get()['status'] == 200, 'init' 4741029Szelenkov@nginx.com 475781Szelenkov@nginx.com self.certificate() 476781Szelenkov@nginx.com 477781Szelenkov@nginx.com self.add_tls(application='mirror') 478781Szelenkov@nginx.com 4791017Szelenkov@nginx.com (resp, sock) = self.post_ssl( 4801017Szelenkov@nginx.com headers={ 4811017Szelenkov@nginx.com 'Host': 'localhost', 4821017Szelenkov@nginx.com 'Connection': 'keep-alive', 4831017Szelenkov@nginx.com 'Content-Type': 'text/html', 4841017Szelenkov@nginx.com }, 4851017Szelenkov@nginx.com start=True, 4861017Szelenkov@nginx.com body='0123456789', 4871029Szelenkov@nginx.com read_timeout=1, 4881017Szelenkov@nginx.com ) 489781Szelenkov@nginx.com 4901596Szelenkov@nginx.com assert resp['body'] == '0123456789', 'keepalive 1' 491781Szelenkov@nginx.com 4921017Szelenkov@nginx.com resp = self.post_ssl( 4931017Szelenkov@nginx.com headers={ 4941017Szelenkov@nginx.com 'Host': 'localhost', 4951017Szelenkov@nginx.com 'Connection': 'close', 4961017Szelenkov@nginx.com 'Content-Type': 'text/html', 4971017Szelenkov@nginx.com }, 4981017Szelenkov@nginx.com sock=sock, 4991017Szelenkov@nginx.com body='0123456789', 5001017Szelenkov@nginx.com ) 501781Szelenkov@nginx.com 5021596Szelenkov@nginx.com assert resp['body'] == '0123456789', 'keepalive 2' 503781Szelenkov@nginx.com 5041886Szelenkov@nginx.com def test_tls_no_close_notify(self): 5051886Szelenkov@nginx.com self.certificate() 5061886Szelenkov@nginx.com 5071886Szelenkov@nginx.com assert 'success' in self.conf( 5081886Szelenkov@nginx.com { 5091886Szelenkov@nginx.com "listeners": { 5101886Szelenkov@nginx.com "*:7080": { 5111886Szelenkov@nginx.com "pass": "routes", 5121886Szelenkov@nginx.com "tls": {"certificate": "default"}, 5131886Szelenkov@nginx.com } 5141886Szelenkov@nginx.com }, 5151886Szelenkov@nginx.com "routes": [{"action": {"return": 200}}], 5161886Szelenkov@nginx.com "applications": {}, 5171886Szelenkov@nginx.com } 5181886Szelenkov@nginx.com ), 'load application configuration' 5191886Szelenkov@nginx.com 5201886Szelenkov@nginx.com (resp, sock) = self.get_ssl(start=True) 5211886Szelenkov@nginx.com 5221886Szelenkov@nginx.com time.sleep(5) 5231886Szelenkov@nginx.com 5241886Szelenkov@nginx.com sock.close() 5251886Szelenkov@nginx.com 5261596Szelenkov@nginx.com @pytest.mark.skip('not yet') 527781Szelenkov@nginx.com def test_tls_keepalive_certificate_remove(self): 528781Szelenkov@nginx.com self.load('empty') 529781Szelenkov@nginx.com 5301596Szelenkov@nginx.com assert self.get()['status'] == 200, 'init' 5311029Szelenkov@nginx.com 532781Szelenkov@nginx.com self.certificate() 533781Szelenkov@nginx.com 534781Szelenkov@nginx.com self.add_tls() 535781Szelenkov@nginx.com 5361017Szelenkov@nginx.com (resp, sock) = self.get_ssl( 5371017Szelenkov@nginx.com headers={'Host': 'localhost', 'Connection': 'keep-alive'}, 5381017Szelenkov@nginx.com start=True, 5391029Szelenkov@nginx.com read_timeout=1, 5401017Szelenkov@nginx.com ) 541781Szelenkov@nginx.com 5421775Szelenkov@nginx.com assert 'success' in self.conf( 5431775Szelenkov@nginx.com {"pass": "applications/empty"}, 'listeners/*:7080' 5441775Szelenkov@nginx.com ) 5451775Szelenkov@nginx.com assert 'success' in self.conf_delete('/certificates/default') 546781Szelenkov@nginx.com 547781Szelenkov@nginx.com try: 5481017Szelenkov@nginx.com resp = self.get_ssl( 5491017Szelenkov@nginx.com headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock 5501017Szelenkov@nginx.com ) 5511706Smax.romanov@nginx.com 5521706Smax.romanov@nginx.com except KeyboardInterrupt: 5531706Smax.romanov@nginx.com raise 5541706Smax.romanov@nginx.com 555781Szelenkov@nginx.com except: 556781Szelenkov@nginx.com resp = None 557781Szelenkov@nginx.com 5581596Szelenkov@nginx.com assert resp == None, 'keepalive remove certificate' 559781Szelenkov@nginx.com 5601596Szelenkov@nginx.com @pytest.mark.skip('not yet') 561781Szelenkov@nginx.com def test_tls_certificates_remove_all(self): 562781Szelenkov@nginx.com self.load('empty') 563781Szelenkov@nginx.com 564781Szelenkov@nginx.com self.certificate() 565781Szelenkov@nginx.com 5661596Szelenkov@nginx.com assert 'success' in self.conf_delete( 5671596Szelenkov@nginx.com '/certificates' 5681596Szelenkov@nginx.com ), 'remove all certificates' 569781Szelenkov@nginx.com 5701736Szelenkov@nginx.com def test_tls_application_respawn(self, skip_alert): 571781Szelenkov@nginx.com self.load('mirror') 572781Szelenkov@nginx.com 573781Szelenkov@nginx.com self.certificate() 574781Szelenkov@nginx.com 5751775Szelenkov@nginx.com assert 'success' in self.conf('1', 'applications/mirror/processes') 576781Szelenkov@nginx.com 577781Szelenkov@nginx.com self.add_tls(application='mirror') 578781Szelenkov@nginx.com 5791453Szelenkov@nginx.com (_, sock) = self.post_ssl( 5801017Szelenkov@nginx.com headers={ 5811017Szelenkov@nginx.com 'Host': 'localhost', 5821017Szelenkov@nginx.com 'Connection': 'keep-alive', 5831017Szelenkov@nginx.com 'Content-Type': 'text/html', 5841017Szelenkov@nginx.com }, 5851017Szelenkov@nginx.com start=True, 5861017Szelenkov@nginx.com body='0123456789', 5871029Szelenkov@nginx.com read_timeout=1, 5881017Szelenkov@nginx.com ) 589781Szelenkov@nginx.com 590781Szelenkov@nginx.com app_id = self.findall(r'(\d+)#\d+ "mirror" application started')[0] 591781Szelenkov@nginx.com 592*2004Szelenkov@nginx.com subprocess.check_output(['kill', '-9', app_id]) 593781Szelenkov@nginx.com 5941999Smax.romanov@nginx.com skip_alert(r'process .* %s.* exited on signal 9' % app_id) 5951453Szelenkov@nginx.com 5961017Szelenkov@nginx.com self.wait_for_record( 5971017Szelenkov@nginx.com re.compile( 5981635Szelenkov@nginx.com r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started' 5991017Szelenkov@nginx.com ) 6001017Szelenkov@nginx.com ) 601781Szelenkov@nginx.com 6021017Szelenkov@nginx.com resp = self.post_ssl( 6031017Szelenkov@nginx.com headers={ 6041017Szelenkov@nginx.com 'Host': 'localhost', 6051017Szelenkov@nginx.com 'Connection': 'close', 6061017Szelenkov@nginx.com 'Content-Type': 'text/html', 6071017Szelenkov@nginx.com }, 6081017Szelenkov@nginx.com sock=sock, 6091017Szelenkov@nginx.com body='0123456789', 6101017Szelenkov@nginx.com ) 611781Szelenkov@nginx.com 6121596Szelenkov@nginx.com assert resp['status'] == 200, 'application respawn status' 6131596Szelenkov@nginx.com assert resp['body'] == '0123456789', 'application respawn body' 614781Szelenkov@nginx.com 6151011Smax.romanov@nginx.com def test_tls_url_scheme(self): 6161011Smax.romanov@nginx.com self.load('variables') 6171011Smax.romanov@nginx.com 6181596Szelenkov@nginx.com assert ( 6191017Szelenkov@nginx.com self.post( 6201017Szelenkov@nginx.com headers={ 6211017Szelenkov@nginx.com 'Host': 'localhost', 6221017Szelenkov@nginx.com 'Content-Type': 'text/html', 6231017Szelenkov@nginx.com 'Custom-Header': '', 6241017Szelenkov@nginx.com 'Connection': 'close', 6251017Szelenkov@nginx.com } 6261596Szelenkov@nginx.com )['headers']['Wsgi-Url-Scheme'] 6271596Szelenkov@nginx.com == 'http' 6281596Szelenkov@nginx.com ), 'url scheme http' 6291011Smax.romanov@nginx.com 6301011Smax.romanov@nginx.com self.certificate() 6311011Smax.romanov@nginx.com 6321011Smax.romanov@nginx.com self.add_tls(application='variables') 6331011Smax.romanov@nginx.com 6341596Szelenkov@nginx.com assert ( 6351017Szelenkov@nginx.com self.post_ssl( 6361017Szelenkov@nginx.com headers={ 6371017Szelenkov@nginx.com 'Host': 'localhost', 6381017Szelenkov@nginx.com 'Content-Type': 'text/html', 6391017Szelenkov@nginx.com 'Custom-Header': '', 6401017Szelenkov@nginx.com 'Connection': 'close', 6411017Szelenkov@nginx.com } 6421596Szelenkov@nginx.com )['headers']['Wsgi-Url-Scheme'] 6431596Szelenkov@nginx.com == 'https' 6441596Szelenkov@nginx.com ), 'url scheme https' 6451011Smax.romanov@nginx.com 6461356St.nateldemoura@f5.com def test_tls_big_upload(self): 6471356St.nateldemoura@f5.com self.load('upload') 6481356St.nateldemoura@f5.com 6491356St.nateldemoura@f5.com self.certificate() 6501356St.nateldemoura@f5.com 6511356St.nateldemoura@f5.com self.add_tls(application='upload') 6521356St.nateldemoura@f5.com 6531356St.nateldemoura@f5.com filename = 'test.txt' 6541356St.nateldemoura@f5.com data = '0123456789' * 9000 6551356St.nateldemoura@f5.com 6561596Szelenkov@nginx.com res = self.post_ssl( 6571596Szelenkov@nginx.com body={ 6581596Szelenkov@nginx.com 'file': { 6591596Szelenkov@nginx.com 'filename': filename, 6601596Szelenkov@nginx.com 'type': 'text/plain', 6611596Szelenkov@nginx.com 'data': io.StringIO(data), 6621596Szelenkov@nginx.com } 6631356St.nateldemoura@f5.com } 6641596Szelenkov@nginx.com ) 6651596Szelenkov@nginx.com assert res['status'] == 200, 'status ok' 6661596Szelenkov@nginx.com assert res['body'] == filename + data 6671904Smax.romanov@nginx.com 6681904Smax.romanov@nginx.com def test_tls_multi_listener(self): 6691904Smax.romanov@nginx.com self.load('empty') 6701904Smax.romanov@nginx.com 6711904Smax.romanov@nginx.com self.certificate() 6721904Smax.romanov@nginx.com 6731904Smax.romanov@nginx.com self.add_tls() 6741904Smax.romanov@nginx.com self.add_tls(port=7081) 6751904Smax.romanov@nginx.com 6761904Smax.romanov@nginx.com assert self.get_ssl()['status'] == 200, 'listener #1' 6771904Smax.romanov@nginx.com 6781904Smax.romanov@nginx.com assert self.get_ssl(port=7081)['status'] == 200, 'listener #2' 679