def main(): parser = argparse.ArgumentParser( description='King Phisher Certbot Wrapper Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('--certbot', dest='certbot_bin', help='the path to the certbot binary to use') parser.add_argument('--json-output', dest='json_file', help='update a json formatted file with the details') parser.add_argument('--restart-service', action='store_true', default=False, help='attempt to restart the king-phisher service') parser.add_argument('server_config', help='the server configuration file') parser.add_argument('hostnames', nargs='+', help='the host names to request certificates for') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() server_config = configuration.ex_load_config( arguments.server_config).get('server') web_root = server_config['web_root'] if os.getuid(): color.print_error('this tool must be run as root') return os.EX_NOPERM certbot_bin = arguments.certbot_bin or smoke_zephyr.utilities.which( 'certbot') if certbot_bin is None: color.print_error( 'could not identify the path to the certbot binary, make sure that it is' ) color.print_error( 'installed and see: https://certbot.eff.org/ for more details') return os.EX_UNAVAILABLE if not os.access(certbot_bin, os.R_OK | os.X_OK): color.print_error( 'found insufficient permissions on the certbot binary') return os.EX_NOPERM logger = logging.getLogger('KingPhisher.Tool.CLI.CertbotWrapper') logger.info('using certbot binary at: ' + certbot_bin) logger.debug('getting server binding information') if server_config.get('addresses'): address = server_config['addresses'][0] else: address = server_config['address'] address['ssl'] = bool(server_config.get('ssl_cert')) logger.debug( "checking that the king phisher server is running on: {host}:{port} (ssl={ssl})" .format(**address)) try: rpc = advancedhttpserver.RPCClient((address['host'], address['port']), use_ssl=address['ssl']) version = rpc('version') except (advancedhttpserver.RPCError, socket.error): logger.error('received an rpc error while checking the version', exc_info=True) color.print_error( 'failed to verify that the king phisher server is running') return os.EX_UNAVAILABLE logger.info('connected to server version: ' + version['version']) vhost_directories = server_config['vhost_directories'] if len(arguments.hostnames) > 1 and not vhost_directories: color.print_error( 'vhost_directories must be true to specify multiple hostnames') return os.EX_CONFIG for hostname in arguments.hostnames: if vhost_directories: directory = os.path.join(web_root, hostname) else: directory = web_root if os.path.split(os.path.abspath(directory))[-1] != hostname: color.print_error( 'when the vhost_directories option is not set, the web_root option' ) color.print_error('must be: ' + os.path.join(web_root, hostname)) return os.EX_CONFIG if not os.path.exists(directory): os.mkdir(directory, mode=0o775) logger.info('created directory for host at: ' + directory) certbot_args = (certbot_bin, 'certonly', '--webroot', '-w', directory, '-d', hostname) logger.info('running certbot command: ' + ' '.join(certbot_args)) proc_h = subprocess.Popen(certbot_args, shell=False) status = proc_h.wait() if status != os.EX_OK: color.print_error('certbot exited with exit status: ' + str(status)) break color.print_good('certbot exited with a successful status code') timestamp = datetime.datetime.utcnow().isoformat() + '+00:00' if not os.path.isdir(os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname)): logger.warning('failed to find the new hostname in: ' + LETS_ENCRYPT_LIVE_PATH) continue details = { 'created': timestamp, 'host': hostname, 'ssl_cert': os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname, 'fullchain.pem'), 'ssl_key': os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname, 'privkey.pem') } if arguments.json_file: existing_data = [] if os.path.isfile(arguments.json_file): with open(arguments.json_file, 'r') as file_h: existing_data = serializers.JSON.load(file_h) if not isinstance(existing_data, list): color.print_status( 'the existing json data must be a list to add the new data' ) existing_data.append(details) with open(arguments.json_file, 'w') as file_h: serializers.JSON.dump(existing_data, file_h) else: color.print_status( 'copy the following lines into the server configuration file under' ) color.print_status( 'the \'ssl_hosts:\' section to use the certificates with king phisher' ) print(' # created: ' + details['created']) print(' - host: ' + details['host']) print(' ssl_cert: ' + details['ssl_cert']) print(' ssl_key: ' + details['ssl_key']) if arguments.hostnames and arguments.json_file and arguments.restart_service: systemctl_bin = smoke_zephyr.utilities.which('systemctl') if systemctl_bin is None: color.print_error( 'could not restart the king-phisher service (could not find systemctl)' ) return os.EX_OK proc_h = subprocess.Popen([systemctl_bin, 'restart', 'king-phisher'], shell=False) if proc_h.wait() != 0: color.print_error( 'failed to restart the king-phisher service via systemctl') return os.EX_SOFTWARE color.print_status('restarted the king-phisher service via systemctl') return os.EX_OK
def main(): parser = argparse.ArgumentParser(description='King Phisher Certbot Wrapper Utility', conflict_handler='resolve') utilities.argp_add_args(parser) parser.add_argument('--certbot', dest='certbot_bin', help='the path to the certbot binary to use') parser.add_argument('server_config', type=argparse.FileType('r'), help='the server configuration file') parser.add_argument('hostnames', nargs='+', help='the host names to request certificates for') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() server_config = yaml.load(arguments.server_config) web_root = server_config['server']['web_root'] if os.getuid(): color.print_error('this tool must be ran as root') return os.EX_NOPERM certbot_bin = arguments.certbot_bin or smoke_zephyr.utilities.which('certbot') if certbot_bin is None: color.print_error('could not identify the path to the certbot binary, make sure that it is') color.print_error('installed and see: https://certbot.eff.org/ for more details') return os.EX_NOTFOUND if not os.access(certbot_bin, os.R_OK | os.X_OK): color.print_error('found insufficient permissions on the certbot binary') return os.EX_NOPERM logger = logging.getLogger('KingPhisher.Tool.CLI.CertbotWrapper') logger.info('using certbot binary at: ' + certbot_bin) logger.debug('getting server binding information') if server_config['server'].get('addresses'): address = server_config['server']['addresses'][0] else: address = server_config['server']['address'] address['ssl'] = bool(server_config['server'].get('ssl_cert')) logger.debug("checking that the king phisher server is running on: {host}:{port} (ssl={ssl})".format(**address)) try: rpc = advancedhttpserver.RPCClient((address['host'], address['port']), use_ssl=address['ssl']) version = rpc('version') except (advancedhttpserver.RPCError, socket.error): logger.error('received an rpc error while checking the version', exc_info=True) color.print_error('failed to verify that the king phisher server is running') return os.EX_UNAVAILABLE logger.info('connected to server version: ' + version['version']) vhost_directories = server_config['server']['vhost_directories'] if len(arguments.hostnames) > 1 and not vhost_directories: color.print_error('vhost_directories must be true to specify multiple hostnames') return os.EX_CONFIG for hostname in arguments.hostnames: if vhost_directories: directory = os.path.join(web_root, hostname) else: directory = web_root if os.path.split(os.path.abspath(directory))[-1] != hostname: color.print_error('when the vhost_directories option is not set, the web_root option') color.print_error('must be: ' + os.path.join(web_root, hostname)) return os.EX_CONFIG if not os.path.exists(directory): os.mkdir(directory, mode=0o775) logger.info('created directory for host at: ' + directory) certbot_args = (certbot_bin, 'certonly', '--webroot', '-w', directory, '-d', hostname) logger.info('running certbot command: ' + ' '.join(certbot_args)) proc_h = subprocess.Popen(certbot_args, shell=False) status = proc_h.wait() if status != os.EX_OK: color.print_error('certbot exited with exit status: ' + int(status)) break color.print_good('certbot exited with successful status code') if not os.path.isdir(os.path.join(LETS_ENCRYPT_LIVE_PATH, hostname)): logger.warning('failed to find the new hostname in: ' + LETS_ENCRYPT_LIVE_PATH) continue color.print_status('copy the following lines into the server configuration file under') color.print_status('the \'ssl_hosts:\' section to use the certificates with king phisher') print(" - host: {0}".format(hostname)) print(" ssl_cert: /etc/letsencrypt/live/{0}/fullchain.pem".format(hostname)) print(" ssl_key: /etc/letsencrypt/live/{0}/privkey.pem".format(hostname))