]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-119400: make_ssl_certs: update reference test data automatically, pass in expirat...
authorAlexander Kanavin <alex.kanavin@gmail.com>
Wed, 25 Sep 2024 21:23:47 +0000 (23:23 +0200)
committerGitHub <noreply@github.com>
Wed, 25 Sep 2024 21:23:47 +0000 (21:23 +0000)
* 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 <alex.kanavin@gmail.com>
Lib/test/certdata/keycert.pem.reference [new file with mode: 0644]
Lib/test/certdata/keycert3.pem.reference [new file with mode: 0644]
Lib/test/certdata/make_ssl_certs.py
Lib/test/test_asyncio/utils.py
Lib/test/test_ssl.py
Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst [new file with mode: 0644]

diff --git a/Lib/test/certdata/keycert.pem.reference b/Lib/test/certdata/keycert.pem.reference
new file mode 100644 (file)
index 0000000..f9a82f3
--- /dev/null
@@ -0,0 +1,13 @@
+{'issuer': ((('countryName', 'XY'),),
+            (('localityName', 'Castle Anthrax'),),
+            (('organizationName', 'Python Software Foundation'),),
+            (('commonName', 'localhost'),)),
+ 'notAfter': 'Jan 24 04:21:36 2043 GMT',
+ 'notBefore': 'Nov 25 04:21:36 2023 GMT',
+ 'serialNumber': '53E14833F7546C29256DD0F034F776C5E983004C',
+ 'subject': ((('countryName', 'XY'),),
+             (('localityName', 'Castle Anthrax'),),
+             (('organizationName', 'Python Software Foundation'),),
+             (('commonName', 'localhost'),)),
+ 'subjectAltName': (('DNS', 'localhost'),),
+ 'version': 3}
diff --git a/Lib/test/certdata/keycert3.pem.reference b/Lib/test/certdata/keycert3.pem.reference
new file mode 100644 (file)
index 0000000..04a749c
--- /dev/null
@@ -0,0 +1,15 @@
+{'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
+ 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
+ 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
+ 'issuer': ((('countryName', 'XY'),),
+            (('organizationName', 'Python Software Foundation CA'),),
+            (('commonName', 'our-ca-server'),)),
+ 'notAfter': 'Oct 28 14:23:16 2037 GMT',
+ 'notBefore': 'Aug 29 14:23:16 2018 GMT',
+ 'serialNumber': 'CB2D80995A69525C',
+ 'subject': ((('countryName', 'XY'),),
+             (('localityName', 'Castle Anthrax'),),
+             (('organizationName', 'Python Software Foundation'),),
+             (('commonName', 'localhost'),)),
+ 'subjectAltName': (('DNS', 'localhost'),),
+ 'version': 3}
\ No newline at end of file
index 6626b93976a585c0169b8d513c1a037f81074edd..5e626baf550c5b1bfd58d3ad02b13d84976f59fa 100644 (file)
@@ -1,6 +1,7 @@
 """Make the custom certificate and private key files used by test_ssl
 and friends."""
 
+import argparse
 import os
 import pprint
 import shutil
@@ -8,7 +9,8 @@ import tempfile
 from subprocess import *
 
 startdate = "20180829142316Z"
-enddate = "20371028142316Z"
+enddate_default = "20371028142316Z"
+days_default = "7000"
 
 req_template = """
     [ default ]
@@ -79,8 +81,8 @@ req_template = """
     default_startdate = {startdate}
     enddate = {enddate}
     default_enddate = {enddate}
-    default_days = 7000
-    default_crl_days = 7000
+    default_days = {days}
+    default_crl_days = {days}
     certificate = pycacert.pem
     private_key = pycakey.pem
     serial    = $dir/serial
