Skip to content

Commit 1ff1b89

Browse files
authored
gh-119400: make_ssl_certs: update reference test data automatically, pass in expiration dates as parameters #119400 (GH-119401)
* Lib/test/certdata: do not hardcode reference cert data into tests The script was simply printing the reference data and asking users to update it by hand into the test suites. This can be easily improved by writing the data into files and having the test cases load the files. * make_ssl_certs: make it possible to pass in expiration dates from command line Note that in this commit, the defaults are same as they were, so if nothing is specified the script works as before. --------- Signed-off-by: Alexander Kanavin <[email protected]>
1 parent 17a544b commit 1ff1b89

File tree

6 files changed

+72
-72
lines changed

6 files changed

+72
-72
lines changed
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{'issuer': ((('countryName', 'XY'),),
2+
(('localityName', 'Castle Anthrax'),),
3+
(('organizationName', 'Python Software Foundation'),),
4+
(('commonName', 'localhost'),)),
5+
'notAfter': 'Jan 24 04:21:36 2043 GMT',
6+
'notBefore': 'Nov 25 04:21:36 2023 GMT',
7+
'serialNumber': '53E14833F7546C29256DD0F034F776C5E983004C',
8+
'subject': ((('countryName', 'XY'),),
9+
(('localityName', 'Castle Anthrax'),),
10+
(('organizationName', 'Python Software Foundation'),),
11+
(('commonName', 'localhost'),)),
12+
'subjectAltName': (('DNS', 'localhost'),),
13+
'version': 3}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
2+
'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
3+
'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
4+
'issuer': ((('countryName', 'XY'),),
5+
(('organizationName', 'Python Software Foundation CA'),),
6+
(('commonName', 'our-ca-server'),)),
7+
'notAfter': 'Oct 28 14:23:16 2037 GMT',
8+
'notBefore': 'Aug 29 14:23:16 2018 GMT',
9+
'serialNumber': 'CB2D80995A69525C',
10+
'subject': ((('countryName', 'XY'),),
11+
(('localityName', 'Castle Anthrax'),),
12+
(('organizationName', 'Python Software Foundation'),),
13+
(('commonName', 'localhost'),)),
14+
'subjectAltName': (('DNS', 'localhost'),),
15+
'version': 3}

Lib/test/certdata/make_ssl_certs.py

+34-22
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
"""Make the custom certificate and private key files used by test_ssl
22
and friends."""
33

4+
import argparse
45
import os
56
import pprint
67
import shutil
78
import tempfile
89
from subprocess import *
910

1011
startdate = "20180829142316Z"
11-
enddate = "20371028142316Z"
12+
enddate_default = "20371028142316Z"
13+
days_default = "7000"
1214

