示例#1
0
def get_duplicate(order_id, sub_id, file_path, domain, api_key=''):
    LOGGER.info("Getting duplicate")
    LOGGER.info("order id: %s sub id: %s" % (order_id, sub_id))
    if not api_key:
        api_key = get_temp_api_key()

    if api_key:
        order_client = CertificateOrder(HOST, customer_api_key=api_key)
        duplicate_data = order_client.download_duplicate(
            digicert_order_id=order_id, sub_id=sub_id)
        cert_file_path = os.path.join(
            file_path, '{0}.crt'.format(domain.replace(".", "_")))
        chain_file_path = os.path.join(
            file_path, '{0}.pem'.format(domain.replace(".", "_")))

        # download the certificate
        cert = duplicate_data[0]
        cert_file = open(cert_file_path, 'w')
        cert_file.write(cert)
        cert_file.close()

        # download the intermediate certificate
        chain = duplicate_data[2]
        chain_file = open(chain_file_path, 'w')
        chain_file.write(chain)
        chain_file.close()

        return {"cert": cert_file_path, "chain": chain_file_path}
示例#2
0
    def _find_apache_config(self):
        distro = express_utils.determine_platform()
        apache_command = "`which {0}` -V 2>/dev/null".format(
            APACHE_SERVICES.get(distro[0]))
        apache_config = os.popen(apache_command).read()
        if apache_config:
            server_config_check = "SERVER_CONFIG_FILE="
            httpd_root_check = "HTTPD_ROOT="
            server_config_file = apache_config[apache_config.
                                               index(server_config_check) +
                                               len(server_config_check):-1]
            server_config_file = server_config_file.replace('"', '')

            if server_config_file[0] != "/":
                # get the httpd root to find the server config file path
                LOGGER.info("Finding Apache configuration files...")
                httpd_root_dir = apache_config[apache_config.
                                               index(httpd_root_check) +
                                               len(httpd_root_check):-1]
                httpd_root_dir = httpd_root_dir[:httpd_root_dir.index("\n")]
                httpd_root_dir = httpd_root_dir.replace('"', '')

                if os.path.exists(httpd_root_dir) and os.path.isdir(
                        httpd_root_dir):
                    server_config_file = os.path.join(httpd_root_dir,
                                                      server_config_file)

            if os.path.exists(server_config_file):
                return server_config_file
示例#3
0
    def load_apache_configs(self, apache_config_file=None):
        try:
            if not apache_config_file:
                apache_config_file = self._find_apache_config()
            self.aug.set("/augeas/load/Httpd/lens", "Httpd.lns")
            if apache_config_file:
                self.aug.set("/augeas/load/Httpd/incl", apache_config_file)
                self.aug.load()

                # get all of the included configuration files and add them to augeas
                LOGGER.info("Loading Apache configuration files...")
                self._load_included_files(apache_config_file)
                self.check_for_parsing_errors()
            else:
                raise Exception(
                    "We could not find your main apache configuration file.  Please ensure that apache is "
                    "running or include the path to your virtual host file in your command line arguments"
                )
        except Exception, e:
            import traceback
            traceback.print_exc(file=sys.stdout)
            print e.message
            raise e
            self.check_for_parsing_errors()
            raise ParserException(
                "An error occurred while loading your apache configuration.\n{0}"
                .format(e.message), self.directives)
示例#4
0
def configure_apache(host,
                     cert,
                     key,
                     chain,
                     apache_parser=None,
                     apache_config=None,
                     is_multidomain=False):
    """
    Main method to configure a web server.
    :param host:  domain name to secure
    :param cert: path to cert file used to secure the web server
    :param key: path to key file to secure the web server
    :param chain: path to certificate chain file for securing the web server
    :param apache_parser: base parser object
    :param apache_config: path to apache config file
    :return:
    """

    LOGGER.info("Configuring Web Server for virtual host: %s" % host)
    if not apache_parser:
        apache_parser = BaseParser(host,
                                   cert,
                                   key,
                                   chain,
                                   CFG_PATH,
                                   is_multidomain=is_multidomain)
        apache_parser.load_apache_configs(apache_config)

    virtual_host = apache_parser.get_vhost_path_by_domain()
    apache_parser.set_certificate_directives(virtual_host)
    express_utils.enable_ssl_mod()

    LOGGER.info('Apache configuration updated successfully.')
示例#5
0
def create_duplicate(order_id, cert_data, api_key=''):
    LOGGER.info("Creating duplicate")
    if not api_key:
        api_key = get_temp_api_key()

    if api_key:
        order_client = CertificateOrder(HOST, customer_api_key=api_key)
        return order_client.create_duplicate(order_id, **cert_data)
