Beispiel #1
0
    def create_certificate(self):
        """ Create Node certificate from Cluster CA authority

        """
        if self.certificate is None:
            # Get PKI next serial number
            cluster = Cluster.objects.get()
            serial = cluster.ca_serial
            serial += 1

            crt, key = ssl_utils.mk_signed_cert(ssl_utils.get_ca_cert_path(),
                                                ssl_utils.get_ca_key_path(),
                                                self.name, 'FR', '', '', '',
                                                '', serial)

            # TODO: Error handling
            # Save serial number
            cluster.ca_serial = serial
            cluster.save()

            # Store the certificate
            certificate = SSLCertificate()
            certificate.name = str(crt.get_subject())
            certificate.cn = str(self.name)
            certificate.o = 'FR'
            certificate.cert = crt.as_pem().decode('utf8')
            certificate.key = key.as_pem(cipher=None).decode('utf8')
            certificate.status = 'V'
            certificate.issuer = str(crt.get_issuer())
            certificate.validfrom = str(crt.get_not_before().get_datetime())
            certificate.validtill = str(crt.get_not_after().get_datetime())
            certificate.serial = str(serial)
            certificate.is_ca = False

            internal = cluster.ca_certificate
            certificate.chain = str(internal.cert)

            certificate.save()
            self.certificate = certificate
            self.save()
def import_certificate(conn):
    """
    Import all SSL certificates
    :param: ssl_conf_id: ssl certificate id
    :param: ssl_conf_cert: ssl cert chain
    :param: ssl_conf_key: ssl key chain
    :param: ssl_conf_ca: ssl ca chain
    :param: ssl_conf_ssl_protocol: ssl protocols supported
    :param: ssl_conf_ssl_cipher_suite: ssl ciphers suite
    :return modssl_dict: dict to link sslprofile id in sqlite to object created in mongodb
    """
    logger.info("Importing SSL profiles and certificates")
    ssl_conf = conn.cursor()
    ssl_conf.execute("SELECT * FROM ssl_conf")
    ssl_conf_sql = ssl_conf.fetchall()

    app = conn.cursor()
    app.execute("SELECT * FROM app")
    application_sql = app.fetchall()

    # Retrieve index in database of each name fields of "app" table
    col_name_list_app = [tuple[0] for tuple in app.description]
    ssl_configuration_id = col_name_list_app.index("ssl_configuration_id")
    auth_id = col_name_list_app.index("auth_id")

    # Retrieve index in database of each name fields of ""ssl_conf" table
    col_name_list_ssl_conf = [tuple[0] for tuple in ssl_conf.description]
    ssl_conf_id = col_name_list_ssl_conf.index("id")
    ssl_conf_cert = col_name_list_ssl_conf.index("cert")
    ssl_conf_key = col_name_list_ssl_conf.index("key")
    ssl_conf_ca = col_name_list_ssl_conf.index("ca")
    ssl_conf_ssl_protocol = col_name_list_ssl_conf.index("ssl_protocol")
    ssl_conf_ssl_cipher_suite = col_name_list_ssl_conf.index("ssl_cipher_suite")

    modssl_dict = dict()
    used_ssl_list = list()

    # Avoid unused ssl_profile
    for app in application_sql:
        used_ssl_list.append(app[ssl_configuration_id])

    for i in ssl_conf_sql:
        # if ssl_profile id is in list of used ssl profile by application, we import it
        if i[ssl_conf_id] in used_ssl_list and i[ssl_conf_cert]:
            # then we create and populate the ssl profile
            verify_client = "none"
            modssl = ModSSL()
            modssl.name = "SSL_profile_" + str(i[ssl_conf_id])
            if "+SSLv3" in i[ssl_conf_ssl_protocol]:
                modssl.protocols = "+SSLv3"
            if "+TLSv1" in i[ssl_conf_ssl_protocol]:
                modssl.protocols = "+TLSv1"
            if "+TLSv1.1" in i[ssl_conf_ssl_protocol]:
                modssl.protocols = "+TLSv1.1"
            if "+TLSv1.2" in i[ssl_conf_ssl_protocol]:
                modssl.protocols = "+TLSv1.2"
            modssl.ciphers = i[ssl_conf_ssl_cipher_suite]
            modssl.engine = "builtin"
            # if auth method is SSL or SSL|Kerberos, verify client certificate
            for app in application_sql:
                if app[auth_id] == "6" or app[auth_id] == "5":
                    verify_client = "require"

            modssl.verifyclient = verify_client
            modssl.engine = "builtin"

            # then we create the linked certificate of this ssl profile
            cert = SSLCertificate()
            cert.cert = ""
            cert.key = ""
            cert.chain = ""
            certificate = ""

            # remove \r in string cert, key, ca
            for j in i[ssl_conf_cert].split("\r"):
                certificate = certificate + j

            cert.cert = str(i[ssl_conf_cert])
            cert.key = str(i[ssl_conf_key])
            cert.chain = str(i[ssl_conf_ca])
            x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert.cert)

            # retrieve each fields of subject if it exists
            for j in x509.get_subject().get_components():
                if j[0] == "CN":
                    cert.cn = j[1]
                elif j[0] == "C":
                    cert.c = j[1]
                elif j[0] == "ST":
                    cert.st = j[1]
                elif j[0] == "L":
                    cert.l = j[1]
                elif j[0] == "O":
                    cert.o = j[1]
                elif j[0] == "OU":
                    cert.ou = j[1]

            # retrieve issuer informations
            cert.issuer = str(x509.get_issuer()).split("<X509Name object '")[1].split("'>")[0]
            # parse date format
            cert.validfrom = str(x509.get_notBefore())[0:4]+"-"+str(x509.get_notBefore())[4:6]\
                             +"-"+str(x509.get_notBefore())[6:8]+" "+str(x509.get_notBefore())[8:10]\
                             +":"+str(x509.get_notBefore())[10:12]+":"+str(x509.get_notBefore())[12:14]
            cert.validtill = str(x509.get_notAfter())[0:4]+"-"+str(x509.get_notAfter())[4:6]\
                             +"-"+str(x509.get_notAfter())[6:8]+" "+str(x509.get_notAfter())[8:10]\
                             +":"+str(x509.get_notAfter())[10:12]+":"+str(x509.get_notAfter())[12:14]

            # name is issuer
            cert.name = str(x509.get_subject()).split("<X509Name object '")[1].split("'>")[0]
            cert.save()
            modssl.certificate = cert
            modssl.save()
            modssl_dict[i[ssl_conf_id]] = modssl
    logger.info("End of SSL profiles and certificates importing process")
    return modssl_dict
