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}
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
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)
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.')
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)
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)
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
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
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")
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')
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
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
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)
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()
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
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
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
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)
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
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
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')
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")
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.')
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 ''