示例#6
0
    def _create_secure_vhost(self, vhost):
        LOGGER.info("Creating new virtual host %s on port 443" % vhost)
        secure_vhost = None
        host_file = "/files{0}".format(get_path_to_file(vhost))

        # create a map of the insecure vhost's configuration
        vhost_map = list()
        self._create_map_from_vhost(vhost, vhost_map)

        if express_utils.determine_platform()[0] != "CentOS":

            # check if there is an IfModule for mod_ssl.c, if not create it
            if_module = None
            check_matches = self.aug.match(
                "{0}/*[label()=~regexp('{1}')]".format(
                    host_file, create_regex("IfModule")))
            if check_matches:
                for check in check_matches:
                    if self.aug.get(check + "/arg") == "mod_ssl.c":
                        if_module = check

            if not if_module:
                self.aug.set(host_file + "/IfModule[last()+1]/arg",
                             "mod_ssl.c")
                if_modules = self.aug.match(
                    host_file + "/*[self::IfModule/arg='mod_ssl.c']")
                if len(if_modules) > 0:
                    if_module = if_modules[0]
                    host_file = if_module
                else:
                    raise ParserException(
                        "An error occurred while creating IfModule mod_ssl.c for {0}."
                        .format(self.domain), self.directives)

        # create a new secure vhost
        vhost_name = self.aug.get(vhost + "/arg")
        vhost_name = vhost_name[0:vhost_name.index(":")] + ":443"
        self.aug.set(host_file + "/VirtualHost[last()+1]/arg", vhost_name)

        vhosts = self.aug.match("{0}/*[self::VirtualHost/arg='{1}']".format(
            host_file, vhost_name))
        for vhost in vhosts:
            secure_vhost = vhost

            # write the insecure vhost configuration into the new secure vhost
            self._create_vhost_from_map(secure_vhost, vhost_map)

        self.check_for_parsing_errors()

        return secure_vhost
def cleanup(domain=''):
    LOGGER.info("Cleaning up files")
    for path in os.listdir(CFG_PATH):
        if path.endswith('.crt'):
            os.remove('%s/%s' % (CFG_PATH, path))

    if os.path.exists('/tmp/certs'):
        shutil.rmtree('/tmp/certs')

    if domain:
        pem_file = '%s/%s' % (CFG_PATH, domain)
        pem_file = pem_file.replace('.', '_')
        pem_file = '%s.pem' % pem_file
        if os.path.exists(pem_file):
            os.remove(pem_file)
示例#8
0
def verify_and_normalize_file(file_path,
                              desc,
                              name,
                              apache_user,
                              storage_path,
                              keep_original=False):
    """
    Verify that the file exists, move it to a common location, & set the proper permissions

    :param file_path  the file to verify/normalize
    :param desc  what kind of file is this? for output purposes only
    :param name what the new file name should be
    :param apache_user  the user apache runs as
    :param storage_path  where to store the file
    :return:
    """

    if not os.path.isfile(file_path):
        raise ParserException("%s %s could not be found on the filesystem" %
                              (desc, file_path))

    if not os.path.exists(storage_path):
        LOGGER.info("Creating directory: %s" % storage_path)
        os.mkdir(storage_path)

    LOGGER.info("Copying files to: %s" % storage_path)
    # copy the files to the storage path if they aren't already there
    path = os.path.dirname(file_path)
    old_name = os.path.basename(file_path)
    if storage_path != path or old_name != name:
        normalized_cfg_file = '%s/%s' % (storage_path, name)
        if keep_original:
            shutil.copy(file_path, normalized_cfg_file)
            LOGGER.info('Copied %s to %s...' %
                        (file_path, normalized_cfg_file))
        else:
            shutil.move(file_path, normalized_cfg_file)
            LOGGER.info('Moved %s to %s...' % (file_path, normalized_cfg_file))
        file_path = normalized_cfg_file

    # change the owners of the ssl files
    LOGGER.info("Updating permissions on %s" % file_path)
    os.system("chown root:{0} {1}".format(apache_user, file_path))

    # change the permission of the ssl files, only the root and apache users should have read permissions
    os.system("chmod 640 {0}".format(file_path))

    return file_path
示例#9
0
def get_temp_api_key():
    # prompt for username and password,
    LOGGER.info(
        "You will need your Digicert account credentials to continue: ")

    username = raw_input("DigiCert Username: "******"DigiCert Password: ")

    result = Request(action=LoginCommand(username, password), host=HOST).send()
    if result['http_status'] >= 300:
        raise Exception('Login failed:  %d - %s' %
                        (result['http_status'], result['http_reason']))

    try:
        api_key = result['api_key']
        return api_key
    except KeyError:
        api_key = None
    return