1315
req_template = """
1416
[ default ]
@@ -79,8 +81,8 @@
7981
default_startdate = {startdate}
8082
enddate = {enddate}
8183
default_enddate = {enddate}
82-
default_days = 7000
83-
default_crl_days = 7000
84+
default_days = {days}
85+
default_crl_days = {days}
8486
certificate = pycacert.pem
8587
private_key = pycakey.pem
8688
serial = $dir/serial
@@ -117,7 +119,7 @@
117119
here = os.path.abspath(os.path.dirname(__file__))
118120

119121

120-
def make_cert_key(hostname, sign=False, extra_san='',
122+
def make_cert_key(cmdlineargs, hostname, sign=False, extra_san='',
121123
ext='req_x509_extensions_full', key='rsa:3072'):
122124
print("creating cert for " + hostname)
123125
tempnames = []
@@ -130,11 +132,12 @@ def make_cert_key(hostname, sign=False, extra_san='',
130132
hostname=hostname,
131133
extra_san=extra_san,
132134
startdate=startdate,
133-
enddate=enddate
135+
enddate=cmdlineargs.enddate,
136+
days=cmdlineargs.days
134137
)
135138
with open(req_file, 'w') as f:
136139
f.write(req)
137-
args = ['req', '-new', '-nodes', '-days', '7000',
140+
args = ['req', '-new', '-nodes', '-days', cmdlineargs.days,
138141
'-newkey', key, '-keyout', key_file,
139142
'-extensions', ext,
140143
'-config', req_file]
@@ -175,7 +178,7 @@ def make_cert_key(hostname, sign=False, extra_san='',
175178
def unmake_ca():
176179
shutil.rmtree(TMP_CADIR)
177180

178-
def make_ca():
181+
def make_ca(cmdlineargs):
179182
os.mkdir(TMP_CADIR)
180183
with open(os.path.join('cadir','index.txt'),'a+') as f:
181184
pass # empty file
@@ -192,7 +195,8 @@ def make_ca():
192195
hostname='our-ca-server',
193196
extra_san='',
194197
startdate=startdate,
195-
enddate=enddate
198+
enddate=cmdlineargs.enddate,
199+
days=cmdlineargs.days
196200
)
197201
t.write(req)
198202
t.flush()
@@ -219,14 +223,22 @@ def make_ca():
219223
shutil.copy('capath/ceff1710.0', 'capath/b1930218.0')
220224

221225

222-
def print_cert(path):
226+
def write_cert_reference(path):
223227
import _ssl
224-
pprint.pprint(_ssl._test_decode_cert(path))
228+
refdata = pprint.pformat(_ssl._test_decode_cert(path))
229+
print(refdata)
230+
with open(path + '.reference', 'w') as f:
231+
print(refdata, file=f)
225232

226233

227234
if __name__ == '__main__':
235+
parser = argparse.ArgumentParser(description='Make the custom certificate and private key files used by test_ssl and friends.')
236+
parser.add_argument('--days', default=days_default)
237+
parser.add_argument('--enddate', default=enddate_default)
238+
cmdlineargs = parser.parse_args()
239+
228240
os.chdir(here)
229-
cert, key = make_cert_key('localhost', ext='req_x509_extensions_simple')
241+
cert, key = make_cert_key(cmdlineargs, 'localhost', ext='req_x509_extensions_simple')
230242
with open('ssl_cert.pem', 'w') as f:
231243
f.write(cert)
232244
with open('ssl_key.pem', 'w') as f:
@@ -243,24 +255,24 @@ def print_cert(path):
243255
f.write(cert)
244256

245257
# For certificate matching tests
246-
make_ca()
247-
cert, key = make_cert_key('fakehostname', ext='req_x509_extensions_simple')
258+
make_ca(cmdlineargs)
259+
cert, key = make_cert_key(cmdlineargs, 'fakehostname', ext='req_x509_extensions_simple')
248260
with open('keycert2.pem', 'w') as f:
249261
f.write(key)
250262
f.write(cert)
251263

252-
cert, key = make_cert_key('localhost', sign=True)
264+
cert, key = make_cert_key(cmdlineargs, 'localhost', sign=True)
253265
with open('keycert3.pem', 'w') as f:
254266
f.write(key)
255267
f.write(cert)
256268

257-
cert, key = make_cert_key('fakehostname', sign=True)
269+
cert, key = make_cert_key(cmdlineargs, 'fakehostname', sign=True)
258270
with open('keycert4.pem', 'w') as f:
259271
f.write(key)
260272
f.write(cert)
261273

262274
cert, key = make_cert_key(
263-
'localhost-ecc', sign=True, key='param:secp384r1.pem'
275+
cmdlineargs, 'localhost-ecc', sign=True, key='param:secp384r1.pem'
264276
)
265277
with open('keycertecc.pem', 'w') as f:
266278
f.write(key)
@@ -280,7 +292,7 @@ def print_cert(path):
280292
'RID.1 = 1.2.3.4.5',
281293
]
282294

283-
cert, key = make_cert_key('allsans', sign=True, extra_san='\n'.join(extra_san))
295+
cert, key = make_cert_key(cmdlineargs, 'allsans', sign=True, extra_san='\n'.join(extra_san))
284296
with open('allsans.pem', 'w') as f:
285297
f.write(key)
286298
f.write(cert)
@@ -297,17 +309,17 @@ def print_cert(path):
297309
]
298310

299311
# IDN SANS, signed
300-
cert, key = make_cert_key('idnsans', sign=True, extra_san='\n'.join(extra_san))
312+
cert, key = make_cert_key(cmdlineargs, 'idnsans', sign=True, extra_san='\n'.join(extra_san))
301313
with open('idnsans.pem', 'w') as f:
302314
f.write(key)
303315
f.write(cert)
304316

305-
cert, key = make_cert_key('nosan', sign=True, ext='req_x509_extensions_nosan')
317+
cert, key = make_cert_key(cmdlineargs, 'nosan', sign=True, ext='req_x509_extensions_nosan')
306318
with open('nosan.pem', 'w') as f:
307319
f.write(key)
308320
f.write(cert)
309321

310322
unmake_ca()
311-
print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py")
312-
print_cert('keycert.pem')
313-
print_cert('keycert3.pem')
323+
print("Writing out reference data for Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py")
324+
write_cert_reference('keycert.pem')
325+
write_cert_reference('keycert3.pem')

Lib/test/test_asyncio/utils.py

+3-18
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import unittest
1616
import weakref
1717
import warnings
18+
from ast import literal_eval
1819
from unittest import mock
1920

2021
from http.server import HTTPServer
@@ -56,24 +57,8 @@ def data_file(*filename):
5657
ONLYKEY = data_file('certdata', 'ssl_key.pem')
5758
SIGNED_CERTFILE = data_file('certdata', 'keycert3.pem')
5859
SIGNING_CA = data_file('certdata', 'pycacert.pem')
59-
PEERCERT = {
60-
'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
61-
'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
62-
'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
63-
'issuer': ((('countryName', 'XY'),),
64-
(('organizationName', 'Python Software Foundation CA'),),
65-
(('commonName', 'our-ca-server'),)),
66-
'notAfter': 'Oct 28 14:23:16 2037 GMT',
67-
'notBefore': 'Aug 29 14:23:16 2018 GMT',
68-
'serialNumber': 'CB2D80995A69525C',
69-
'subject': ((('countryName', 'XY'),),
70-
(('localityName', 'Castle Anthrax'),),
71-
(('organizationName', 'Python Software Foundation'),),
72-
(('commonName', 'localhost'),)),
73-
'subjectAltName': (('DNS', 'localhost'),),
74-
'version': 3
75-
}
76-
60+
with open(data_file('certdata', 'keycert3.pem.reference')) as file:
61+
PEERCERT = literal_eval(file.read())
7762

7863
def simple_server_sslcontext():
7964
server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)

Lib/test/test_ssl.py

+5-32
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
import unittest
55
import unittest.mock
6+
from ast import literal_eval
67
from test import support
78
from test.support import import_helper
89
from test.support import os_helper
@@ -82,21 +83,8 @@ def data_file(*name):
8283
CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
8384
CAFILE_CACERT = data_file("capath", "5ed36f99.0")
8485

85-
CERTFILE_INFO = {
86-
'issuer': ((('countryName', 'XY'),),
87-
(('localityName', 'Castle Anthrax'),),
88-
(('organizationName', 'Python Software Foundation'),),
89-
(('commonName', 'localhost'),)),
90-
'notAfter': 'Jan 24 04:21:36 2043 GMT',
91-
'notBefore': 'Nov 25 04:21:36 2023 GMT',
92-
'serialNumber': '53E14833F7546C29256DD0F034F776C5E983004C',
93-
'subject': ((('countryName', 'XY'),),
94-
(('localityName', 'Castle Anthrax'),),
95-
(('organizationName', 'Python Software Foundation'),),
96-
(('commonName', 'localhost'),)),
97-
'subjectAltName': (('DNS', 'localhost'),),
98-
'version': 3
99-
}
86+
with open(data_file('keycert.pem.reference')) as file:
87+
CERTFILE_INFO = literal_eval(file.read())
10088

10189
# empty CRL
10290
CRLFILE = data_file("revocation.crl")
@@ -106,23 +94,8 @@ def data_file(*name):
10694
SINGED_CERTFILE_ONLY = data_file("cert3.pem")
10795
SIGNED_CERTFILE_HOSTNAME = 'localhost'
10896

109-
SIGNED_CERTFILE_INFO = {
110-
'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
111-
'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
112-
'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
113-
'issuer': ((('countryName', 'XY'),),
114-
(('organizationName', 'Python Software Foundation CA'),),
115-
(('commonName', 'our-ca-server'),)),
116-
'notAfter': 'Oct 28 14:23:16 2037 GMT',
117-
'notBefore': 'Aug 29 14:23:16 2018 GMT',
118-
'serialNumber': 'CB2D80995A69525C',
119-
'subject': ((('countryName', 'XY'),),
120-
(('localityName', 'Castle Anthrax'),),
121-
(('organizationName', 'Python Software Foundation'),),
122-
(('commonName', 'localhost'),)),
123-
'subjectAltName': (('DNS', 'localhost'),),
124-
'version': 3
125-
}
97+
with open(data_file('keycert3.pem.reference')) as file:
98+
SIGNED_CERTFILE_INFO = literal_eval(file.read())
12699

127100
SIGNED_CERTFILE2 = data_file("keycert4.pem")
128101
SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``make_ssl_certs``, the script that prepares certificate data for the
2+
test suite, now allows specifying expiration dates.

0 commit comments

Comments
 (0)