Easy CA management
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
4.1 KiB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from playhouse.gfk import *
  4. import os
  5. from inspect import getsourcefile
  6. import subprocess
  7. from models.authority import Authority
  8. from models.certificate import Certificate
  9. from models.request import SignRequest
  10. from paths import *
  11. import json
  12. class HostSSLRequest(SignRequest):
  13. def __init__(self, req_id, host_name, key_data):
  14. super(HostSSLRequest, self).__init__(req_id)
  15. self.host_name = host_name
  16. self.key_data = key_data
  17. @property
  18. def name(self):
  19. return "Hostname: %s" % self.host_name
  20. @property
  21. def fields(self):
  22. return [
  23. ("Hostname", self.host_name)
  24. ]
  25. @property
  26. def receiver(self):
  27. return self.host_name
  28. class CASSLRequest(SignRequest):
  29. def __init__(self, req_id, ca_name, key_data):
  30. super(CASSLRequest, self).__init__(req_id)
  31. self.ca_name = ca_name
  32. self.key_data = key_data
  33. @property
  34. def name(self):
  35. return "CA name: %s" % self.ca_name
  36. @property
  37. def fields(self):
  38. return [
  39. ("CA name", self.ca_name)
  40. ]
  41. @property
  42. def receiver(self):
  43. return self.ca_name
  44. class SSLAuthority(Authority):
  45. request_allowed = [ HostSSLRequest, CASSLRequest, ]
  46. ca_key_algorithm = 'des3'
  47. key_length = '4096'
  48. key_algorithm = 'sha256'
  49. root_ca_validity = '3650'
  50. ca_validity = '1825'
  51. cert_validity = '365'
  52. def generate(self):
  53. if os.path.exists(self.path):
  54. raise ValueError("A CA with the same id and type already exists")
  55. confirm = input('Is a root CA? [y/N]> ')
  56. if confirm == 'y':
  57. self.isRoot = True
  58. else:
  59. self.isRoot = False
  60. subprocess.check_output(['openssl',
  61. 'genrsa',
  62. '-%s'%self.ca_key_algorithm,
  63. '-out', '%s'%(self.path),
  64. self.key_length])
  65. print(self.isRoot)
  66. if self.isRoot:
  67. subprocess.check_output(['openssl',
  68. 'req',
  69. '-extensions', 'v3_root_ca',
  70. '-config', os.path.join(os.path.dirname(os.path.abspath(getsourcefile(lambda:0))), '../openssl-config/openssl.cnf'),
  71. '-new',
  72. '-x509',
  73. '-days', self.root_ca_validity,
  74. '-key', self.path,
  75. # '-extensions', 'v3_ca'
  76. '-out', "%s.pub"%self.path,
  77. # '-config', "%s.conf"%self.path
  78. ])
  79. else:
  80. subprocess.check_output(['openssl',
  81. 'req',
  82. '-new',
  83. #'-x509',
  84. # '-days', self.ca_validity,
  85. '-key', self.path,
  86. # '-extensions', 'v3_ca'
  87. '-out', "%s.csr"%self.path,
  88. # '-config', "%s.conf"%self.path
  89. ])
  90. result_dict = {}
  91. result_dict['keyType'] = 'ssl_ca'
  92. result_dict['caName'] = self.ca_id
  93. with open("%s.csr"%self.path, 'r') as f:
  94. result_dict['keyData'] = "".join(f.readlines())
  95. request = { 'type': 'sign_request', 'request': result_dict }
  96. print("Please sign the following request:")
  97. print(json.dumps(request))
  98. with open(self.path + '.serial', 'w') as stream:
  99. stream.write(str(0))
  100. def generate_certificate(self, request):
  101. """
  102. Sign a *SSLRequest with this certification authority
  103. """
  104. pub_key_path = request.destination
  105. cert_path = request.cert_destination
  106. with open(pub_key_path, 'w') as stream:
  107. stream.write(request.key_data)
  108. subprocess.check_output(['openssl',
  109. 'x509',
  110. '-req',
  111. '-days', self.ca_validity,
  112. '-in', pub_key_path,
  113. '-CA', "%s.pub"%self.path,
  114. '-CAkey', self.path,
  115. '-CAcreateserial',
  116. '-out', cert_path,
  117. '-%s'%self.key_algorithm])
  118. return self.ca_validity