示例#10
0
def verify_requirements():
    LOGGER.info("Verifying minimum requirements are met. ")
    os_name, os_version, code_name = express_utils.determine_platform()
    python_version = express_utils.determine_python_version()
    apache_version = express_utils.determine_apache_version(os_name)

    errors = []
    if apache_version:
        if os_name == 'Ubuntu':
            if StrictVersion(os_version) < StrictVersion('14.04'):
                errors.append(
                    "Your version of Ubuntu (%s) is not supported.  Ubuntu version 14.04 or higher is required."
                    % os_version)
            if StrictVersion(python_version) < StrictVersion('2.7'):
                errors.append(
                    "Your version of Python (%s) is not supported.  Python version 2.7 or higher is required."
                    % python_version)
            if StrictVersion(apache_version) < StrictVersion('2.4'):
                errors.append(
                    "Your version of Apache (%s) is not supported.  Apache version 2.4 or higher is required."
                    % apache_version)
        elif os_name == 'CentOS':
            if StrictVersion(os_version) < StrictVersion('6.5'):
                errors.append(
                    "Your version of CentOS (%s) is not supported.  CentOS version 6.5 or higher is required."
                    % os_version)
            if StrictVersion(python_version) < StrictVersion('2.6'):
                errors.append(
                    "Your version of Python (%s) is not supported.  Python version 2.6 or higher is required."
                    % python_version)
            if StrictVersion(apache_version) < StrictVersion('2.2'):
                errors.append(
                    "Your version of Apache (%s) is not supported.  Apache version 2.2 or higher is required."
                    % apache_version)
        else:
            errors.append(
                "%s %s is not a supported operating system.  Ubuntu 14.04 and CentOS 6.5 are supported."
                % (os_name, os_version))
    else:
        errors.append(
            "No Apache version detected, please verify that Apache is installed and running"
        )

    if len(errors) > 0:
        if 'localhost' not in express_utils.HOST:
            error_msg = "ERROR: Your system does not meet the minimum requirements to run this program:"
            LOGGER.info(error_msg)
            LOGGER.info("\n".join(errors))
            for error in errors:
                error_msg = "%s\n%s" % (error_msg, error)
            raise Exception(error_msg)
    else:
        LOGGER.info("Minimum requirements are met")
示例#11
0
def finalize_and_restart(domain):
    if raw_input('Would you like to restart Apache now? [Y/n] ') != 'n':
        express_utils.restart_apache()
        LOGGER.info(
            "Congratulations, you've successfully installed your certificate to (%s)."
            % domain)
    else:
        LOGGER.info(
            'Restart your Apache server for your changes to take effect.')
        LOGGER.info(
            'Use the following command to restart your Apache server and verify your SSL settings:'
        )
        LOGGER.info('sudo express_install restart_apache')
示例#12
0
    def get_vhosts_on_server(self):
        """ Use this method to search for all virtual hosts configured on the web server """
        LOGGER.info("Getting vhosts on server")
        server_virtual_hosts = []
        matches = self.aug.match("/augeas/load/Httpd/incl")
        for match in matches:
            host_file = "/files{0}".format(self.aug.get(match))
            if '~previous' not in host_file:
                vhosts = self.aug.match("{0}/*[label()=~regexp('{1}')]".format(
                    host_file, create_regex("VirtualHost")))
                vhosts += self.aug.match(
                    "{0}/*/*[label()=~regexp('{1}/arg')]".format(
                        host_file, create_regex("VirtualHost")))

                vhost = self._get_vhosts_domain_name(vhosts, '443')
                if not vhost:
                    vhost = self._get_vhosts_domain_name(vhosts, '80')
                if vhost:
                    server_virtual_hosts.extend(vhost)
        return server_virtual_hosts
示例#13
0
def get_order_and_domain_info(order_id, domain):
    common_name = domain
    if not order_id and not domain:
        # if we don't have an order_id or domain, then we'll query for all issued certificates
        LOGGER.info(
            "no order_id or domain, so let's query %s for issued certificates in the account"
            % HOST)
        order = select_from_orders()
        order_id = order['id']
        domain = order.get('certificate', None).get('common_name', None)
        common_name = domain

    if not order_id and domain:
        LOGGER.info("querying %s for issued certificates for domain %s" %
                    (HOST, domain))
        order = get_order_by_domain(domain)
        order_id = order.get('id', '')
        common_name = order.get('certificate', None).get('common_name', None)

    return order_id, domain, common_name
