xref: /unit/test/test_tls.py (revision 2004)
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