@@ -117,7 +119,7 @@ req_template = """
 here = os.path.abspath(os.path.dirname(__file__))
 
 
-def make_cert_key(hostname, sign=False, extra_san='',
+def make_cert_key(cmdlineargs, hostname, sign=False, extra_san='',
                   ext='req_x509_extensions_full', key='rsa:3072'):
     print("creating cert for " + hostname)
     tempnames = []
@@ -130,11 +132,12 @@ def make_cert_key(hostname, sign=False, extra_san='',
             hostname=hostname,
             extra_san=extra_san,
             startdate=startdate,
-            enddate=enddate
+            enddate=cmdlineargs.enddate,
+            days=cmdlineargs.days
         )
         with open(req_file, 'w') as f:
             f.write(req)
-        args = ['req', '-new', '-nodes', '-days', '7000',
+        args = ['req', '-new', '-nodes', '-days', cmdlineargs.days,
                 '-newkey', key, '-keyout', key_file,
                 '-extensions', ext,
                 '-config', req_file]
@@ -175,7 +178,7 @@ TMP_CADIR = 'cadir'
 def unmake_ca():
     shutil.rmtree(TMP_CADIR)
 
-def make_ca():
+def make_ca(cmdlineargs):
     os.mkdir(TMP_CADIR)
     with open(os.path.join('cadir','index.txt'),'a+') as f:
         pass # empty file
@@ -192,7 +195,8 @@ def make_ca():
             hostname='our-ca-server',
             extra_san='',
             startdate=startdate,
-            enddate=enddate
+            enddate=cmdlineargs.enddate,
+            days=cmdlineargs.days
         )
         t.write(req)
         t.flush()
@@ -219,14 +223,22 @@ def make_ca():
     shutil.copy('capath/ceff1710.0', 'capath/b1930218.0')
 
 
-def print_cert(path):
+def write_cert_reference(path):
     import _ssl
-    pprint.pprint(_ssl._test_decode_cert(path))
+    refdata = pprint.pformat(_ssl._test_decode_cert(path))
+    print(refdata)
+    with open(path + '.reference', 'w') as f:
+        print(refdata, file=f)
 
 
 if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Make the custom certificate and private key files used by test_ssl and friends.')
+    parser.add_argument('--days', default=days_default)
+    parser.add_argument('--enddate', default=enddate_default)
+    cmdlineargs = parser.parse_args()
+
     os.chdir(here)
-    cert, key = make_cert_key('localhost', ext='req_x509_extensions_simple')
+    cert, key = make_cert_key(cmdlineargs, 'localhost', ext='req_x509_extensions_simple')
     with open('ssl_cert.pem', 'w') as f:
         f.write(cert)
     with open('ssl_key.pem', 'w') as f:
@@ -243,24 +255,24 @@ if __name__ == '__main__':
         f.write(cert)
 
     # For certificate matching tests
-    make_ca()
-    cert, key = make_cert_key('fakehostname', ext='req_x509_extensions_simple')
+    make_ca(cmdlineargs)
+    cert, key = make_cert_key(cmdlineargs, 'fakehostname', ext='req_x509_extensions_simple')
     with open('keycert2.pem', 'w') as f:
         f.write(key)
         f.write(cert)
 
-    cert, key = make_cert_key('localhost', sign=True)
+    cert, key = make_cert_key(cmdlineargs, 'localhost', sign=True)
     with open('keycert3.pem', 'w') as f:
         f.write(key)
         f.write(cert)
 
-    cert, key = make_cert_key('fakehostname', sign=True)
+    cert, key = make_cert_key(cmdlineargs, 'fakehostname', sign=True)
     with open('keycert4.pem', 'w') as f:
         f.write(key)
         f.write(cert)
 
     cert, key = make_cert_key(
-        'localhost-ecc', sign=True, key='param:secp384r1.pem'
+        cmdlineargs, 'localhost-ecc', sign=True, key='param:secp384r1.pem'
     )
     with open('keycertecc.pem', 'w') as f:
         f.write(key)
@@ -280,7 +292,7 @@ if __name__ == '__main__':
         'RID.1 = 1.2.3.4.5',
     ]
 
-    cert, key = make_cert_key('allsans', sign=True, extra_san='\n'.join(extra_san))
+    cert, key = make_cert_key(cmdlineargs, 'allsans', sign=True, extra_san='\n'.join(extra_san))
     with open('allsans.pem', 'w') as f:
         f.write(key)
         f.write(cert)
@@ -297,17 +309,17 @@ if __name__ == '__main__':
     ]
 
     # IDN SANS, signed
-    cert, key = make_cert_key('idnsans', sign=True, extra_san='\n'.join(extra_san))
+    cert, key = make_cert_key(cmdlineargs, 'idnsans', sign=True, extra_san='\n'.join(extra_san))
     with open('idnsans.pem', 'w') as f:
         f.write(key)
         f.write(cert)
 
-    cert, key = make_cert_key('nosan', sign=True, ext='req_x509_extensions_nosan')
+    cert, key = make_cert_key(cmdlineargs, 'nosan', sign=True, ext='req_x509_extensions_nosan')
     with open('nosan.pem', 'w') as f:
         f.write(key)
         f.write(cert)
 
     unmake_ca()
-    print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py")
-    print_cert('keycert.pem')
-    print_cert('keycert3.pem')
+    print("Writing out reference data for Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py")
+    write_cert_reference('keycert.pem')
+    write_cert_reference('keycert3.pem')
index 35893ab3118e1ec6b6a310566206fe19f534723c..b8dbe7feaac3f48927b46055edf6dfe1a39e4ae9 100644 (file)
@@ -15,6 +15,7 @@ import threading
 import unittest
 import weakref
 import warnings
+from ast import literal_eval
 from unittest import mock
 
 from http.server import HTTPServer
@@ -56,24 +57,8 @@ ONLYCERT = data_file('certdata', 'ssl_cert.pem')
 ONLYKEY = data_file('certdata', 'ssl_key.pem')
 SIGNED_CERTFILE = data_file('certdata', 'keycert3.pem')
 SIGNING_CA = data_file('certdata', 'pycacert.pem')
-PEERCERT = {
-    'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
-    'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
-    'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
-    'issuer': ((('countryName', 'XY'),),
-            (('organizationName', 'Python Software Foundation CA'),),
-            (('commonName', 'our-ca-server'),)),
-    'notAfter': 'Oct 28 14:23:16 2037 GMT',
-    'notBefore': 'Aug 29 14:23:16 2018 GMT',
-    'serialNumber': 'CB2D80995A69525C',
-    'subject': ((('countryName', 'XY'),),
-             (('localityName', 'Castle Anthrax'),),
-             (('organizationName', 'Python Software Foundation'),),
-             (('commonName', 'localhost'),)),
-    'subjectAltName': (('DNS', 'localhost'),),
-    'version': 3
-}
-
+with open(data_file('certdata', 'keycert3.pem.reference')) as file:
+    PEERCERT = literal_eval(file.read())
 
 def simple_server_sslcontext():
     server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
index 9c415bd7d1c4e427c5e34f225980e7b65b20fc49..216aa84a8c147b5b912392f4a14395f800a2840b 100644 (file)
@@ -3,6 +3,7 @@
 import sys
 import unittest
 import unittest.mock
+from ast import literal_eval
 from test import support
 from test.support import import_helper
 from test.support import os_helper
@@ -82,21 +83,8 @@ BYTES_CAPATH = os.fsencode(CAPATH)
 CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
 CAFILE_CACERT = data_file("capath", "5ed36f99.0")
 
-CERTFILE_INFO = {
-    'issuer': ((('countryName', 'XY'),),
-               (('localityName', 'Castle Anthrax'),),
-               (('organizationName', 'Python Software Foundation'),),
-               (('commonName', 'localhost'),)),
-    'notAfter': 'Jan 24 04:21:36 2043 GMT',
-    'notBefore': 'Nov 25 04:21:36 2023 GMT',
-    'serialNumber': '53E14833F7546C29256DD0F034F776C5E983004C',
-    'subject': ((('countryName', 'XY'),),
-             (('localityName', 'Castle Anthrax'),),
-             (('organizationName', 'Python Software Foundation'),),
-             (('commonName', 'localhost'),)),
-    'subjectAltName': (('DNS', 'localhost'),),
-    'version': 3
-}
+with open(data_file('keycert.pem.reference')) as file:
+    CERTFILE_INFO = literal_eval(file.read())
 
 # empty CRL
 CRLFILE = data_file("revocation.crl")
@@ -106,23 +94,8 @@ SIGNED_CERTFILE = data_file("keycert3.pem")
 SINGED_CERTFILE_ONLY = data_file("cert3.pem")
 SIGNED_CERTFILE_HOSTNAME = 'localhost'
 
-SIGNED_CERTFILE_INFO = {
-    'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
-    'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
-    'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
-    'issuer': ((('countryName', 'XY'),),
-            (('organizationName', 'Python Software Foundation CA'),),
-            (('commonName', 'our-ca-server'),)),
-    'notAfter': 'Oct 28 14:23:16 2037 GMT',
-    'notBefore': 'Aug 29 14:23:16 2018 GMT',
-    'serialNumber': 'CB2D80995A69525C',
-    'subject': ((('countryName', 'XY'),),
-             (('localityName', 'Castle Anthrax'),),
-             (('organizationName', 'Python Software Foundation'),),
-             (('commonName', 'localhost'),)),
-    'subjectAltName': (('DNS', 'localhost'),),
-    'version': 3
-}
+with open(data_file('keycert3.pem.reference')) as file:
+    SIGNED_CERTFILE_INFO = literal_eval(file.read())
 
 SIGNED_CERTFILE2 = data_file("keycert4.pem")
 SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
diff --git a/Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst b/Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst
new file mode 100644 (file)
index 0000000..b4029f2
--- /dev/null
@@ -0,0 +1,2 @@
+``make_ssl_certs``, the script that prepares certificate data for the
+test suite, now allows specifying expiration dates.