示例#14
0
    def check_for_parsing_errors(self):
        LOGGER.info("Verifying Apache configuration files can be parsed...")
        errors = []
        error_files = self.aug.match("/augeas//error")
        for path in error_files:
            # check to see if it was an error resulting from the use of the httpd lens
            lens_path = self.aug.get(path + "/lens")
            if lens_path and "httpd.aug" in lens_path:
                # strip off /augeas/files and /error
                error_message = self.aug.get(path + "/message")
                error_line = self.aug.get(path + "/line")

                errors.append(
                    "Error parsing the file: {0} {1} at line #{2}".format(
                        path[13:len(path) - 6], error_message, error_line))

        if len(errors) > 0:
            error_msg = "The following errors occurred while parsing your configuration file:"
            for error in errors:
                error_msg = "{0}\t{1}\n".format(error_msg, error)
            raise Exception(error_msg)
示例#15
0
def format_config_file(host_file):
    """
    Format the apache configuration file.  Loop through the lines of the file and indent/un-indent where necessary

    :param host_file:
    :return:
    """
    LOGGER.info("Formatting file %s" % host_file)

    # get the lines of the config file
    lines = list()
    with open(host_file) as f:
        lines = f.read().splitlines()

    f = open(host_file, 'w+')

    try:
        format_lines(lines, f)
    finally:
        f.truncate()
        f.close()
示例#16
0
def upload_csr(order_id, csr_file, api_key=''):
    LOGGER.info("Uploading CSR file for order# {0}...".format(order_id))
    if not api_key:
        api_key = get_temp_api_key()

    if api_key:
        # call the V2 view orders API
        csr_text = None
        with open(csr_file, "r") as f:
            csr_text = f.read()

        orderclient = CertificateOrder(HOST, api_key)
        resp = orderclient.upload_csr(order_id, csr_text)
        if resp and resp['http_status']:
            # accept any 2xx status code
            import math

            result = int(math.floor(int(resp['http_status']) / 100)) * 100
            if result == 200:
                LOGGER.info("CSR uploaded successfully")
                print ""
                return True
        return False
示例#17
0
def _download_and_install_cert(order_id,
                               domain,
                               private_key='',
                               api_key='',
                               create_csr=False):
    LOGGER.info("Attempting to download the cert")
    private_key_file = private_key
    if create_csr:
        private_key_file, csr_file = express_utils.create_csr(domain)
        express_client.upload_csr(
            order_id, csr_file,
            api_key)  # TODO: maybe catch result to see if successful

    certs = express_client.download_cert(order_id,
                                         CFG_PATH,
                                         domain,
                                         api_key=api_key)
    chain = certs.get('chain', None)
    cert = certs.get('cert', None)
    key = private_key_file
    if not key:
        key = parsers.locate_cfg_file('%s.key' % domain.replace('.', '_'),
                                      'Private key',
                                      validate_key=True,
                                      cert=cert,
                                      default_search_path="{0}/{1}".format(
                                          CFG_PATH, domain.replace('.', '_')))

    if not key:
        raise Exception('Could not find private key')

    LOGGER.info("Installing cert for domain: %s" % domain)
    parsers.configure_apache(domain, cert, key, chain)

    cleanup()

    return
示例#18
0
def _download_multidomain_cert(order_id,
                               common_name,
                               domains,
                               private_key='',
                               api_key='',
                               create_duplicate=False):
    LOGGER.info("Getting ready to download the certificate.")
    key = private_key
    if create_duplicate:
        LOGGER.info("Creating duplicate certificate")
        private_key_file, csr_file = express_utils.create_csr(common_name)

        csr = open(csr_file, 'r').read()
        duplicate_cert_data = {
            "certificate": {
                "common_name": common_name,
                "csr": csr,
                "signature_hash": "sha256",
                "server_platform": {
                    "id": 2
                },
                "dns_names": domains
            }
        }

        result = express_client.create_duplicate(order_id,
                                                 duplicate_cert_data,
                                                 api_key=api_key)
        LOGGER.info("Please wait a few seconds")
        import time
        time.sleep(12)
        if not result.get('sub_id'):
            raise Exception(
                "Order: %s needs to have administrator approval to proceed.  Please contact your administrator or DigiCert Support for help. "
                % order_id)
        duplicate_cert = express_client.get_duplicate(order_id,
                                                      result.get('sub_id'),
                                                      CFG_PATH,
                                                      common_name,
                                                      api_key=api_key)
        cert = duplicate_cert.get("cert", None)
        chain = duplicate_cert.get("chain", None)
        key = private_key_file
    else:
        certs = express_client.download_cert(order_id,
                                             CFG_PATH,
                                             common_name,
                                             api_key=api_key)
        chain = certs.get('chain', None)
        cert = certs.get('cert', None)

    if not key:
        raise Exception('Could not find private key')

    return cert, chain, key