Beispiel #3
0
def load_ca(request):
    """ method dedicated to certificate importation
    :param request: Django POST request object
    :param POST['cert']: The PEM X509 trusted CA
    """
    # Used to api_request the write of the new certificates
    cluster = Cluster.objects.get()

    cert = SSLCertificate()
    str_cert_list = ""

    if request.method == 'POST':
        dataPosted = request.POST

        users_cn = ""
        error = dict()
        err = None
        try:
            str_cert_list = str(dataPosted['cert'])
        except:
            err = True
            error['cert'] = "X509 PEM trusted CA required"
            pass

        try:
            users_cn = str(dataPosted['cn'])
        except:
            pass

        if err:
            return render_to_response('cert_import_ca.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # If the user provide CN, split them
        users_cn = users_cn.replace(' ', '')
        users_cn_list = filter(lambda x: x, users_cn.split(";"))

        # Create a list with the certificates the user imported
        cert_list = filter(lambda x: x,
                           str_cert_list.split("-----BEGIN CERTIFICATE-----"))

        # Create the CAs in Mongo
        ca_count = 0
        for cer_pem, users_cn in zip_longest(cert_list, users_cn_list):
            if not cer_pem:
                break
            if "-----BEGIN CERTIFICATE-----" not in cer_pem:
                cer_pem = "-----BEGIN CERTIFICATE-----" + cer_pem

            cert = SSLCertificate()
            cert.cert = cer_pem
            cert.key = ""
            cert.chain = ""
            cert.is_trusted_ca = True

            # Check the certificate
            try:
                x509Cert = X509.load_cert_string(cert.cert)
            except:
                error['cert'] = "Invalid X509 PEM trusted CA: " + str(
                    ca_count) + " CA saved"
                return render_to_response(
                    'cert_import_ca.html', {
                        'cert': cert,
                        'error': error
                    },
                    context_instance=RequestContext(request))

            # Store certificate details
            cert.name = str(x509Cert.get_subject())
            cert.status = 'V'
            cert.issuer = str(x509Cert.get_issuer())
            try:
                cert.validfrom = str(x509Cert.get_not_before().get_datetime())
            except Exception as e:
                logger.error(
                    "Exception while retrieving validation date 'before' of certificates : "
                )
                logger.exception(e)
            try:
                cert.validtill = str(x509Cert.get_not_after().get_datetime())
            except Exception as e:
                logger.error(
                    "Exception while retrieving validation date 'after' dates of certificates : "
                )
                logger.exception(e)

            # Find certificate fields
            fields = cert.name.split('/')
            for field in fields:
                tmp = field.split('=')
                if str(tmp[0]) == "CN":
                    cert.cn = tmp[1]
                elif str(tmp[0]) == "C":
                    cert.c = tmp[1]
                elif str(tmp[0]) == "ST":
                    cert.st = tmp[1]
                elif str(tmp[0]) == "L":
                    cert.l = tmp[1]
                elif str(tmp[0]) == "O":
                    cert.o = tmp[1]
                elif str(tmp[0]) == "OU":
                    cert.ou = tmp[1]

            # If the CA doesn't provide a CN, use the user's one
            if not cert.cn and not users_cn:
                error['cn'] = "No CN provided by the user or the CA: " + str(
                    ca_count) + " CA saved"
                return render_to_response(
                    'cert_import_ca.html', {
                        'cert': cert,
                        'error': error
                    },
                    context_instance=RequestContext(request))
            elif not cert.cn:
                cert.cn = users_cn

            # Save the CA in Mongo
            cert.save()

            # Write the certificate on disk on all nodes
            response = cluster.api_request(
                "/api/certs/write_ca/{}".format(str(cert.id)),
                {'certificate': cert.cert})
            for node_name in response.keys():
                if response[node_name].get('status') != 1:
                    logger.error(response[node_name].get('error'))

            # Add the saved CA to the count
            ca_count += 1

        os.system("/usr/local/bin/c_rehash /home/vlt-sys/Engine/conf/certs")

        return HttpResponseRedirect('/system/cert/')

    return render_to_response('cert_import_ca.html', {
        'cert': cert,
    },
                              context_instance=RequestContext(request))
Beispiel #4
0
def sign(request):
    """ method dedicated to sign an external certificate request
    :param request: Django POST request object
    :param POST['csr']: The PEM certificate request
    """
    cert = SSLCertificate()
    cert.cert = ""
    cert.key = ""
    cert.chain = ""
    cert.csr = ""

    if request.method == 'POST':
        dataPosted = request.POST

        error = dict()
        err = None
        try:
            cert.csr = str(dataPosted['csr'])
        except:
            err = True
            error['csr'] = "PEM Certificate request required"
            pass

        if err:
            return render_to_response('cert_sign.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # Check the request
        try:
            x509Request = X509.load_request_string(cert.csr)
        except:
            error['csr'] = "Invalid PEM Certificate Request"
            return render_to_response('cert_sign.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # Get cluster
        cluster = Cluster.objects.get()

        # Find the internal CA's certificate and private key
        internal = cluster.ca_certificate
        ca_key = RSA.load_key_string(internal.key.encode('utf8'))
        ca_cert = X509.load_cert_string(internal.cert.encode('utf8'))

        # Get PKI next serial number
        serial = cluster.ca_serial
        serial += 1

        # Create a certificate from the request
        crt = mk_cert(serial)
        crt.set_pubkey(x509Request.get_pubkey())

        pk = EVP.PKey()
        pk.assign_rsa(ca_key)

        issuer = X509.X509_Name()
        subject = X509.X509_Name()

        fields = str(x509Request.get_subject()).split('/')
        for field in fields:
            tmp = field.split('=')
            if str(tmp[0]) == "CN":
                subject.CN = tmp[1]
                cert.cn = tmp[1]
            elif str(tmp[0]) == "C":
                subject.C = tmp[1]
                cert.c = tmp[1]
            elif str(tmp[0]) == "ST":
                subject.ST = tmp[1]
                cert.st = tmp[1]
            elif str(tmp[0]) == "L":
                subject.L = tmp[1]
                cert.l = tmp[1]
            elif str(tmp[0]) == "O":
                subject.O = tmp[1]
                cert.o = tmp[1]
            elif str(tmp[0]) == "OU":
                subject.OU = tmp[1]
                cert.ou = tmp[1]

        fields = str(ca_cert.get_subject()).split('/')
        for field in fields:
            tmp = field.split('=')
            if str(tmp[0]) == "CN":
                issuer.CN = tmp[1]
            elif str(tmp[0]) == "C":
                issuer.C = tmp[1]
            elif str(tmp[0]) == "ST":
                issuer.ST = tmp[1]
            elif str(tmp[0]) == "L":
                issuer.L = tmp[1]
            elif str(tmp[0]) == "O":
                issuer.O = tmp[1]
            elif str(tmp[0]) == "OU":
                issuer.OU = tmp[1]

        crt.set_subject(subject)
        crt.set_issuer(issuer)

        crt.add_ext(X509.new_extension('basicConstraints', 'CA:FALSE'))
        crt.add_ext(
            X509.new_extension('subjectKeyIdentifier',
                               str(crt.get_fingerprint())))

        try:
            crt.sign(pk, 'sha256')
        except Exception as e:
            print(e)

        # Save serial number
        cluster.ca_serial = serial
        cluster.save()

        # Store the certificate
        cert.cert = crt.as_pem().decode('utf8')
        cert.name = str(crt.get_subject())
        cert.status = 'V'
        cert.issuer = str(internal.issuer)
        cert.validfrom = str(crt.get_not_before().get_datetime())
        cert.validtill = str(crt.get_not_after().get_datetime())
        cert.is_ca = False
        cert.chain = str(internal.cert)
        cert.serial = str(serial)
        cert.save()

        return HttpResponseRedirect('/system/cert/')

    return render_to_response('cert_sign.html', {
        'cert': cert,
    },
                              context_instance=RequestContext(request))
Beispiel #5
0
def load(request):
    """ method dedicated to certificate importation
    :param request: Django POST request object
    :param POST['cert']: The PEM X509 certificate
    :param POST['key']: The PEM X509 key
    :param POST['chain']: The PEM X509 certificate chain
    """
    cert = SSLCertificate()
    cert.cert = ""
    cert.key = ""
    cert.chain = ""
    if request.method == 'POST':
        dataPosted = request.POST

        error = dict()
        err = None
        try:
            cert_cert = dataPosted['cert']
        except:
            err = True
            error['cert'] = "X509 PEM Certificate required"
            pass

        try:
            cert_key = dataPosted['key']
        except:
            err = True
            error['key'] = "X509 PEM Key required"
            pass

        try:
            cert.chain = str(dataPosted['chain'])
        except:
            pass

        if err:
            return render_to_response('cert_import.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # Check the certificate
        try:
            x509Cert = X509.load_cert_string(bytes(cert_cert, 'utf8'))
            cert.cert = str(cert_cert)
        except:
            error['cert'] = "Invalid X509 PEM Certificate"
            return render_to_response('cert_import.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        global keypass
        try:
            keypass = str(dataPosted['keypass'])
        except:
            pass

        # Check the private key
        try:
            bio = BIO.MemoryBuffer(bytes(cert_key, 'utf8'))
            RSA.load_key_bio(bio, callback=read_pass_from_POST)
            cert.key = str(cert_key)
        except RSA.RSAError:
            try:
                bio = BIO.MemoryBuffer(bytes(cert_key, 'utf8'))
                EC.load_key_bio(bio, callback=read_pass_from_POST)
                cert.key = str(cert_key)
            except RSA.RSAError:
                error['keypass'] = "******"
            except Exception as e:
                logger.exception(e)
                error['key'] = "Invalid PEM KEY"
        except Exception as e:
            logger.exception(e)
            error['key'] = "Invalid PEM KEY"

        if error:
            return render_to_response('cert_import.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # Store certificate details
        cert.name = str(x509Cert.get_subject())
        cert.status = 'V'
        cert.issuer = str(x509Cert.get_issuer())
        try:
            cert.validfrom = str(x509Cert.get_not_before().get_datetime())
        except Exception as e:
            logger.error(
                "Exception while retrieving validation date 'before' of certificates : "
            )
            logger.exception(e)

        try:
            cert.validtill = str(x509Cert.get_not_after().get_datetime())
        except Exception as e:
            logger.error(
                "Exception while retrieving validation date 'after' of certificates : "
            )
            logger.exception(e)

        if x509Cert.check_ca():
            cert.is_ca = True
        else:
            cert.is_ca = False

        # Find certificate fields
        fields = cert.name.split('/')
        for field in fields:
            tmp = field.split('=')
            if str(tmp[0]) == "CN":
                cert.cn = tmp[1]
            elif str(tmp[0]) == "C":
                cert.c = tmp[1]
            elif str(tmp[0]) == "ST":
                cert.st = tmp[1]
            elif str(tmp[0]) == "L":
                cert.l = tmp[1]
            elif str(tmp[0]) == "O":
                cert.o = tmp[1]
            elif str(tmp[0]) == "OU":
                cert.ou = tmp[1]

        # if cert.cn is empty check if subjectAltName is set en use it
        if (not cert.cn):
            alt_name = x509Cert.get_ext('subjectAltName').get_value()
            if (alt_name):
                cert.cn = alt_name

        cert.save()

        return HttpResponseRedirect('/system/cert/')

    return render_to_response('cert_import.html', {
        'cert': cert,
    },
                              context_instance=RequestContext(request))