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
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))
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))
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))