Пример #1
0
def cert_list(request):
    """ Page dedicated to show certificate list
    """
    try:
        certs = SSLCertificate.objects(is_trusted_ca__ne=True)
    except DoesNotExist:
        certs = None

    try:
        trusted_ca_list = SSLCertificate.objects(is_trusted_ca=True)
    except DoesNotExist:
        trusted_ca_list = None

    return render_to_response('cert.html', {'certs': certs, 'trusted_ca_list': trusted_ca_list}, context_instance=RequestContext(request))
Пример #2
0
def remove_ca(request, cert_id):
    """ Function called when a Trusted CA certificate is deleted.
     It will erase-it on disk.

    :param request: Django request object
    :param cert_id: String id of certificate to erase
    :return:
    """

    try:
        certificate = SSLCertificate(ObjectId(cert_id))
    except Exception as e:
        logger.error(
            "API::remove_ca: CA Certificate '{}' not found : {}".format(
                cert_id, e))
        return JsonResponse({
            'status':
            0,
            'error':
            "CA Certificate '{}' not found : {}".format(cert_id, str(e))
        })

    # Delete the certificate on disk
    certificate_path = "{}/{}.crt".format(certs_dir, str(cert_id))
    try:
        os_remove(certificate_path)
    except Exception as e:
        logger.error(
            "API::remove_ca: Failed to delete certificate '{}' on disk : {}".
            format(certificate_path, str(e)))

    os_system("/usr/local/bin/c_rehash /home/vlt-sys/Engine/conf/certs")
    logger.info("API::remove_ca: Ca certificate successfully deleted on disk")

    return JsonResponse({'status': 1})
Пример #3
0
def remove_cert(request, cert_id):
    """ Function called when a certificate is deleted.
     It will erase-it on disk.

    :param request: Django request object
    :param cert_id: String id of certificate to erase
    :return:
    """

    try:
        certificate = SSLCertificate(ObjectId(cert_id))
    except Exception as e:
        logger.error(
            "API::delete_cert: SSL Certificate '{}' not found : {}".format(
                cert_id, e))
        return JsonResponse({
            'status':
            0,
            'error':
            "SSL Certificate '{}' not found : {}".format(cert_id, str(e))
        })

    # Delete all the declinaisons of files of that certificate on disk
    if certificate.cert and certificate.key:
        certificate_path = "{}SSLProxyCertificateFile-{}.txt".format(
            settings.CONF_DIR, cert_id)
        try:
            os_remove(certificate_path)
        except Exception as e:
            logger.error(
                "API::remove_cert: Failed to delete file '{}' on disk : {}".
                format(certificate_path, str(e)))

    if certificate.cert:
        certificate_path = "{}SSLCertificateFile-{}.txt".format(
            settings.CONF_DIR, cert_id)
        try:
            os_remove(certificate_path)
        except Exception as e:
            logger.error(
                "API::remove_cert: Failed to delete file '{}' on disk : {}".
                format(certificate_path, str(e)))

    if certificate.key:
        certificate_path = "{}SSLCertificateKeyFile-{}.txt".format(
            settings.CONF_DIR, cert_id)
        try:
            os_remove(certificate_path)
        except Exception as e:
            logger.error(
                "API::remove_cert: Failed to delete file '{}' on disk : {}".
                format(certificate_path, str(e)))

    logger.info(
        "API::remove_cert: SSL certificate successfully deleted on disk")

    return JsonResponse({'status': 1})
Пример #4
0
 def perform_cert_options(self, zabbix_options):
     certificate_files = {
         'chain': "{}/pki/ca_cert.crt".format(self.config_path),
         'cert': "{}/pki/cert.crt".format(self.config_path),
         'key': "{}/pki/cert.key".format(self.config_path),
         'crl': "{}/pki/cert.crl".format(self.config_path)
     }
     # Retrieve SSLCertificate object
     ssl_cert = SSLCertificate.objects(id=zabbix_options.get('tls_cert')).only(*certificate_files.keys()).first()
     for attribute_name in certificate_files.keys():
         self.write_configuration_file(certificate_files[attribute_name], getattr(ssl_cert, attribute_name))
     # If CRL is not present, set the crl empty
     if not ssl_cert.crl:
         certificate_files['crl'] = ""
     # Replace SSLCertificate object by dict for template use
     zabbix_options['tls_cert_file'] = certificate_files
     return zabbix_options