示例#19
0
    def set_certificate_directives(self, vhost_path):
        try:
            if not vhost_path:
                raise Exception(
                    "Virtual Host was not found for {0}.  Please verify that the 'ServerName' directive in "
                    "your Virtual Host is set to {1} and try again.".format(
                        self.domain, self.domain))

            # back up the configuration file
            host_file = get_path_to_file(vhost_path)
            shutil.copy(host_file, "{0}~previous".format(host_file))

            errors = []
            for directive in self.directives:
                matches = self.aug.match(
                    "{0}/*[self::directive=~regexp('{1}')]".format(
                        vhost_path, create_regex(directive)))
                if len(matches) > 0:
                    for match in matches:
                        self.aug.set("{0}/arg".format(match),
                                     self.directives[directive])
                        LOGGER.info(
                            "Directive %s was updated to %s in %s" %
                            (directive, self.directives[directive], match))
                else:
                    self.aug.set(vhost_path + "/directive[last()+1]",
                                 directive)
                    self.aug.set(vhost_path + "/directive[last()]/arg",
                                 self.directives[directive])

            if len(errors):
                error_msg = "Could not update all directives:\n"
                for error in errors:
                    error_msg = "{0}\t{1}\n".format(error_msg, error)
                raise Exception(error_msg)

            self.aug.save()

            # check for augeas errors
            self.check_for_parsing_errors()

            # verify the added/modified directives are the values we set
            errors = []
            for directive in self.directives:
                val = None
                matches = self.aug.match(
                    "{0}/*[self::directive=~regexp('{1}')]/arg".format(
                        vhost_path, create_regex(directive)))
                if len(matches) > 0:
                    for match in matches:
                        val = self.aug.get(match)

                if val != self.directives[directive]:
                    errors.append("{0} is {1} instead of {2}".format(
                        directive, val, self.directives[directive]))

            if len(errors) > 0:
                error_msg = "Some of your directives are incorrect:\n"
                for error in errors:
                    error_msg = "{0}\t{1}\n".format(error_msg, error)
                raise Exception(error_msg)

        except Exception, e:
            self.check_for_parsing_errors()
            raise ParserException(
                "An error occurred while updating the Virtual Host for {0}".
                format(self.domain), self.directives)
示例#20
0
def locate_cfg_file(cfg_file_names,
                    file_type,
                    prompt=True,
                    validate_key=False,
                    cert=None,
                    default_search_path=CFG_PATH):
    """
    :param cfg_file_names: list of file names to loop through
    :param file_type:
    :param prompt: boolean, set to true and will ask user for a path to the file
    :param validate_key:
    :param cert:
    :param default_search_path:
    :return:
    """

    LOGGER.info("Looking for {0}...".format(file_type))
    if isinstance(cfg_file_names, basestring):
        names = [cfg_file_names]
    else:
        names = cfg_file_names
    for cfg_file_name in names:
        file_path = os.path.join(default_search_path, cfg_file_name)
        if os.path.exists(file_path):
            return_file = True
            if validate_key:
                if not cert or not express_utils.validate_key(file_path, cert):
                    return_file = False
            if return_file:
                return file_path

    # Search the filesystem
    for cfg_file_name in names:
        sudo_user_name = os.getenv("SUDO_USER")
        sudo_user_home = "%s/%s" % ("/home", sudo_user_name)

        command = "find {0} -type f -name {1}".format(sudo_user_home,
                                                      cfg_file_name)
        files = os.popen(command).read().splitlines()

        if len(files) > 0:
            matching_files = list()
            for file in files:
                if validate_key:
                    if cert and express_utils.validate_key(file, cert):
                        matching_files.append(file)
                else:
                    matching_files.append(file)

            if len(matching_files) == 1:
                return matching_files[0]
            elif len(matching_files) > 1:
                resp = None
                while not resp:
                    for i in range(0, len(matching_files)):
                        print "{0}.\t{1}".format(i + 1, matching_files[i])

                    resp = raw_input(
                        "\nPlease select the {0} you wish to secure "
                        "from the list above (q to quit): ".format(file_type))

                    if resp != 'q':
                        # validate the input, catch any exceptions from casting to an int and validate the
                        # int value makes sense
                        try:
                            if int(resp) > len(matching_files) or int(
                                    resp) < 0:
                                raise ValueError
                        except ValueError as e:
                            resp = None
                            print ""
                            print "ERROR: Invalid number, please try again."
                            print ""
                    else:
                        continue
                if resp and resp != 'q':
                    selection = int(resp) - 1
                    return matching_files[selection]

    if prompt:
        # At this point we haven't found any matching files so we need to prompt for one
        file_path = None
        try:
            while not file_path:
                try:
                    answer = raw_input(
                        "Do you have a private key for the certificate you want to install? [y/n] "
                    )
                    if answer and answer.strip().lower() == 'y':
                        file_path = raw_input(
                            'Please provide a full absolute path to the file: '
                        )
                    else:
                        file_path = 'q'
                        return ''

                    if os.path.exists(file_path):
                        if validate_key and cert:
                            if not express_utils.validate_key(file_path, cert):
                                raise Exception(
                                    "This key ({0}) does not match your certificate ({1}), please try again."
                                    .format(file_path, cert))
                            else:
                                break
                        else:
                            break
                    if len(file_path):
                        raise Exception('No such file or directory: "%s"' %
                                        file_path)
                    file_path = None
                except Exception, e:
                    file_path = None
                    print e.message
                    print ''
        except KeyboardInterrupt:
            print ''
            LOGGER.error('No valid file selected.')
            print ''
        return file_path
