def __init__(self, stdout: Optional[bool] = True, verbose: Optional[bool] = False, pretty_print_status: Optional[bool] = False): """Manage Kibana Process Args: stdout: Print output to console verbose: Include detailed debug messages pretty_print_status: If enabled, status will be printed in a tabulated style Returns: None """ environ = utilities.get_environment_file_dict() process.BaseProcessManager.__init__( self, 'kibana.service', 'kibana.process', log_path=environ.get('KIBANA_LOGS'), stdout=stdout, verbose=verbose, pretty_print_status=pretty_print_status) if not kibana_profile.ProcessProfiler().is_installed(): self.logger.error( "Kibana is not installed. Install it with 'dynamite kibana install -h'" ) raise CallKibanaProcessError("Kibana is not installed.")
def _install_kibana_objects(self): self.logger.info('Installing Kibana Dashboards') self.logger.info('Waiting for ElasticSearch to become accessible.') # Start ElasticSearch if it is installed locally and is not running if self.elasticsearch_host in ['localhost', '127.0.0.1', '0.0.0.0', '::1', '::/128']: self.logger.info('Starting ElasticSearch.') elastic_process.ProcessManager().start() while not elastic_profile.ProcessProfiler().is_listening(): self.logger.info('Waiting for ElasticSearch API to become accessible.') time.sleep(5) self.logger.info('ElasticSearch API is up.') self.logger.info('Sleeping for 5 seconds, while ElasticSearch API finishes booting.') time.sleep(5) try: kibana_proc = kibana_process.ProcessManager() kibana_proc.optimize() utilities.set_ownership_of_file(self.install_directory, user='******', group='dynamite') utilities.set_ownership_of_file(self.configuration_directory, user='******', group='dynamite') time.sleep(5) self.logger.info('Starting Kibana.') kibana_proc.start() except Exception as e: raise kibana_exceptions.InstallKibanaError("General error while starting Kibana process; {}".format(e)) kibana_api_start_attempts = 0 while not kibana_profile.ProcessProfiler().is_listening() and kibana_api_start_attempts != 5: self.logger.info('Waiting for Kibana API to become accessible.') kibana_api_start_attempts += 1 time.sleep(5) if kibana_api_start_attempts == 5: self.logger.error('Kibana API could not be started after {} attempts.'.format(kibana_api_start_attempts)) raise kibana_exceptions.InstallKibanaError( "Kibana API could not be started after {} attempts.".format(kibana_api_start_attempts)) self.logger.info('Kibana API is up.') self.logger.info('Sleeping for 10 seconds, while Kibana API finishes booting.') time.sleep(10) api_config = kibana_configs.ApiConfigManager(self.configuration_directory) kibana_object_create_attempts = 1 while kibana_object_create_attempts != 5: try: self.logger.info('[Attempt {}] Attempting to install dashboards/visualizations.'.format( kibana_object_create_attempts)) api_config.create_dynamite_kibana_objects() break except kibana_exceptions.CreateKibanaObjectsError: kibana_object_create_attempts += 1 time.sleep(10) if kibana_object_create_attempts == 5: self.logger.error( "Kibana objects could not be created after {} attempts".format(kibana_object_create_attempts)) raise kibana_exceptions.InstallKibanaError( "Kibana objects could not be created after {} attempts".format(kibana_object_create_attempts)) self.logger.info('Successfully created dashboards/visualizations.') kibana_proc.stop()
def change_kibana_elasticsearch_password(password='******', prompt_user=True, stdout=True, verbose=False): """ Change the password used by Kibana to authenticate to ElasticSearch :param password: The new Elasticsearch password :param prompt_user: If True, warning prompt is displayed before proceeding :param stdout: Print status to stdout :param verbose: Include detailed debug messages """ from dynamite_nsm.services.kibana import process as kibana_process from dynamite_nsm.services.kibana import profile as kibana_profile log_level = logging.INFO if verbose: log_level = logging.DEBUG logger = get_logger('KIBANA', level=log_level, stdout=stdout) environment_variables = utilities.get_environment_file_dict() if not kibana_profile.ProcessProfiler().is_installed(): logger.error( "Password reset failed. Kibana is not installed on this host.") if prompt_user: resp = utilities.prompt_input( '\033[93m[-] WARNING! Changing the Kibana password can cause Kibana to lose communication with ' 'ElasticSearch.\n[?] Are you sure you wish to continue? [no]|yes):\033[0m ' ) while resp not in ['', 'no', 'yes']: resp = utilities.prompt_input( '\033[93m[?] Are you sure you wish to continue? ([no]|yes):\033[0m ' ) if resp != 'yes': if stdout: sys.stdout.write('\n[+] Exiting\n') exit(0) try: kb_config = ConfigManager( environment_variables.get('KIBANA_PATH_CONF')) kb_config.elasticsearch_password = password kb_config.write_config() except (kibana_exceptions.ReadKibanaConfigError, kibana_exceptions.WriteKibanaConfigError): logger.error("Could not read/write Kibana configuration.") raise general_exceptions.ResetPasswordError( "Could not read/write Kibana configuration.") kibana_process.ProcessManager().restart()
def __init__(self, prompt_user, stdout, verbose): execution_strategy.BaseExecStrategy.__init__( self, strategy_name="monitor_uninstall", strategy_description="Uninstall Monitor.", functions=( utilities.create_dynamite_environment_file, prompt_monitor_uninstall, ), arguments=( # utilities.create_dynamite_environment_file {}, # prompt_user { "prompt_user": bool(prompt_user), "stdout": bool(stdout) }, ), return_formats=(None, None)) if kb_profile.ProcessProfiler().is_installed(): self.add_function(func=kb_install.uninstall_kibana, argument_dict={ 'prompt_user': False, 'stdout': bool(stdout), 'verbose': bool(verbose) }) if ls_profile.ProcessProfiler().is_installed(): self.add_function(func=ls_install.uninstall_logstash, argument_dict={ 'prompt_user': False, 'stdout': bool(stdout), 'verbose': bool(verbose) }) if es_profile.ProcessProfiler().is_installed(): self.add_function(func=es_install.uninstall_elasticsearch, argument_dict={ 'prompt_user': False, 'stdout': bool(stdout), 'verbose': bool(verbose) }) self.add_function(func=log_message, argument_dict={ "msg": '*** Monitor uninstalled successfully. ***', 'stdout': bool(stdout), 'verbose': bool(verbose) })
def stop(self) -> bool: """Stop the monitor services Returns: True, if successfully stopped """ kibana_res, logstash_res, elasticsearch_res = True, True, True if not elasticsearch_profile.ProcessProfiler().is_installed(): self.logger.error('You must install kibana to run this command.') return False elasticsearch_res = elasticsearch_process.ProcessManager().stop() if logstash_profile.ProcessProfiler().is_installed(): logstash_res = logstash_process.ProcessManager().stop() if kibana_profile.ProcessProfiler().is_installed(): kibana_res = kibana_process.ProcessManager().stop() return kibana_res and elasticsearch_res and logstash_res
def install_kibana(install_directory, configuration_directory, log_directory, host='0.0.0.0', port=5601, elasticsearch_host='localhost', elasticsearch_port=9200, elasticsearch_password='******', create_dynamite_user=True, stdout=False, verbose=False): """ Install Kibana/ElastiFlow/Synesis Dashboards :param install_directory: Path to the install directory (E.G /opt/dynamite/kibana/) :param configuration_directory: Path to the configuration directory (E.G /etc/dynamite/kibana/) :param log_directory: Path to the log directory (E.G /var/log/dynamite/kibana/) :param host: The IP address to listen on (E.G "0.0.0.0") :param port: The port that the Kibana UI/API is bound to (E.G 5601) :param elasticsearch_host: A hostname/IP of the target ElasticSearch instance :param elasticsearch_port: A port number for the target ElasticSearch instance :param elasticsearch_password: The password used for authentication across all builtin ES users :param create_dynamite_user: Automatically create the 'dynamite' user, who has privs to run Logstash/ElasticSearch/Kibana :param stdout: Print the output to console :param verbose: Include output from system utilities """ log_level = logging.INFO if verbose: log_level = logging.DEBUG logger = get_logger('KIBANA', level=log_level, stdout=stdout) kb_profiler = kibana_profile.ProcessProfiler() if kb_profiler.is_installed(): logger.error('Kibana is already installed. If you wish to re-install, first uninstall.') raise kibana_exceptions.AlreadyInstalledKibanaError() if utilities.get_memory_available_bytes() < 2 * (1000 ** 3): sys.stderr.write('\n\033[93m[-] WARNING! Kibana should have at-least 2GB to run ' 'currently available [{} GB]\033[0m\n'.format( utilities.get_memory_available_bytes() / (1000 ** 3))) if str(utilities.prompt_input('\033[93m[?] Continue? [y|N]:\033[0m ')).lower() != 'y': sys.stdout.write('\n[+] Exiting\n') exit(0) kb_installer = InstallManager(install_directory, configuration_directory, log_directory, host=host, port=port, elasticsearch_host=elasticsearch_host, elasticsearch_port=elasticsearch_port, elasticsearch_password=elasticsearch_password, download_kibana_archive=not kb_profiler.is_downloaded(), stdout=stdout, verbose=verbose) if create_dynamite_user: utilities.create_dynamite_user(utilities.generate_random_password(50)) kb_installer.setup_kibana()
def uninstall(self): from dynamite_nsm.services.elasticsearch import profile as elasticsearch_profile from dynamite_nsm.services.logstash import profile as logstash_profile from dynamite_nsm.services.kibana import profile as kibana_profile if elasticsearch_profile.ProcessProfiler().is_installed(): elasticsearch_install.UninstallManager( purge_config=True, stdout=self.stdout, verbose=self.verbose).uninstall() if logstash_profile.ProcessProfiler().is_installed(): logstash_install.UninstallManager( purge_config=True, stdout=self.stdout, verbose=self.verbose).uninstall() if kibana_profile.ProcessProfiler().is_installed(): kibana_install.UninstallManager(purge_config=True, stdout=self.stdout, verbose=self.verbose).uninstall()
def __init__(self, old_password, new_password, stdout, verbose): execution_strategy.BaseExecStrategy.__init__( self, strategy_name="monitor_change_password", strategy_description= "Change the password for all monitor components.", ) if es_profile.ProcessProfiler().is_installed(): self.add_function(func=es_config.change_elasticsearch_password, argument_dict={ 'old_password': str(old_password), 'password': str(new_password), 'prompt_user': False, 'stdout': bool(stdout), 'verbose': bool(verbose) }) if ls_profile.ProcessProfiler().is_installed(): self.add_function( func=ls_config.change_logstash_elasticsearch_password, argument_dict={ 'password': str(new_password), 'prompt_user': False, 'stdout': bool(stdout), 'verbose': bool(verbose) }) if kb_profile.ProcessProfiler().is_installed(): self.add_function( func=kb_config.change_kibana_elasticsearch_password, argument_dict={ 'password': str(new_password), 'prompt_user': False, 'stdout': bool(stdout), 'verbose': bool(verbose) }) self.add_function(func=log_message, argument_dict={ 'msg': 'Monitor passwords changed successfully!', 'stdout': bool(stdout), 'verbose': bool(verbose) })
def __init__(self, stdout=True, verbose=False, pretty_print_status=False): environ = utilities.get_environment_file_dict() try: process.BaseProcessManager.__init__( self, 'kibana.service', 'kibana', log_path=environ.get('KIBANA_LOGS'), pid_file=os.path.join(PID_DIRECTORY, 'kibana.pid'), stdout=stdout, verbose=verbose, pretty_print_status=pretty_print_status) except general_exceptions.CallProcessError: self.logger.error("Could not find systemctl on this system.") raise kibana_exceptions.CallKibanaProcessError( "Could not find systemctl.") if not kibana_profile.ProcessProfiler().is_installed(): self.logger.error( "Kibana is not installed. Install it with 'dynamite kibana install -h'" ) raise kibana_exceptions.CallKibanaProcessError( "Kibana is not installed.")
def uninstall_kibana(prompt_user=True, stdout=True, verbose=False): """ Uninstall Kibana/ElastiFlow/Synesis Dashboards :param prompt_user: Print a warning before continuing :param stdout: Print the output to console :param verbose: Include detailed debug messages """ log_level = logging.INFO if verbose: log_level = logging.DEBUG logger = get_logger('KIBANA', level=log_level, stdout=stdout) env_file = os.path.join(const.CONFIG_PATH, 'environment') environment_variables = utilities.get_environment_file_dict() kb_profiler = kibana_profile.ProcessProfiler() if not kb_profiler.is_installed(): raise kibana_exceptions.UninstallKibanaError("Kibana is not installed.") configuration_directory = environment_variables.get('KIBANA_PATH_CONF') kb_config = kibana_configs.ConfigManager(configuration_directory) if prompt_user: sys.stderr.write( '\n\033[93m[-] WARNING! Removing Kibana will uninstall all visualizations and saved searches previously ' 'created.\033[0m\n') resp = utilities.prompt_input('\033[93m[?] Are you sure you wish to continue? ([no]|yes):\033[0m ') while resp not in ['', 'no', 'yes']: resp = utilities.prompt_input('\n\033[93m[?] Are you sure you wish to continue? ([no]|yes):\033[0m ') if resp != 'yes': if stdout: sys.stdout.write('\n[+] Exiting\n') exit(0) if kb_profiler.is_running(): kibana_process.ProcessManager().stop() try: shutil.rmtree(kb_config.kibana_path_conf) shutil.rmtree(kb_config.kibana_home) shutil.rmtree(kb_config.kibana_logs) shutil.rmtree(const.INSTALL_CACHE, ignore_errors=True) env_lines = '' with open(env_file) as env_fr: for line in env_fr.readlines(): if 'KIBANA_PATH_CONF' in line: continue elif 'KIBANA_HOME' in line: continue elif 'KIBANA_LOGS' in line: continue elif line.strip() == '': continue env_lines += line.strip() + '\n' with open(env_file, 'w') as env_fw: env_fw.write(env_lines) except Exception as e: logger.error("General error occurred while attempting to uninstall Kibana.".format(e)) logger.debug("General error occurred while attempting to uninstall Kibana; {}".format(e)) raise kibana_exceptions.UninstallKibanaError( "General error occurred while attempting to uninstall kibana; {}".format(e)) try: sysctl = systemctl.SystemCtl() except general_exceptions.CallProcessError: raise kibana_exceptions.UninstallKibanaError("Could not find systemctl.") sysctl.uninstall_and_disable('kibana')
def status(self) -> Optional[Union[Dict, str]]: """Get the statuses of monitor services Returns: The statuses of monitor services """ agent_status = {} kibana_status, elasticsearch_status, logstash_status = {}, {}, {} if not elasticsearch_profile.ProcessProfiler().is_installed(): self.logger.error( 'You must install elasticsearch to run this command.') return None elasticsearch_status = elasticsearch_process.ProcessManager().status() agent_status.update({ 'elasticsearch': { 'running': elasticsearch_status.get('running'), 'enabled_on_startup': elasticsearch_status.get('enabled_on_startup') } }) if logstash_profile.ProcessProfiler().is_installed(): logstash_status = logstash_process.ProcessManager().status() agent_status.update({ 'logstash': { 'running': logstash_status.get('running'), 'enabled_on_startup': logstash_status.get('enabled_on_startup') } }) if kibana_profile.ProcessProfiler().is_installed(): kibana_status = kibana_process.ProcessManager().status() agent_status.update({ 'kibana': { 'running': kibana_status.get('running'), 'enabled_on_startup': kibana_status.get('enabled_on_startup') } }) if self.pretty_print_status: colorize = utilities.PrintDecorations.colorize child_services = [ ['Service', 'Running', 'Enabled on Startup'], [ 'kibana', colorize('yes', 'green') if kibana_status.get('running') else colorize('no', 'red'), colorize('yes', 'green') if kibana_status.get('enabled_on_startup') else colorize( 'no', 'red') ] ] if elasticsearch_status: child_services.append([ 'elasticsearch', colorize('yes', 'green') if elasticsearch_status.get('running') else colorize( 'no', 'red'), colorize('yes', 'green') if elasticsearch_status.get('enabled_on_startup') else colorize('no', 'red') ]) if logstash_status: child_services.append([ 'logstash', colorize('yes', 'green') if elasticsearch_status.get('running') else colorize( 'no', 'red'), colorize('yes', 'green') if elasticsearch_status.get('enabled_on_startup') else colorize('no', 'red') ]) return tabulate.tabulate(child_services, tablefmt='fancy_grid') return agent_status
def __init__(self, logstash_listen_address, kibana_listen_address, kibana_listen_port, elasticsearch_host, elasticsearch_port, elasticsearch_password, elasticsearch_heap_size_gigs, logstash_heap_size_gigs, install_jdk, stdout, verbose): execution_strategy.BaseExecStrategy.__init__( self, strategy_name="monitor_install", strategy_description= "Install ElasticSearch, LogStash, and Kibana on the same instance.", functions=(utilities.create_dynamite_environment_file, ), arguments=({}, ), return_formats=(None, )) self.add_function(func=remove_elasticsearch_tar_archive, argument_dict={}, return_format=None) self.add_function(func=remove_logstash_tar_archive, argument_dict={}, return_format=None) self.add_function(func=remove_kibana_tar_archive, argument_dict={}, return_format=None) if not es_profile.ProcessProfiler().is_installed(): self.add_function(func=es_install.install_elasticsearch, argument_dict={ "configuration_directory": "/etc/dynamite/elasticsearch/", "install_directory": "/opt/dynamite/elasticsearch/", "log_directory": "/var/log/dynamite/elasticsearch/", "password": str(elasticsearch_password), "heap_size_gigs": int(elasticsearch_heap_size_gigs), "install_jdk": bool(install_jdk), "create_dynamite_user": True, "stdout": bool(stdout), "verbose": bool(verbose) }, return_format=None) else: self.add_function( func=log_message, argument_dict={ "msg": 'Skipping ElasticSearch installation; already installed.', 'stdout': bool(stdout), 'verbose': bool(verbose) }, return_format=None) self.add_function(func=es_process.start, argument_dict={"stdout": False}, return_format=None) if not ls_profile.ProcessProfiler().is_installed(): self.add_function(func=ls_install.install_logstash, argument_dict={ "configuration_directory": "/etc/dynamite/logstash/", "install_directory": "/opt/dynamite/logstash/", "log_directory": "/var/log/dynamite/logstash/", "host": str(logstash_listen_address), "elasticsearch_host": str(elasticsearch_host), "elasticsearch_port": int(elasticsearch_port), "elasticsearch_password": str(elasticsearch_password), "heap_size_gigs": int(logstash_heap_size_gigs), "install_jdk": False, "create_dynamite_user": False, "stdout": bool(stdout), "verbose": bool(verbose) }, return_format=None) else: self.add_function( func=log_message, argument_dict={ "msg": 'Skipping LogStash installation; already installed.', 'stdout': bool(stdout), 'verbose': bool(verbose) }, return_format=None) if not kb_profile.ProcessProfiler().is_installed(): self.add_function(func=kb_install.install_kibana, argument_dict={ "configuration_directory": "/etc/dynamite/kibana/", "install_directory": "/opt/dynamite/kibana/", "log_directory": "/var/log/dynamite/kibana/", "host": str(kibana_listen_address), "port": int(kibana_listen_port), "elasticsearch_host": str(elasticsearch_host), "elasticsearch_port": int(elasticsearch_port), "elasticsearch_password": str(elasticsearch_password), "create_dynamite_user": True, "stdout": bool(stdout), "verbose": bool(verbose) }, return_format=None) else: self.add_function( func=log_message, argument_dict={ "msg": 'Skipping Kibana installation; already installed.', 'stdout': bool(stdout), 'verbose': bool(verbose) }, return_format=None) self.add_function(func=kb_process.stop, argument_dict={"stdout": False}, return_format=None) self.add_function(func=es_process.stop, argument_dict={"stdout": False}, return_format=None) self.add_function(func=log_message, argument_dict={ "msg": '*** Monitor installed successfully. ***', 'stdout': bool(stdout), 'verbose': bool(verbose) }, return_format=None) self.add_function( func=log_message, argument_dict={ "msg": 'Next, Start your monitor: ' '\'dynamite monitor start\'. It will be available at: \033[4m{}:{}\033[0m once started.' ''.format(kibana_listen_address, kibana_listen_port), 'stdout': bool(stdout), 'verbose': bool(verbose) }, return_format=None)