Files
DetectionLab/Vagrant/resources/malcolm/scripts/beats/beat_common.py
2021-08-06 10:35:01 +02:00

622 lines
25 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Battelle Energy Alliance, LLC. All rights reserved.
from __future__ import print_function
import getpass
import inspect
import os
import platform
import re
import sys
import time
from collections import defaultdict
from subprocess import (PIPE, STDOUT, Popen, CalledProcessError)
###################################################################################################
ScriptPath = os.path.dirname(os.path.realpath(__file__))
###################################################################################################
# python 2/3 portability
PY3 = (sys.version_info.major >= 3)
# bind raw_input to input in older versions of python
try:
input = raw_input
except NameError:
pass
try:
FileNotFoundError
except NameError:
FileNotFoundError = IOError
###################################################################################################
PLATFORM_WINDOWS = "Windows"
PLATFORM_MAC = "Darwin"
PLATFORM_LINUX = "Linux"
PLATFORM_LINUX_CENTOS = 'centos'
PLATFORM_LINUX_DEBIAN = 'debian'
PLATFORM_LINUX_FEDORA = 'fedora'
PLATFORM_LINUX_UBUNTU = 'ubuntu'
OPERATION_RUN = 'run'
OPERATION_CONFIGURE = 'config'
BEAT_ES_HOST = "BEAT_ES_HOST"
BEAT_ES_PROTOCOL = "BEAT_ES_PROTOCOL"
BEAT_ES_SSL_VERIFY = "BEAT_ES_SSL_VERIFY"
BEAT_HTTP_PASSWORD = "BEAT_HTTP_PASSWORD"
BEAT_HTTP_USERNAME = "BEAT_HTTP_USERNAME"
BEAT_KIBANA_DASHBOARDS_ENABLED = "BEAT_KIBANA_DASHBOARDS_ENABLED"
BEAT_KIBANA_DASHBOARDS_PATH = "BEAT_KIBANA_DASHBOARDS_PATH"
BEAT_KIBANA_HOST = "BEAT_KIBANA_HOST"
BEAT_KIBANA_PROTOCOL = "BEAT_KIBANA_PROTOCOL"
BEAT_KIBANA_SSL_VERIFY = "BEAT_KIBANA_SSL_VERIFY"
BEAT_YML_TEMPLATE = """
#================================ General ======================================
fields_under_root: true
#================================ Outputs ======================================
#-------------------------- Elasticsearch output -------------------------------
output.elasticsearch:
enabled: true
hosts: ["${BEAT_ES_HOST}"]
protocol: "${BEAT_ES_PROTOCOL}"
username: "${BEAT_HTTP_USERNAME}"
password: "${BEAT_HTTP_PASSWORD}"
ssl.verification_mode: "${BEAT_ES_SSL_VERIFY}"
setup.template.enabled: true
setup.template.overwrite: false
setup.template.settings:
index.number_of_shards: 1
index.number_of_replicas: 0
#============================== Dashboards =====================================
setup.dashboards.enabled: "${BEAT_KIBANA_DASHBOARDS_ENABLED}"
setup.dashboards.directory: "${BEAT_KIBANA_DASHBOARDS_PATH}"
#============================== Kibana =====================================
setup.kibana:
host: "${BEAT_KIBANA_HOST}"
protocol: "${BEAT_KIBANA_PROTOCOL}"
username: "${BEAT_HTTP_USERNAME}"
password: "${BEAT_HTTP_PASSWORD}"
ssl.verification_mode: "${BEAT_KIBANA_SSL_VERIFY}"
#================================ Logging ======================================
logging.metrics.enabled: false
"""
###################################################################################################
# print to stderr
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
###################################################################################################
# get interactive user response to Y/N question
def YesOrNo(question, default=None, forceInteraction=False, acceptDefault=False):
if default == True:
questionStr = "\n{} (Y/n): ".format(question)
elif default == False:
questionStr = "\n{} (y/N): ".format(question)
else:
questionStr = "\n{} (y/n): ".format(question)
if acceptDefault and (default is not None) and (not forceInteraction):
reply = ''
else:
while True:
reply = str(input(questionStr)).lower().strip()
if (len(reply) > 0) or (default is not None):
break
if (len(reply) == 0):
reply = 'y' if default else 'n'
if reply[0] == 'y':
return True
elif reply[0] == 'n':
return False
else:
return YesOrNo(question, default=default)
###################################################################################################
# get interactive user response
def AskForString(question, default=None, forceInteraction=False, acceptDefault=False):
if acceptDefault and (default is not None) and (not forceInteraction):
reply = default
else:
reply = str(input('\n{}: '.format(question))).strip()
return reply
###################################################################################################
# get interactive password (without echoing)
def AskForPassword(prompt):
reply = getpass.getpass(prompt=prompt)
return reply
###################################################################################################
# convenient boolean argument parsing
def str2bool(v):
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise ValueError('Boolean value expected')
###################################################################################################
# determine if a program/script exists and is executable in the system path
def Which(cmd, debug=False):
result = any(os.access(os.path.join(path, cmd), os.X_OK) for path in os.environ["PATH"].split(os.pathsep))
if (not result) and (platform.system() == PLATFORM_WINDOWS):
result = os.access(os.path.join(os.getcwd(), cmd), os.X_OK)
if debug:
eprint("Which {} returned {}".format(cmd, result))
return result
###################################################################################################
# run command with arguments and return its exit code, stdout, and stderr
def check_output_input(*popenargs, **kwargs):
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden')
if 'stderr' in kwargs:
raise ValueError('stderr argument not allowed, it will be overridden')
if 'input' in kwargs and kwargs['input']:
if 'stdin' in kwargs:
raise ValueError('stdin and input arguments may not both be used')
inputdata = kwargs['input']
kwargs['stdin'] = PIPE
else:
inputdata = None
kwargs.pop('input', None)
process = Popen(*popenargs, stdout=PIPE, stderr=PIPE, **kwargs)
try:
output, errput = process.communicate(inputdata)
except:
process.kill()
process.wait()
raise
retcode = process.poll()
return retcode, output, errput
###################################################################################################
# run command with arguments and return its exit code, stdout, and stderr
def run_process(command, stdout=True, stderr=True, stdin=None, retry=0, retrySleepSec=5, cwd=None, env=None, debug=False):
retcode = -1
output = []
try:
# run the command
retcode, cmdout, cmderr = check_output_input(command, input=stdin.encode() if (PY3 and stdin) else stdin, cwd=cwd, env=env)
# split the output on newlines to return a list
if PY3:
if stderr and (len(cmderr) > 0): output.extend(cmderr.decode(sys.getdefaultencoding()).split('\n'))
if stdout and (len(cmdout) > 0): output.extend(cmdout.decode(sys.getdefaultencoding()).split('\n'))
else:
if stderr and (len(cmderr) > 0): output.extend(cmderr.split('\n'))
if stdout and (len(cmdout) > 0): output.extend(cmdout.split('\n'))
except (FileNotFoundError, OSError, IOError) as e:
if stderr:
output.append("Command {} not found or unable to execute".format(command))
if debug:
eprint("{}{} returned {}: {}".format(command, "({})".format(stdin[:80] + bool(stdin[80:]) * '...' if stdin else ""), retcode, output))
if (retcode != 0) and retry and (retry > 0):
# sleep then retry
time.sleep(retrySleepSec)
return run_process(command, stdout, stderr, stdin, retry-1, retrySleepSec, cwd, env, debug)
else:
return retcode, output
###################################################################################################
class Beatbox(object):
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def __init__(self, debug=False, ymlFileSpec=None, beatName=None, acceptDefaults=False):
self.debug = debug
self.acceptDefaults = acceptDefaults
self.platform = platform.system()
self.ymlFileSpec = ymlFileSpec
self.ymlFilePath = os.path.dirname(ymlFileSpec)
self.beatName = beatName
self.beatExe = beatName
self.beatInstallDir = None
self.defaultKibanaDashboardDir = None
self.keystoreItems = defaultdict(str)
for initItem in [BEAT_ES_HOST,
BEAT_ES_PROTOCOL,
BEAT_ES_SSL_VERIFY,
BEAT_HTTP_PASSWORD,
BEAT_HTTP_USERNAME,
BEAT_KIBANA_DASHBOARDS_ENABLED,
BEAT_KIBANA_DASHBOARDS_PATH,
BEAT_KIBANA_HOST,
BEAT_KIBANA_PROTOCOL,
BEAT_KIBANA_SSL_VERIFY]:
self.keystoreItems[initItem] = ''
self.keystorePath = None
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def __del__(self):
# nothing for now
pass
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def run_process(self, command, stdout=True, stderr=True, stdin=None, retry=0, retrySleepSec=5):
return run_process(command, stdout=stdout, stderr=stderr, stdin=stdin, retry=retry, retrySleepSec=retrySleepSec, debug=self.debug)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def build_beat_command(self, command):
if not Which(self.beatExe, debug=self.debug):
raise Exception("Beat executable {} does not exist".format(self.beatExe))
if not os.path.isfile(self.ymlFileSpec):
raise Exception("Beat configuration {} does not exist".format(self.ymlFileSpec))
# convert paths to absolutes
ymlFileSpec = os.path.abspath(self.ymlFileSpec)
ymlFilePath = os.path.dirname(ymlFileSpec)
beatCmd = [self.beatExe, '--path.home', ymlFilePath, '--path.config', ymlFilePath, '--path.data', ymlFilePath if (self.platform == PLATFORM_WINDOWS) else os.path.join(ymlFilePath, 'data'), '--path.logs', os.path.join(ymlFilePath, 'logs'), '-c', ymlFileSpec, '-E', "keystore.path='{}'".format(self.keystorePath)]
return beatCmd + command if isinstance(command, list) else beatCmd + [ command ]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def run_beat_command(self, command, stdout=True, stderr=True, stdin=None, retry=0, retrySleepSec=5):
return self.run_process(self.build_beat_command(command), stdout=stdout, stderr=stderr, stdin=stdin, retry=retry, retrySleepSec=retrySleepSec)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_beat_yml(self):
if self.debug:
eprint("{}: {}".format(self.__class__.__name__, inspect.currentframe().f_code.co_name))
if (self.ymlFileSpec is not None):
if os.path.isfile(self.ymlFileSpec):
# if it doesn't look like connectivity stuff (at last BEAT_ES_PROTOCOL) is in the YML file, offer to append it
if ((len(list(filter(lambda x: BEAT_ES_PROTOCOL in x, [line.rstrip('\n') for line in open(self.ymlFileSpec)]))) == 0) and
YesOrNo("Append connectivity boilerplate to {}?".format(self.ymlFileSpec), default=False, acceptDefault=self.acceptDefaults)):
with open(self.ymlFileSpec, 'a') as ymlFile:
ymlFile.write(BEAT_YML_TEMPLATE)
else:
# generate a boilerplate spec file (output configured, no modules) if the YML file doesn't exist
with open(self.ymlFileSpec, 'w') as ymlFile:
ymlFile.write(BEAT_YML_TEMPLATE)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_keystore(self):
if self.debug:
eprint("{}: {}".format(self.__class__.__name__, inspect.currentframe().f_code.co_name))
# check if keystore already exists
err, out = self.run_beat_command(['keystore', 'list'])
if (err == 0) and (len(out) > 0):
if not YesOrNo("{} keystore already exists, overwrite?".format(self.beatName), default=False, acceptDefault=self.acceptDefaults):
raise Exception("Configuration cancelled by user")
# create keystore
err, out = self.run_beat_command(['keystore', 'create', '--force'])
if (err == 0):
eprint('\n'.join(out))
else:
raise Exception("Keystore creation failed: {}".format(out))
# prompt for and store configuration items
for destination in ['Elasticsearch', 'Kibana']:
if YesOrNo("Configure {} {} connectivity?".format(self.beatName, destination), default=True, acceptDefault=self.acceptDefaults):
# protocol
tmpVal, tmpDefault = '', 'https'
while tmpVal not in ['http', 'https']:
tmpVal = AskForString("Enter {} connection protocol (http or https) [{}]".format(destination, tmpDefault), default=tmpDefault, acceptDefault=self.acceptDefaults).lower()
if (len(tmpVal) == 0): tmpVal = tmpDefault
self.keystoreItems[BEAT_ES_PROTOCOL.replace('_ES_', '_KIBANA_' if (destination == 'Kibana') else '_ES_')] = tmpVal
# SSL verification
tmpVal, tmpDefault = '', 'none'
while tmpVal not in ['none', 'full']:
tmpVal = AskForString("Enter {} SSL verification (none (for self-signed certificates) or full) [{}]".format(destination, tmpDefault), default=tmpDefault, acceptDefault=self.acceptDefaults).lower()
if (len(tmpVal) == 0): tmpVal = tmpDefault
self.keystoreItems[BEAT_ES_SSL_VERIFY.replace('_ES_', '_KIBANA_' if (destination == 'Kibana') else '_ES_')] = tmpVal
# host
tmpVal, tmpDefault = '', ''
while (len(tmpVal) == 0):
tmpVal = AskForString("Enter {} connection host".format(destination), default=tmpDefault, acceptDefault=self.acceptDefaults)
self.keystoreItems[BEAT_ES_HOST.replace('_ES_', '_KIBANA_' if (destination == 'Kibana') else '_ES_')] = tmpVal
if (BEAT_KIBANA_HOST in self.keystoreItems):
# configure kibana dashboards
if YesOrNo("Configure {} Kibana dashboards?".format(self.beatName), default=True, acceptDefault=self.acceptDefaults):
self.keystoreItems[BEAT_KIBANA_DASHBOARDS_ENABLED] = 'true'
# kibana dashboards
tmpVal, tmpDefault = '', self.defaultKibanaDashboardDir
while (len(tmpVal) == 0):
tmpVal = AskForString("Enter directory containing Kibana dashboards [{}]".format(tmpDefault), default=tmpDefault, acceptDefault=self.acceptDefaults)
if (len(tmpVal) == 0): tmpVal = tmpDefault
self.keystoreItems[BEAT_KIBANA_DASHBOARDS_PATH] = tmpVal
# username
tmpVal, tmpDefault = '', ''
while (len(tmpVal) == 0):
tmpVal = AskForString("Enter HTTP/HTTPS server username", default=tmpDefault, acceptDefault=self.acceptDefaults)
self.keystoreItems[BEAT_HTTP_USERNAME] = tmpVal
# password
tmpVal, tmpValConfirm = '', 'xxxx'
while (len(tmpVal) == 0) and (tmpVal != tmpValConfirm):
tmpVal = AskForPassword("Enter password for {}: ".format(self.keystoreItems[BEAT_HTTP_USERNAME]))
tmpValConfirm = AskForPassword("Enter password for {} (again): ".format(self.keystoreItems[BEAT_HTTP_USERNAME]))
if (tmpVal != tmpValConfirm):
eprint('Passwords do not match')
tmpVal, tmpValConfirm = '', 'xxxx'
self.keystoreItems[BEAT_HTTP_PASSWORD] = tmpVal
# write values to keystore
for key, value in self.keystoreItems.items():
err, out = self.run_beat_command(['keystore', 'add', key, '--stdin', '--force'], stdin=value)
if (err != 0):
raise Exception("Failed to add {} to {} keystore: {}".format(key, self.beatName, out))
# list keystore
err, out = self.run_beat_command(['keystore', 'list'])
if (err == 0):
eprint('Generated keystore for {}'.format(self.beatName))
eprint('\n'.join(out))
else:
raise Exception("Failed to enumerate keystore: {}".format(out))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def beat_run(self):
if self.debug:
eprint("{}: {}".format(self.__class__.__name__, inspect.currentframe().f_code.co_name))
process = Popen(self.build_beat_command(['run', '-e']), stdout=PIPE)
while True:
output = process.stdout.readline()
if (len(output) == 0) and (process.poll() is not None):
break
if output:
print(output.decode().strip())
else:
time.sleep(0.5)
process.poll()
###################################################################################################
class LinuxBeatbox(Beatbox):
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def __init__(self, debug=False, ymlFileSpec=None, beatName=None):
if PY3:
super().__init__(debug=debug, ymlFileSpec=ymlFileSpec, beatName=beatName)
else:
super(LinuxBeatbox, self).__init__(debug=debug, ymlFileSpec=ymlFileSpec, beatName=beatName)
if not Which(self.beatExe, debug=self.debug):
self.beatExe = self.beatExe.lower() if (self.beatExe is not None) else self.beatName.lower()
self.beatInstallDir = "/usr/share/{}".format(self.beatName)
self.defaultKibanaDashboardDir = os.path.join(self.beatInstallDir, 'kibana')
self.keystorePath = os.path.join(os.path.join(os.path.dirname(os.path.abspath(self.ymlFileSpec)), 'data'), "{}.keystore".format(self.beatName))
self.distro = None
self.codename = None
self.release = None
# determine the distro (e.g., ubuntu) and code name (e.g., bionic) if applicable
# check /etc/os-release values first
if os.path.isfile('/etc/os-release'):
osInfo = dict()
with open("/etc/os-release", 'r') as f:
for line in f:
try:
k, v = line.rstrip().split("=")
osInfo[k] = v.strip('"')
except:
pass
if ('NAME' in osInfo) and (len(osInfo['NAME']) > 0):
distro = osInfo['NAME'].lower().split()[0]
if ('VERSION_CODENAME' in osInfo) and (len(osInfo['VERSION_CODENAME']) > 0):
codename = osInfo['VERSION_CODENAME'].lower().split()[0]
if ('VERSION_ID' in osInfo) and (len(osInfo['VERSION_ID']) > 0):
release = osInfo['VERSION_ID'].lower().split()[0]
# try lsb_release next
if (self.distro is None):
err, out = self.run_process(['lsb_release', '-is'], stderr=False)
if (err == 0) and (len(out) > 0):
self.distro = out[0].lower()
if (self.codename is None):
err, out = self.run_process(['lsb_release', '-cs'], stderr=False)
if (err == 0) and (len(out) > 0):
self.codename = out[0].lower()
if (self.release is None):
err, out = self.run_process(['lsb_release', '-rs'], stderr=False)
if (err == 0) and (len(out) > 0):
self.release = out[0].lower()
# try release-specific files
if (self.distro is None):
if os.path.isfile('/etc/centos-release'):
distroFile = '/etc/centos-release'
if os.path.isfile('/etc/redhat-release'):
distroFile = '/etc/redhat-release'
elif os.path.isfile('/etc/issue'):
distroFile = '/etc/issue'
else:
distroFile = None
if (distroFile is not None):
with open(distroFile, 'r') as f:
distroVals = f.read().lower().split()
distroNums = [x for x in distroVals if x[0].isdigit()]
self.distro = distroVals[0]
if (self.release is None) and (len(distroNums) > 0):
self.release = distroNums[0]
if (self.distro is None):
self.distro = "linux"
if self.debug:
eprint("distro: {}{}{}".format(self.distro,
" {}".format(self.codename) if self.codename else "",
" {}".format(self.release) if self.release else ""))
if not self.codename: self.codename = self.distro
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_beat_yml(self):
if PY3:
super().configure_beat_yml()
else:
super(LinuxBeatbox, self).configure_beat_yml()
localModulePath = os.path.join(os.path.abspath(self.ymlFilePath), 'module')
installedModulePath = os.path.join(self.beatInstallDir, 'module')
if ((not os.path.exists(localModulePath)) and
(os.path.isdir(installedModulePath)) and
YesOrNo("Create symlink to module path {} as {}?".format(installedModulePath, localModulePath), default=True, acceptDefault=self.acceptDefaults)):
os.symlink(installedModulePath, localModulePath)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_keystore(self):
if PY3:
super().configure_keystore()
else:
super(LinuxBeatbox, self).configure_keystore()
pass
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def beat_run(self):
if PY3:
super().beat_run()
else:
super(LinuxBeatbox, self).beat_run()
pass
###################################################################################################
class WindowsBeatbox(Beatbox):
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def __init__(self, debug=False, ymlFileSpec=None, beatName=None):
if PY3:
super().__init__(debug=debug, ymlFileSpec=ymlFileSpec, beatName=beatName)
else:
super(WindowsBeatbox, self).__init__(debug=debug, ymlFileSpec=ymlFileSpec, beatName=beatName)
if not Which(self.beatExe, debug=self.debug):
self.beatExe = self.beatExe + '.exe' if (self.beatExe is not None) else self.beatName + '.exe'
self.beatInstallDir = os.path.abspath(self.ymlFilePath)
self.defaultKibanaDashboardDir = os.path.join(self.beatInstallDir, 'kibana')
self.keystorePath = os.path.join(os.path.dirname(os.path.abspath(self.ymlFileSpec)), "{}.keystore".format(self.beatName))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_beat_yml(self):
if PY3:
super().configure_beat_yml()
else:
super(WindowsBeatbox, self).configure_beat_yml()
pass
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_keystore(self):
if PY3:
super().configure_keystore()
else:
super(WindowsBeatbox, self).configure_keystore()
pass
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def beat_run(self):
if PY3:
super().beat_run()
else:
super(WindowsBeatbox, self).beat_run()
pass
###################################################################################################
class MacBeatbox(Beatbox):
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def __init__(self, debug=False, ymlFileSpec=None, beatName=None):
if PY3:
super().__init__(debug=debug, ymlFileSpec=ymlFileSpec, beatName=beatName)
else:
super(MacBeatbox, self).__init__(debug=debug, ymlFileSpec=ymlFileSpec, beatName=beatName)
if not Which(self.beatExe, debug=self.debug):
self.beatExe = self.beatExe.lower() if (self.beatExe is not None) else self.beatName.lower()
self.beatInstallDir = "/Library/Application Support/elastic/{}".format(self.beatName)
self.defaultKibanaDashboardDir = os.path.join(self.beatInstallDir, 'kibana')
self.keystorePath = os.path.join(os.path.join(os.path.dirname(os.path.abspath(self.ymlFileSpec)), 'data'), "{}.keystore".format(self.beatName))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_beat_yml(self):
if PY3:
super().configure_beat_yml()
else:
super(MacBeatbox, self).configure_beat_yml()
localModulePath = os.path.join(os.path.abspath(self.ymlFilePath), 'module')
installedModulePath = os.path.join(self.beatInstallDir, 'module')
if ((not os.path.exists(localModulePath)) and
(os.path.isdir(installedModulePath)) and
YesOrNo("Create symlink to module path {} as {}?".format(installedModulePath, localModulePath), default=True, acceptDefault=self.acceptDefaults)):
os.symlink(installedModulePath, localModulePath)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_keystore(self):
if PY3:
super().configure_keystore()
else:
super(MacBeatbox, self).configure_keystore()
pass
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def beat_run(self):
if PY3:
super().beat_run()
else:
super(MacBeatbox, self).beat_run()
pass