示例#21
0
def _install_multidomain_cert(order_id,
                              common_name,
                              domains,
                              cert,
                              key,
                              chain,
                              api_key=''):
    # get all virtual hosts
    apache_parser = parsers.prepare_parser(common_name, cert, key, chain)
    LOGGER.info("Now, getting the vhosts that are on this server")
    virtual_hosts = apache_parser.get_vhosts_on_server()

    # find matches from virtuals hosts and domains
    matched_hosts = parsers.compare_match(virtual_hosts, domains)
    LOGGER.info("Found matching host: \n%s" % "\n".join(matched_hosts))

    if not matched_hosts:
        raise Exception(
            "Didn't find any virtual hosts on this web server matching the domains for this certificate.\nCheck '/etc/digicert' for downloaded certificates"
        )

    # prepare menu selection for the user to choose which virtual hosts to configure
    choices = zip(range(1, len(matched_hosts) + 1), matched_hosts)
    doc_hosts = list()
    for choice in choices:
        s = [str(a) for a in choice]
        doc_hosts.append(". ".join(s))
    prompt_hosts = "\n".join(doc_hosts)
    LOGGER.info(
        "The following virtual hosts on this server match the certificate. ")
    LOGGER.info(prompt_hosts)
    selected = raw_input(
        "Choose which hosts to configure:\nEnter comma separated numbers to select multiple hosts.  IE 1,2,3\n"
    )

    # from user input, determine the domains chosen.
    selection = selected.split(',')
    selected_hosts = []
    for x in selection:
        for choice in choices:
            if int(x) == choice[0]:
                LOGGER.info("User selected host: %s" % choice[1])
                selected_hosts.append(choice[1])

    # finally, configure apache
    for host in selected_hosts:
        LOGGER.info("Installing cert for domain: %s" % host)
        apache_parser.common_name = host
        parsers.configure_apache(host,
                                 apache_parser.cert_path,
                                 apache_parser.key_path,
                                 apache_parser.chain_path,
                                 is_multidomain=True)

    cleanup(domain=common_name)

    return
