def _create_ssl_pem_and_cert(self, path, reg): """Create ssl.pem and ssl.cert files for suite in path.""" try: from OpenSSL import crypto except ImportError: # OpenSSL not installed, so we can't use HTTPS anyway. return host = get_hostname() altnames = [ "DNS:*", "DNS:%s" % host, "IP:%s" % get_local_ip_address(host), # See https://github.com/kennethreitz/requests/issues/2621 "DNS:%s" % get_local_ip_address(host)] # Use suite name as the 'common name', but no more than 64 chars. cert_common_name = reg if len(reg) > 64: cert_common_name = reg[:61] + "..." # Create a private key. pkey_obj = crypto.PKey() pkey_obj.generate_key(crypto.TYPE_RSA, 2048) self._dump_item( path, self.FILE_BASE_SSL_PEM, crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey_obj)) # Create a self-signed certificate. cert_obj = crypto.X509() cert_obj.get_subject().O = "Cylc" cert_obj.get_subject().CN = cert_common_name cert_obj.gmtime_adj_notBefore(0) cert_obj.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) # 10 years. cert_obj.set_issuer(cert_obj.get_subject()) cert_obj.set_pubkey(pkey_obj) cert_obj.add_extensions([crypto.X509Extension( "subjectAltName", False, ", ".join(altnames))]) cert_obj.sign(pkey_obj, 'sha256') self._dump_item( path, self.FILE_BASE_SSL_CERT, crypto.dump_certificate(crypto.FILETYPE_PEM, cert_obj))
def _get_ssl_cert(self, path, pkey_obj): """Load or create ssl.cert file for suite in path. Self-signed SSL certificate file. """ try: from OpenSSL import crypto except ImportError: # OpenSSL not installed, so we can't use HTTPS anyway. return # Use suite host as the 'common name', but no more than 64 chars. host = get_suite_host() common_name = host if len(common_name) > 64: common_name = common_name[:61] + "..." # See https://github.com/kennethreitz/requests/issues/2621 ext = crypto.X509Extension( "subjectAltName", False, "DNS:*, DNS:%(dns)s, IP:%(ip)s, DNS:%(ip)s" % { "dns": host, "ip": get_local_ip_address(host)}) file_name = self._locate_item(self.FILE_BASE_SSL_CERT, path) if file_name: cert_obj = crypto.load_certificate( crypto.FILETYPE_PEM, open(file_name).read()) try: prev_ext = cert_obj.get_extension(0) except (AttributeError, IndexError): pass else: if (cert_obj.get_subject().CN == common_name and not cert_obj.has_expired() and str(prev_ext) == str(ext)): return # certificate good for the same suite and host # Generate a new certificate cert_obj = crypto.X509() cert_obj.get_subject().O = "Cylc" cert_obj.get_subject().CN = common_name cert_obj.gmtime_adj_notBefore(0) cert_obj.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) # 10 years. cert_obj.set_issuer(cert_obj.get_subject()) cert_obj.set_pubkey(pkey_obj) cert_obj.set_serial_number(1) cert_obj.add_extensions([ext]) cert_obj.sign(pkey_obj, 'sha256') self._dump_item( path, self.FILE_BASE_SSL_CERT, crypto.dump_certificate(crypto.FILETYPE_PEM, cert_obj))
def _get_ssl_cert(self, path, pkey_obj): """Load or create ssl.cert file for suite in path. Self-signed SSL certificate file. """ try: from OpenSSL import crypto except ImportError: # OpenSSL not installed, so we can't use HTTPS anyway. return # Use suite host as the 'common name', but no more than 64 chars. host = get_suite_host() common_name = host if len(common_name) > 64: common_name = common_name[:61] + "..." # See https://github.com/kennethreitz/requests/issues/2621 ext = crypto.X509Extension( "subjectAltName", False, "DNS:*, DNS:%(dns)s, IP:%(ip)s, DNS:%(ip)s" % { "dns": host, "ip": get_local_ip_address(host)}) file_name = self._locate_item(self.FILE_BASE_SSL_CERT, path) if file_name: cert_obj = crypto.load_certificate( crypto.FILETYPE_PEM, open(file_name).read()) try: prev_ext = cert_obj.get_extension(0) except (AttributeError, IndexError): pass else: if (cert_obj.get_subject().CN == common_name and not cert_obj.has_expired() and str(prev_ext) == str(ext)): return # certificate good for the same suite and host # Generate a new certificate cert_obj = crypto.X509() cert_obj.get_subject().O = "Cylc" cert_obj.get_subject().CN = common_name cert_obj.gmtime_adj_notBefore(0) cert_obj.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) # 10 years. cert_obj.set_issuer(cert_obj.get_subject()) cert_obj.set_pubkey(pkey_obj) cert_obj.add_extensions([ext]) cert_obj.sign(pkey_obj, 'sha256') self._dump_item( path, self.FILE_BASE_SSL_CERT, crypto.dump_certificate(crypto.FILETYPE_PEM, cert_obj))
def _dump_certificate_and_key_to_dir(self, path, suite): """Dump SSL certificate to "ssl.cert" file in "path".""" try: from OpenSSL import crypto except ImportError: # OpenSSL not installed, so we can't use HTTPS anyway. return host = get_hostname() altnames = ["DNS:*", "DNS:%s" % host, "IP:%s" % get_local_ip_address(host)] # Workaround for https://github.com/kennethreitz/requests/issues/2621 altnames.append("DNS:%s" % get_local_ip_address(host)) # Use suite name as the 'common name', but no more than 64 chars. cert_common_name = suite if len(suite) > 64: cert_common_name = suite[:61] + "..." # Create a private key. pkey_obj = crypto.PKey() pkey_obj.generate_key(crypto.TYPE_RSA, 2048) # Create a self-signed certificate. cert_obj = crypto.X509() cert_obj.get_subject().O = "Cylc" cert_obj.get_subject().CN = cert_common_name cert_obj.gmtime_adj_notBefore(0) cert_obj.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) # 10 years. cert_obj.set_issuer(cert_obj.get_subject()) cert_obj.set_pubkey(pkey_obj) cert_obj.add_extensions([ crypto.X509Extension( "subjectAltName", False, ", ".join(altnames) ) ]) cert_obj.sign(pkey_obj, 'sha256') mkdir_p(path) # Work in a user-read-write-only directory for guaranteed safety. from tempfile import mkdtemp work_dir = mkdtemp() pkey_file = os.path.join(work_dir, self.SSL_PRIVATE_KEY_FILE_BASE) cert_file = os.path.join(work_dir, self.SSL_CERTIFICATE_FILE_BASE) with open(pkey_file, "w") as file_handle: file_handle.write( crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey_obj)) with open(cert_file, "w") as file_handle: file_handle.write( crypto.dump_certificate(crypto.FILETYPE_PEM, cert_obj)) import stat os.chmod(pkey_file, stat.S_IRUSR) os.chmod(cert_file, stat.S_IRUSR) pkey_dest_file = os.path.join(path, self.SSL_PRIVATE_KEY_FILE_BASE) cert_dest_file = os.path.join(path, self.SSL_CERTIFICATE_FILE_BASE) import shutil shutil.copy(pkey_file, pkey_dest_file) shutil.copy(cert_file, cert_dest_file) shutil.rmtree(work_dir) if cylc.flags.verbose: print 'Generated suite SSL certificate: %s' % cert_dest_file print 'Generated suite SSL private key: %s' % pkey_dest_file