예제 #1
0
    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))
예제 #2
0
    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))
예제 #3
0
    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))
예제 #4
0
    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