示例#22
0
def _process(domain, order_id, failed_pk_check=False):
    order_info = express_client.get_order_info(order_id)
    api_key = order_info.get('api_key')
    if order_info.get('status') != 'issued':
        if order_info.get('status') == 'needs_csr':
            LOGGER.info("Order needs a CSR.")
            private_key_file, csr_file = express_utils.create_csr(domain)
            express_client.upload_csr(order_id, csr_file, api_key=api_key)
            order_info = express_client.get_order_info(order_id,
                                                       api_key=api_key)
            if order_info.get('status') == 'issued':
                LOGGER.info("Order is issued")

                if order_info.get('allow_duplicates'):
                    cert, chain, key = _download_multidomain_cert(
                        order_id,
                        domain,
                        domains=order_info.get('certificate').get('dns_names'),
                        private_key=private_key_file,
                        api_key=api_key,
                        create_duplicate=False)
                    _install_multidomain_cert(
                        order_id,
                        domain,
                        domains=order_info.get('certificate').get('dns_names'),
                        cert=cert,
                        key=private_key_file,
                        chain=chain,
                        api_key=api_key)
                else:
                    _download_and_install_cert(order_id,
                                               domain,
                                               private_key=private_key_file,
                                               api_key=api_key,
                                               create_csr=False)
                return
            # TODO: we may need to add better handling for csr if it exists
        raise Exception(
            'This certificate cannot be installed at this time because something happened getting the status back from the site'
        )
    else:
        if order_info.get('allow_duplicates'):
            response = raw_input(
                "Do you want to create and install a duplicate for a certificate? \n Answering no will attempt to install the original certificate.  [y/n] "
            )
            LOGGER.info(
                "Do you want to create and install a duplicate for a certificate? \n Answering no will attempt to install the original certificate.  [y/n] "
            )
            LOGGER.info("Duplicate Response: %s" % response)
            if response.lower().strip() == 'y':  # TODO: make this more robust
                cert, chain, key = _download_multidomain_cert(
                    order_id,
                    domain,
                    domains=order_info.get('certificate').get('dns_names'),
                    api_key=api_key,
                    create_duplicate=True)
                _install_multidomain_cert(
                    order_id,
                    domain,
                    domains=order_info.get('certificate').get('dns_names'),
                    cert=cert,
                    key=key,
                    chain=chain)
            else:
                if not failed_pk_check:
                    _download_and_install_cert(order_id,
                                               domain,
                                               api_key=api_key,
                                               create_csr=False)
                else:
                    raise Exception(
                        'This certificate cannot be installed at this time because it failed the pk check.'
                    )
        else:
            if not failed_pk_check:
                LOGGER.info("Order does not support duplicates")
                _download_and_install_cert(order_id,
                                           domain,
                                           api_key=api_key,
                                           create_csr=False)
            else:
                raise Exception(
                    'This certificate cannot be installed at this time')
示例#23
0
def do_everything_with_args(order_id='', domain='', api_key='', key=''):
    raw_input(
        "I'll attempt to secure virtual hosts configured on this web server with an SSL certificate.  Press ENTER to continue."
    )
    print ''
    LOGGER.info("Looking up order info")
    order_id, domain, common_name = express_client.get_order_and_domain_info(
        order_id, domain)

    if order_id:  #and not domain:
        # 1.  get the order info for order_id, domain and common_name
        LOGGER.info("Querying for issued certificates with order_id %s" %
                    order_id)

        # 2.  look for key, chain and csr
        cert = parsers.locate_cfg_file(
            '%s.crt' % express_utils.replace_chars(common_name),
            'Certificate',
            prompt=False,
            default_search_path="{0}/{1}".format(
                CFG_PATH, express_utils.replace_chars(domain)))
        chain = parsers.locate_cfg_file(
            ['DigiCertCA.crt'],
            'Certificate chain',
            prompt=False,
            default_search_path="{0}/{1}".format(
                CFG_PATH, express_utils.replace_chars(domain)))
        key = parsers.locate_cfg_file('%s.key' %
                                      express_utils.replace_chars(common_name),
                                      'Private key',
                                      validate_key=True,
                                      cert=cert,
                                      default_search_path="{0}/{1}".format(
                                          CFG_PATH,
                                          express_utils.replace_chars(domain)))

        if cert and chain and key:
            LOGGER.info("Found cert, chain and key")
            LOGGER.info("Installing cert for domain: %s" % domain)

            dns_names = express_utils.get_dns_names_from_openssl(cert)

            _install_multidomain_cert(order_id,
                                      domain,
                                      dns_names,
                                      cert,
                                      key=key,
                                      chain=chain)
            finalize_and_restart(domain)
            return

        if not cert and not chain and not key:
            LOGGER.info("Did not find cert, chain and key, proceeding...")
            _process(domain, order_id, failed_pk_check=False)
            finalize_and_restart(domain)
            return

        if cert and chain and not key:
            LOGGER.info("Found cert and chain but not key, proceeding...")
            _process(domain, order_id, failed_pk_check=True)
            finalize_and_restart(domain)
            return
    else:
        LOGGER.error("ERROR: You must specify a valid domain or order id")