Пример #5
0
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
Пример #6
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()
Пример #7
0
    def __init__(self, *args, **kwargs):
        try:
            self.listeners = kwargs.pop('listeners')
        except KeyError:
            pass

        super(ApplicationForm, self).__init__(*args, **kwargs)

        self = bootstrap_tooltips(self)
        repo_lst = BaseAbstractRepository.get_auth_repositories()
        auth_repo_lst = list()
        for rep in repo_lst:
            auth_repo_lst.append((
                ObjectId(rep.id),
                rep.repo_name,
            ))

        mod_sec_choices = list()
        for rule in ModSecRulesSet.objects(type_rule__nin=('wlbl', )):
            mod_sec_choices.append((ObjectId(rule.id), rule.name))

        dataset_list = list()
        dataset_list.append(((None), "------------------------------"))
        for dataset in Dataset.objects(svm_built=True).only('name', 'id'):
            dataset_list.append((ObjectId(dataset.id), dataset.name))

        client_certificate = [('', '---------')]
        for cert in SSLCertificate.objects(is_trusted_ca__ne=True).only(
                'id', 'cn'):
            client_certificate.append(("%sSSLProxyCertificateFile-%s.txt" %
                                       (settings.CONF_DIR, cert.id), cert.cn))

        COOCKIE_CIPHER = (
            ('rc4', 'RC4 (128 bits)'),
            ('aes128', 'AES 128 (128 bits)'),
            ('aes256', 'AES 256 (256 bits)'),
        )

        IP_REPUTATION = []
        loganalyser_rules = Cluster.objects.get(
        ).system_settings.loganalyser_settings.loganalyser_rules
        for rule in loganalyser_rules:
            tags = rule.tags.split(',')

            for tag in tags:
                IP_REPUTATION.append((tag, tag.capitalize()))

        GEOIP = []
        for tag in [
                "AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG",
                "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB",
                "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BQ", "BA", "BW",
                "BV", "BR", "IO", "BN", "BG", "BF", "BI", "KH", "CM", "CA",
                "CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM",
                "CG", "CD", "CK", "CR", "CI", "HR", "CU", "CW", "CY", "CZ",
                "DK", "DJ", "DM", "DO", "EC", "EG", "SV", "GQ", "ER", "EE",
                "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA",
                "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU",
                "GT", "GG", "GN", "GW", "GY", "HT", "HM", "VA", "HN", "HK",
                "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT",
                "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "KP", "KR", "KW",
                "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU",
                "MO", "MK", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ",
                "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS",
                "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI",
                "NE", "NG", "NU", "NF", "MP", "NO", "OM", "PK", "PW", "PS",
                "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA",
                "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM",
                "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG",
                "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "SS", "ES", "LK",
                "SD", "SR", "SJ", "SZ", "SE", "CH", "SY", "TW", "TJ", "TZ",
                "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC",
                "TV", "UG", "UA", "AE", "GB", "US", "UM", "UY", "UZ", "VU",
                "VE", "VN", "VG", "VI", "WF", "EH", "YE", "ZM", "ZW"
        ]:
            GEOIP.append((tag, tag))

        self.fields['block_reputation'] = MultipleChoiceField(
            required=False,
            choices=set(IP_REPUTATION),
            widget=SelectMultiple(attrs={'class': 'form-control select2'}))
        self.fields['block_geoip'] = MultipleChoiceField(
            required=False,
            choices=set(GEOIP),
            widget=SelectMultiple(attrs={'class': 'form-control select2'}))
        self.fields['allow_geoip'] = MultipleChoiceField(
            required=False,
            choices=set(GEOIP),
            widget=SelectMultiple(attrs={'class': 'form-control select2'}))

        self.fields['template'].queryset = portalTemplate.objects.filter()
        self.fields['auth_backend'] = ChoiceField(
            choices=auth_repo_lst,
            required=False,
            widget=Select(attrs={'class': 'form-control'}))
        self.fields['auth_backend_fallbacks'] = MultipleChoiceField(
            choices=auth_repo_lst,
            required=False,
            widget=SelectMultiple(attrs={'class': 'form-control select2'}))
        self.fields['redirect_uri'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 80,
                'rows': 1,
                'class': 'form-control'
            }))
        self.fields['sso_capture_content'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 80,
                'rows': 2,
                'class': 'form-control'
            }))
        self.fields['sso_replace_pattern'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 40,
                'rows': 2,
                'class': 'form-control'
            }))
        self.fields['sso_replace_content'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 40,
                'rows': 2,
                'class': 'form-control'
            }))
        self.fields['sso_after_post_request'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 80,
                'rows': 2,
                'class': 'form-control'
            }))
        self.fields['rules_set'] = MultipleChoiceField(
            choices=mod_sec_choices,
            required=False,
            widget=SelectMultiple(attrs={'class': 'form-control'}))
        self.fields['datasets'] = ChoiceField(
            choices=dataset_list,
            required=False,
            widget=Select(attrs={'class': 'form-control'}))
        self.fields['ssl_protocol'] = ChoiceField(
            choices=SSL_PROTOCOLS,
            required=False,
            widget=Select(attrs={'class': 'form-control'}))
        self.fields['ssl_client_certificate'] = ChoiceField(
            choices=client_certificate,
            required=False,
            widget=Select(attrs={'class': 'form-control'}))

        self.fields['custom_vhost'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 80,
                'rows': 15,
                'class': 'form-control'
            }))
        self.fields['custom_location'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 80,
                'rows': 15,
                'class': 'form-control'
            }))
        self.fields['custom_proxy'] = CharField(
            required=False,
            widget=Textarea(attrs={
                'cols': 80,
                'rows': 15,
                'class': 'form-control'
            }))

        self.fields['cookie_cipher'] = ChoiceField(
            choices=COOCKIE_CIPHER,
            required=False,
            widget=Select(attrs={'class': 'form-control'}))

        if self.initial.get("auth_backend"):
            repo = BaseAbstractRepository.search_repository(
                self.initial.get('auth_backend'))
            if isinstance(repo, LDAPRepository):
                try:
                    groups = [(x, x)
                              for x in repo.get_backend().enumerate_groups()]
                except:
                    groups = []
                finally:
                    self.fields['group_registration'] = ChoiceField(
                        choices=groups,
                        required=False,
                        widget=Select(attrs={'class': 'form-control'}))
