conftest.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # pylint: disable=missing-docstring,invalid-name,redefined-outer-name
  2. import pytest
  3. from OpenSSL import crypto
  4. # Parameter list for valid_cert fixture
  5. VALID_CERTIFICATE_PARAMS = [
  6. {
  7. 'short_name': 'client',
  8. 'cn': 'client.example.com',
  9. 'serial': 4,
  10. 'uses': b'clientAuth',
  11. 'dns': [],
  12. 'ip': [],
  13. },
  14. {
  15. 'short_name': 'server',
  16. 'cn': 'server.example.com',
  17. 'serial': 5,
  18. 'uses': b'serverAuth',
  19. 'dns': ['kubernetes', 'openshift'],
  20. 'ip': ['10.0.0.1', '192.168.0.1']
  21. },
  22. {
  23. 'short_name': 'combined',
  24. 'cn': 'combined.example.com',
  25. 'serial': 6,
  26. 'uses': b'clientAuth, serverAuth',
  27. 'dns': ['etcd'],
  28. 'ip': ['10.0.0.2', '192.168.0.2']
  29. }
  30. ]
  31. # Extract the short_name from VALID_CERTIFICATE_PARAMS to provide
  32. # friendly naming for the valid_cert fixture
  33. VALID_CERTIFICATE_IDS = [param['short_name'] for param in VALID_CERTIFICATE_PARAMS]
  34. @pytest.fixture(scope='session')
  35. def ca(tmpdir_factory):
  36. ca_dir = tmpdir_factory.mktemp('ca')
  37. key = crypto.PKey()
  38. key.generate_key(crypto.TYPE_RSA, 2048)
  39. cert = crypto.X509()
  40. cert.set_version(3)
  41. cert.set_serial_number(1)
  42. cert.get_subject().commonName = 'test-signer'
  43. cert.gmtime_adj_notBefore(0)
  44. cert.gmtime_adj_notAfter(24 * 60 * 60)
  45. cert.set_issuer(cert.get_subject())
  46. cert.set_pubkey(key)
  47. cert.add_extensions([
  48. crypto.X509Extension(b'basicConstraints', True, b'CA:TRUE, pathlen:0'),
  49. crypto.X509Extension(b'keyUsage', True,
  50. b'digitalSignature, keyEncipherment, keyCertSign, cRLSign'),
  51. crypto.X509Extension(b'subjectKeyIdentifier', False, b'hash', subject=cert)
  52. ])
  53. cert.add_extensions([
  54. crypto.X509Extension(b'authorityKeyIdentifier', False, b'keyid:always', issuer=cert)
  55. ])
  56. cert.sign(key, 'sha256')
  57. return {
  58. 'dir': ca_dir,
  59. 'key': key,
  60. 'cert': cert,
  61. }
  62. @pytest.fixture(scope='session',
  63. ids=VALID_CERTIFICATE_IDS,
  64. params=VALID_CERTIFICATE_PARAMS)
  65. def valid_cert(request, ca):
  66. common_name = request.param['cn']
  67. key = crypto.PKey()
  68. key.generate_key(crypto.TYPE_RSA, 2048)
  69. cert = crypto.X509()
  70. cert.set_serial_number(request.param['serial'])
  71. cert.gmtime_adj_notBefore(0)
  72. cert.gmtime_adj_notAfter(24 * 60 * 60)
  73. cert.set_issuer(ca['cert'].get_subject())
  74. cert.set_pubkey(key)
  75. cert.set_version(3)
  76. cert.get_subject().commonName = common_name
  77. cert.add_extensions([
  78. crypto.X509Extension(b'basicConstraints', True, b'CA:FALSE'),
  79. crypto.X509Extension(b'keyUsage', True, b'digitalSignature, keyEncipherment'),
  80. crypto.X509Extension(b'extendedKeyUsage', False, request.param['uses']),
  81. ])
  82. if request.param['dns'] or request.param['ip']:
  83. san_list = ['DNS:{}'.format(common_name)]
  84. san_list.extend(['DNS:{}'.format(x) for x in request.param['dns']])
  85. san_list.extend(['IP:{}'.format(x) for x in request.param['ip']])
  86. cert.add_extensions([
  87. crypto.X509Extension(b'subjectAltName', False, ', '.join(san_list).encode('utf8'))
  88. ])
  89. cert.sign(ca['key'], 'sha256')
  90. cert_contents = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
  91. cert_file = ca['dir'].join('{}.crt'.format(common_name))
  92. cert_file.write_binary(cert_contents)
  93. return {
  94. 'common_name': common_name,
  95. 'serial': request.param['serial'],
  96. 'dns': request.param['dns'],
  97. 'ip': request.param['ip'],
  98. 'uses': request.param['uses'],
  99. 'cert_file': cert_file,
  100. 'cert': cert
  101. }