示例#24
0
def download_cert(order_id, file_path=None, domain=None, api_key=''):
    msg_downloading = 'Downloading certificate files for: '
    msg_from_dc = 'from %s' % HOST
    if domain:
        LOGGER.info('%s domain "%s" %s (Order ID: %s)...' %
                    (msg_downloading, domain.lower(), msg_from_dc, order_id))
    else:
        LOGGER.info('%s order ID "%s" %s...' %
                    (msg_downloading, order_id, msg_from_dc))
    print ''

    domain = domain.lower()

    if not api_key:
        api_key = get_temp_api_key()

    if api_key:
        orderclient = CertificateOrder(HOST, api_key)
        certificates = orderclient.download(digicert_order_id=order_id)

        cert_file_path = os.path.join(file_path, 'cert.crt')
        chain_file_path = os.path.join(file_path, 'chain.pem')

        try:
            # create the download directory if it does not exist
            if file_path and not os.path.exists(file_path):
                os.mkdir(file_path.replace('*', 'star'))
                LOGGER.info('Created %s directory...' % file_path)

            if isinstance(certificates, str):
                # then we know this is a zip file containing all certs
                zip_file = ZipFile(StringIO(certificates))
                tmp_dir = tempfile.gettempdir()
                zip_file.extractall(tmp_dir)

                # get the files that were extracted
                cert_dir = os.path.join(tmp_dir, "certs")
                src_cert_file_path = os.path.join(
                    cert_dir, '{0}.crt'.format(domain.replace(".", "_")))
                src_chain_file_path = os.path.join(cert_dir, 'DigiCertCA.crt')
                cert_file_path = os.path.join(
                    file_path, os.path.basename(src_cert_file_path))
                chain_file_path = os.path.join(
                    file_path, os.path.basename(src_chain_file_path))
                src_cert_file_path = src_cert_file_path.replace('*', 'star')
                cert_file_path = cert_file_path.replace('*', 'star')
                express_utils.copy_cert(src_cert_file_path, cert_file_path)
                express_utils.copy_cert(src_chain_file_path, chain_file_path)
            else:
                certificates = certificates.get('certificates')
                if not certificates:
                    raise Exception(
                        "Failed to get certificates from order ".format(
                            order_id))

                if domain:
                    cert_file_path = os.path.join(
                        file_path, '{0}.crt'.format(domain.replace(".", "_")))
                    chain_file_path = os.path.join(
                        file_path, '{0}.pem'.format(domain.replace(".", "_")))

                # download the certificate
                cert = certificates.get('certificate')
                cert_file = open(cert_file_path, 'w')
                cert_file.write(cert)
                cert_file.close()

                # download the intermediate certificate
                chain = certificates.get('intermediate')
                chain_file = open(chain_file_path, 'w')
                chain_file.write(chain)
                chain_file.close()
        except IOError as ioe:
            raise Exception("Download failed: {0}".format(ioe))

        LOGGER.info('Created certificate file at path %s' % cert_file_path)
        LOGGER.info('Created certificate chain file at path %s' %
                    chain_file_path)
        print ''
        LOGGER.info('Certificate files downloaded successfully')
        print ''

        return {'cert': cert_file_path, 'chain': chain_file_path}
    else:
        raise Exception(
            'Username or API Key required to download certificate.')
示例#25
0
def run():
    if os.geteuid() != 0:
        print 'DigiCert Express Install must be run as root.'
        exit()

    parser = argparse.ArgumentParser(
        description=
        'Express Install. Let DigiCert manage your certificates for you!  '
        'Run the following commands in the order shown below, or choose "all" to do everything in one step.'
    )
    parser.add_argument('--version',
                        action='version',
                        version='Express Install %s' %
                        pkg_resources.require('digicert_express')[0].version)
    subparsers = parser.add_subparsers(
        help='Choose from the command options below:')

    dependency_check_parser = subparsers.add_parser(
        'dep_check', help="Check for and install any needed dependencies")
    dependency_check_parser.set_defaults(func=check_for_deps)

    restart_apache_parser = subparsers.add_parser(
        'restart_apache', help='Restart Apache and verify SSL configuration')
    restart_apache_parser.add_argument(
        "--domain",
        action="store",
        nargs="?",
        help="Domain to verify after the restart")
    restart_apache_parser.set_defaults(func=restart_apache)

    all_parser = subparsers.add_parser(
        "all",
        help='Download your certificate and secure your domain in one step')
    all_parser.add_argument("--domain",
                            action="store",
                            help="Domain name to secure")
    all_parser.add_argument(
        "--key",
        action="store",
        help="Path to private key file used to order certificate")
    all_parser.add_argument(
        "--api_key",
        action="store",
        help="Skip authentication step with a DigiCert API key")
    all_parser.add_argument("--order_id",
                            action="store",
                            help="DigiCert order ID for certificate")
    all_parser.set_defaults(func=do_everything)

    args = parser.parse_args()

    try:
        print ''
        LOGGER.info(
            'DigiCert Express Install Web Server Configuration Utility')
        print ''
        verify_requirements()
        args.func(args)
    except Exception, e:
        raise e
        LOGGER.error(e)
        print ''