import os
import sys

sys.path.append('/home/vlt-gui/vulture')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'vulture.settings')

import django
django.setup()

from gui.models.ssl_certificate import SSLCertificate
from M2Crypto import X509
import subprocess

if __name__ == '__main__':

    for cert in SSLCertificate.objects(issuer="LET'S ENCRYPT", status__ne="R"):

        print "Updating certificate {}".format(cert.cn)
        # Call acme-client to generate the Let's Encrypt challenge
        proc = subprocess.Popen(
            [
                '/usr/local/sbin/acme.sh', '--issue', '-d', cert.cn,
                '--webroot', '/home/vlt-sys/Engine/conf', '--cert-home',
                '/usr/local/etc/ssl/acme'
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env={
                'PATH':
                "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
            })
Пример #9
0
def write_ca(request, cert_id):
    """ Function called when a new Trusted CA certificate is imported.
     It will write-it on disk.

    :param request: Django request object
    :param cert_id: String id of certificate to write on disk
    :return:
    """

    try:
        certificate = SSLCertificate(ObjectId(cert_id))
    except Exception as e:
        logger.error(
            "API::write_ca: CA Certificate '{}' not found : {}".format(
                cert_id, e))
        return JsonResponse({
            'status':
            0,
            'error':
            "CA Certificate '{}' not found : {}".format(cert_id, str(e))
        })

    try:
        cert_content = json_loads(request.body)['certificate']
    except Exception as e:
        logger.error(
            "API::write_ca: CA certificate content not found in api request : {}"
            .format(str(e)))
        return JsonResponse({
            'status':
            0,
            'error':
            "CA certificate content null : {}".format(str(e))
        })

    # Write the certificate on disk
    certificate_path = "{}/{}.crt".format(certs_dir, str(cert_id))
    try:
        with open(certificate_path, "w") as certificate_fd:
            certificate_fd.write(str(cert_content))
    except Exception as e:
        logger.error(
            "API::write_ca: Cannot write CA certificate '{}' on disk : {}".
            format(certificate_path, e))
        return JsonResponse({
            'status':
            0,
            'error':
            "Cannot write CA certificate '{}' on disk : {}".format(
                certificate_path, str(e))
        })

    # Set permissions
    try:
        os_chmod(certificate_path, 664)
        os_system("/usr/bin/chgrp vlt-web {}".format(certificate_path))
    except Exception as e:
        logger.error(
            "API::write_ca: Failed to set permissions on '{}' file : {}".
            format(certificate_path, str(e)))

    os_system("/usr/local/bin/c_rehash /home/vlt-sys/Engine/conf/certs")
    logger.info("API::write_ca: Ca certificate successfully written on disk")

    return JsonResponse({'status': 1})
Пример #10
0
    def conf_has_changed(self, parameters, service_settings=None, conf_django=None):
        """ Test if configuration into system configuration file is same that
        configuration in database (from parameters var)

        :param parameters: A dict containing configuration parameters
        :param service_settings: A dict containing configuration parameters, sent to tempale.render as 'conf_service'
        :param conf_django: A dict containing configuration parameters, sent to template.render as 'conf_django'
        """
        # Modify parameters according to tls/psk options
        if parameters.get('tls_accept') == 'cert' or parameters.get('tls_connect') == 'cert':
            certificate_files = {
                'chain': "{}/pki/ca_cert.crt".format(self.config_path),
                'cert': "{}/pki/cert.crt".format(self.config_path),
                'key': "{}/pki/cert.key".format(self.config_path),
                'crl': "{}/pki/cert.crl".format(self.config_path)
            }
            ssl_cert = SSLCertificate.objects(id=parameters.get('tls_cert')).only(*certificate_files.keys()).first()
            if not ssl_cert.crl:
                certificate_files['crl'] = ""
            parameters['tls_cert_file'] = certificate_files

        if parameters.get('tls_accept') == 'psk' or parameters.get('tls_connect') == 'psk':
            parameters['psk_file'] = "{}/pki/psk.key".format(self.config_path)

        global_conf_has_changed = super(ZABBIX, self).conf_has_changed(parameters, service_settings, conf_django)

        if global_conf_has_changed.startswith("Unable to check if conf has changed"):
            raise ServiceConfigError(global_conf_has_changed)

        # If the configuration file hasn't changed, check if certificate/psk files has changed
        if not global_conf_has_changed:
            if parameters.get('tls_accept') == 'cert' or parameters.get('tls_connect') == 'cert':
                for attribute_name, filename in certificate_files.items():
                    if not filename:
                        continue
                    try:
                        with open(filename, 'r') as fd:
                            orig_conf = fd.read()
                            if orig_conf != getattr(ssl_cert, attribute_name):
                                logger.info("[ZABBIX] Configuration file '{}' differs on disk".format(filename))
                                return True
                    except Exception as e:
                        # FIXME : raise Exception to say the admin "Hey, cannot read conf!" in the GUI ?
                        logger.error("[ZABBIX] Cannot check configuration on '{}' file: ".format(filename))
                        logger.exception(e)
                        # We can't read the file, but it may have been modified
                        return True

            if parameters.get('tls_accept') == 'psk' or parameters.get('tls_connect') == 'psk':
                psk_key_path = "{}/pki/psk.key".format(self.config_path)
                try:
                    with open(psk_key_path, 'r') as fd:
                        orig_conf = fd.read()
                    if orig_conf != parameters.get('psk_key'):
                        logger.info("[ZABBIX] Configuration file '{}' differs on disk".format(psk_key_path))
                        return True
                except Exception as e:
                    logger.error("[ZABBIX] Cannot check configuration on '{}' file: ".format(psk_key_path))
                    logger.exception(e)
                    # We can't read the file, but it may have been modified
                    return True
            # If none of the files has changed: return False
            return False

        # If the configuration file has changed, return True
        logger.info("[ZABBIX] Global configuration file '/usr/local/etc/zabbix4/zabbix_agentd.conf' differs on disk.")
        return True
__license__ = "GPLv3"
__version__ = "3.0.0"
__maintainer__ = "Vulture Project"
__email__ = "*****@*****.**"
__doc__ = """This migration script rewrite HAProxy certificates on disk """

import os
import sys

sys.path.append('/home/vlt-gui/vulture')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'vulture.settings')

import django
django.setup()

from gui.models.network_settings import Loadbalancer
from gui.models.ssl_certificate import SSLCertificate

if __name__ == '__main__':

    # If HAProxy used
    if Loadbalancer.objects.count() == 0:
        print("No load-balancer configured.")
        sys.exit(0)

    for cert in SSLCertificate.objects():
        cert.write_certificate()
        print("Cert {} reloaded".format(cert.name))

    print("Certificates reloaded")
Пример #12
0
def check_status():
    """ Check if rc.conf.local need updates. Update file if needed

    :return: True if rc.conf.local was updated, False otherwise
    """
    listeners = []
    devices = {}
    haproxy = False
    reg = re.compile("^ifconfig_([^ ]+)_alias\{\}.*")
    cluster = Cluster.objects.get()
    node = cluster.get_current_node()

    # We add alias number (by device)
    for listener in node.get_listeners():

        if reg.match(listener.rc_conf):
            dev = reg.match(listener.rc_conf).groups()[0]
            if not devices.get(dev):
                devices[dev] = 0
            cpt = devices.get(dev)
            rc_conf = listener.rc_conf.format(cpt)
            devices[dev] += 1
        else:
            rc_conf = listener.rc_conf
        listeners.append(rc_conf)
    """ GUI-0.3 Upgrade
      system_settings.pf_settings may not exists in GUI-0.3 upgraded from GUI-0.2
      In this case we need to initialize it with default VALUES
    """
    system_settings = node.system_settings
    if system_settings.pf_settings is None:
        system_settings.pf_settings = PFSettings()

    if system_settings.ipsec_settings is None:
        system_settings.ipsec_settings = IPSECSettings()

    loadbalancers = []
    for loadbalancer in Loadbalancer.objects.all():
        if loadbalancer.ssl_profile and loadbalancer.ssl_profile.hpkp_enable:
            loadbalancer.ssl_profile.pkp = PKP.getSPKIFingerpring(
                loadbalancer.ssl_profile.certificate.cert)

        if loadbalancer.incoming_listener.is_carp:
            for l in loadbalancer.incoming_listener.get_related_carp_inets():
                if l.get_related_node() == node:
                    haproxy = True
                    if loadbalancer not in loadbalancers:
                        loadbalancers.append(loadbalancer)

        elif loadbalancer.incoming_listener.get_related_node() == node:
            if loadbalancer not in loadbalancers:
                loadbalancers.append(loadbalancer)
            haproxy = True

    try:
        pf_logs = True if system_settings.pf_settings.repository_type == 'data' else False
    except KeyError:
        pf_logs = False

    parameters = {
        'default_ipv4_gw': node.default_ipv4_gw,
        'default_ipv6_gw': node.default_ipv6_gw,
        'static_route': node.static_route,
        'listeners': listeners,
        'pf_logs': pf_logs,
        'haproxy': haproxy,
        'strongswan': system_settings.ipsec_settings.enabled
    }

    # Checking if rc.conf.local differs.
    tpl, path_rc = tpl_utils.get_template('rc.conf.local')
    conf_rc = tpl.render(conf=parameters)
    try:
        with open(path_rc, 'r') as f:
            orig_conf = f.read()
    except IOError:
        orig_conf = ""

    # rc.conf.local and/or pf.conf differs => writing new version
    if orig_conf != conf_rc:
        write_in_file(path_rc, conf_rc)
        if node.default_ipv4_gw or node.default_ipv6_gw:
            proc = subprocess.Popen([
                '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo',
                'service', 'routing', 'restart'
            ],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            proc.communicate()

    #### HAPROXY Configuration ####
    parameters = {'haproxy': loadbalancers}
    tpl, path_haproxy = tpl_utils.get_template('vlthaproxy')
    conf_haproxy = tpl.render(conf=parameters)
    if not len(loadbalancers):
        conf_haproxy = ""
    try:
        with open(path_haproxy, 'r') as f:
            orig_conf = f.read()
    except IOError:
        orig_conf = ""

    ## Check diff in haproxy.conf
    proc = subprocess.Popen([
        "/usr/local/bin/sudo", "-u", "vlt-sys", "/usr/local/bin/sudo",
        "service", "vlthaproxy", "status"
    ],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    res, errors = proc.communicate()
    haproxy_need_start = "haproxy not running" in errors.decode('utf8')

    if haproxy and orig_conf != conf_haproxy:

        write_in_file(path_haproxy, conf_haproxy)
        """ Delete all certificates in /home/vlt-sys/Engine/conf/haproxy """
        os.system("/bin/rm %shaproxy/*" % settings.CONF_DIR)
        """ Write SSL-Profile certificates """
        for loadbalancer in loadbalancers:
            if loadbalancer.enable_tls and loadbalancer.ssl_profile:
                loadbalancer.ssl_profile.write_HAProxy_conf()
        """ Store certificates so that HA-PROXY may use them """
        for cert in SSLCertificate.objects():
            cert.write_certificate()

        if not haproxy_need_start:

            proc = subprocess.Popen([
                '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo',
                'service', 'vlthaproxy', 'restart'
            ],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            proc.communicate()

        else:

            proc = subprocess.Popen([
                '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo',
                'service', 'vlthaproxy', 'start'
            ],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            proc.communicate()

    elif haproxy and haproxy_need_start:

        proc = subprocess.Popen([
            '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo',
            'service', 'vlthaproxy', 'start'
        ],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        proc.communicate()

    elif not haproxy:

        write_in_file(path_haproxy, conf_haproxy)
        proc = subprocess.Popen([
            '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo',
            'service', 'vlthaproxy', 'stop'
        ],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        proc.communicate()

    cluster = Cluster.objects.get()
    node = cluster.get_current_node()

    ## CHECK Vulture Cluster Whitelist for Packet Filter
    ips = []
    for listener in Listener.objects.all():
        ips.append(listener.ip)
    ips = set(ips)

    proc = subprocess.Popen([
        '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo', 'pfctl',
        '-t', 'vulture_cluster', '-T', 'show'
    ],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    res, errors = proc.communicate()
    if res is False:
        return False
    res = res.decode('utf8')

    for ip in ips:
        if ip not in node.system_settings.pf_settings.pf_whitelist:
            node.system_settings.pf_settings.pf_whitelist = node.system_settings.pf_settings.pf_whitelist + '\n' + str(
                ip)

    node.save(bootstrap=True)
    res = [r.strip() for r in res.split('\n') if r != ""]
    for ip in ips:
        if ip not in res:
            proc = subprocess.Popen([
                '/usr/local/bin/sudo', '-u', 'vlt-sys', '/usr/local/bin/sudo',
                'pfctl', '-t', 'vulture_cluster', '-T', 'add', ip
            ],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            res2, errors = proc.communicate()
            if res2 is False:
                return False

    return True
Пример #13
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))
Пример #14
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))
Пример #15
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))