class QueryRunner(object):
    """ Query Runner.
    a class to handle query to splunkd.
    It grabs a splunkd object according to the splunkrc params provided:
        - If splunkrc is a dictionary, it will create a new splunkd object.
        - If given other object type, it will do do Dependency Injection on _splunkd
    """
    def __init__(self,
                 splunkrc,
                 index_name=INSTRUMENTATION_INDEX_NAME,
                 owner='-',
                 app=INST_APP_NAME,
                 result_reader=QueryRunnerResult):
        self.splunkrc = splunkrc or SPLUNKRC
        self.result_reader = result_reader

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        self._splunkd.namespace['owner'] = owner
        self._splunkd.namespace['app'] = app

        if self._splunkd.has_index(index_name):
            self._index = self._splunkd.get_index(index_name)
        else:
            logging.error('ERROR: INDEX IS NOT AVAILABLE')
            raise (Exception("ERROR INDEX UNAVAILABLE"))

    def search(self, search_cmd, **kwargs):
        """Submit a new search.
        It is a wrapper to the private method _query.
        """
        return self._query(search_cmd, **kwargs)

    def _query(self, search_cmd, **kwargs):
        """Query.

        Note that earliest is inclusive & latest is exclusive:
                                                        [earliest, latest)
        (Prevents getting last-second events again during the next query)
        """
        job = self._splunkd.search(search_cmd, **kwargs)

        while not job.is_done():
            time.sleep(0.2)
        result = self.result_reader(job.results(count=0))
        if hasattr(result, 'job'):
            result.job = job
        return result
예제 #2
0
 def __init__(self,
              splunkd,
              telemetry_conf_service=None,
              server_info_service=None):
     self.splunkd = Splunkd.decorate(splunkd)
     self._telemetry_conf_service = telemetry_conf_service
     self._server_info_service = server_info_service
예제 #3
0
    def __init__(self, splunkrc=None, index_name=None):
        self.splunkrc = splunkrc or SPLUNKRC
        self.socket = None
        self._index = None

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        if index_name:
            if self._splunkd.has_index(index_name):
                self._index = self._splunkd.get_index(index_name)
            else:
                logging.error('ERROR: INDEX IS NOT AVAILABLE')
                raise Exception("ERROR INDEX UNAVAILABLE")
예제 #4
0
        def instrumentation_eligibility(self, optInVersion=None, **kwargs):
            '''
            Determines whether the UI for the instrumentation app should be visible,
            including the initial opt-in modal and all settings/logs pages.
            This is determined by user capabilities, license type, and server roles.
            '''

            cherrypy.response.headers['Content-Type'] = 'application/json'

            services = ServiceBundle(Splunkd(**self.splunkrc()))

            currentOptInVersion = services.telemetry_conf_service.content.get('optInVersion')

            if optInVersion != '*' and optInVersion != currentOptInVersion:
                return json.dumps({
                    'is_eligible': False,
                    'reason': 'UNAUTHORIZED',
                })

            # If we're not running on a free license (where there are no users),
            # first validate that the user has the requisite capabilities.
            if services.server_info_service.content.get('isFree', '0') != '1':
                user = en.getEntity('authentication/users', cherrypy.session['user']['name'])
                if 'edit_telemetry_settings' not in user.properties['capabilities']:
                    return json.dumps({
                        'is_eligible': False,
                        'reason': 'UNAUTHORIZED'
                    })

            # Now check the server roles, etc
            eligibility = client_eligibility.get_ui_eligibility(services)
            return json.dumps(eligibility)
예제 #5
0
def main():
    sleep(INST_PRE_EXECUTE_SLEEP)
    if os.environ['INST_MODE'] == "DEV":
        splunkd = Splunkd(**SPLUNKRC)
    else:
        splunkd = Splunkd(token=os.environ['INST_TOKEN'], server_uri=SPLUNKD_URI)

    services = ServiceBundle(splunkd)
    telemetry_conf_service = services.telemetry_conf_service

    if should_input_run(telemetry_conf_service):
        process_input_params(telemetry_conf_service, args)
        run_input({'start': args.start_date, 'stop': args.stop_date})
    else:
        # indicate to caller that input wasn't executed
        sys.exit(114)
예제 #6
0
    def __connect_to_splunkd(self, search=False):
        if search:
            # WITH NAMESPACE
            splunkrc_copy = {key: self.splunkrc[key] for key in self.splunkrc}
            if 'owner' not in splunkrc_copy:
                splunkrc_copy['owner'] = '-'
            if 'app' not in splunkrc_copy:
                splunkrc_copy['app'] = INST_APP_NAME

            return Splunkd(**splunkrc_copy)
        else:
            splunkrc_copy = {key: self.splunkrc[key] for key in self.splunkrc}

            if 'owner' in splunkrc_copy:
                splunkrc_copy.pop('owner')
            if 'app' in splunkrc_copy:
                splunkrc_copy.pop('app')
            return Splunkd(**self.splunkrc)
예제 #7
0
    def __init__(self, metricSchema, dataPointFactory, splunkrc=None, phase=1):
        self.metricSchema = metricSchema
        self.dataPointFactory = dataPointFactory
        self.splunkrc = splunkrc
        self.profile = get_instance_profile()
        self.phase = phase

        splunkd = Splunkd(**SPLUNKRC)
        services = ServiceBundle(splunkd)
        salt_manager = SaltManager(services)
        self.salt = salt_manager.get_salt()
        self.scheme = {"hash": self.salt}
    def __init__(self,
                 splunkrc,
                 index_name=INSTRUMENTATION_INDEX_NAME,
                 owner='-',
                 app=INST_APP_NAME,
                 result_reader=QueryRunnerResult):
        self.splunkrc = splunkrc or SPLUNKRC
        self.result_reader = result_reader

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        self._splunkd.namespace['owner'] = owner
        self._splunkd.namespace['app'] = app

        if self._splunkd.has_index(index_name):
            self._index = self._splunkd.get_index(index_name)
        else:
            logging.error('ERROR: INDEX IS NOT AVAILABLE')
            raise (Exception("ERROR INDEX UNAVAILABLE"))
예제 #9
0
    def getDeploymentID(self, cookie):
        if not self.deploymentID:
            self.getToken(cookie)
            self.server_uri = rest.makeSplunkdUri()
            splunkd = Splunkd(token=self.token, server_uri=self.server_uri)

            telemetry_conf_service = TelemetryConfService(splunkd,
                                                          is_read_only=True)
            telemetry_conf_service.fetch()

            deployment_id_manager = DeploymentIdManager(
                splunkd, telemetry_conf_service=telemetry_conf_service)

            self.deploymentID = deployment_id_manager.get_deployment_id()
        return self.deploymentID
예제 #10
0
    parser.add_argument('-p', '--password',
                        help='Splunk password',
                        required=True)

    parser.add_argument('--prefix',
                        help='Desired prefix for the deployment ID',
                        required=False)

    args = parser.parse_args()

    splunkrc = {
        'username': args.user,
        'password': args.password
    }

    splunkd = Splunkd(**splunkrc)
    deployment_id_manager = DeploymentIdManager(splunkd)

    deploymentID = deployment_id_manager.get_deployment_id(no_create=True)

    if deploymentID is not None and deploymentID.startswith(args.prefix or ''):
        print("Deployment ID already initialized: %s" %
              deploymentID)
        # Only failures to set are considered error conditions.
        # So the exit code for an existing deployment ID is still 0.
        exit(0)
    else:
        deployment_id_manager.generate_new_deployment_id(prefix=args.prefix)
        deployment_id_manager.write_deployment_id_to_conf_file()
        print("Deployment ID successfully initialized: %s" %
              deployment_id_manager.get_deployment_id(no_create=True))
예제 #11
0
            ['content']['disabled'])
    except Exception:
        # Proceed as if it's disabled if we can't hit the endpoint
        pass

    if dist_search_disabled:
        return True

    search_peers = splunkd.get_json(
        '/services/search/distributed/peers')['entry']
    if search_peers:
        for peer in search_peers:
            if (peer['content']['status'].lower() == 'up'
                    and not peer['content']['disabled'] and '_telemetry'
                    not in peer['content']['searchable_indexes']):
                return False

    return True


if __name__ == '__main__':
    from splunk_instrumentation.splunkd import Splunkd
    from splunk_instrumentation.service_bundle import ServiceBundle
    from splunk_instrumentation.cli_token import get_token

    bundle = ServiceBundle(Splunkd(token=get_token('https://localhost:8089')))

    from pprint import pprint

    pprint(get_eligibility(bundle, opt_in_version='*'))
예제 #12
0
 def get_service(self, token, service=None):
     self.token = token
     self.server_uri = self.make_splunkd_uri()
     if not service:
         service = Splunkd(token=self.token, server_uri=self.server_uri)
     return service
예제 #13
0
import sys
import time

import splunk_instrumentation.splunklib as splunklib
from splunk_instrumentation.splunkd import Splunkd
from splunk_instrumentation.service_bundle import ServiceBundle
from splunk_instrumentation.deployment_id_manager import DeploymentIdManager
import splunk_instrumentation.constants as constants
import splunk_instrumentation.client_eligibility as client_eligibility
from splunk_instrumentation.salt_manager import SaltManager

token = sys.stdin.read().rstrip()
splunkd = Splunkd(token=token, server_uri=constants.SPLUNKD_URI)

services = ServiceBundle(splunkd)
salt_manager = SaltManager(services)

# Cloud provisioning sets their own deployment
# ID's after starting splunk. But just in case
# we're stuck with the value from this script,
# let's use the correct prefix.
prefix = None
if services.server_info_service.is_cloud():
    prefix = 'CLOUD'
    if services.server_info_service.is_lite():
        prefix += 'LIGHT'

# Migration of the deployment ID from V1 of instrumentation
# requires waiting until the KV store is ready. We'll give
# it 5 minutes, then proceed without out.
t_start = time.time()
예제 #14
0
      splunk cmd python -m splunk_instrumentation.deployment_node_list

      # Alternatively, with a remote splunk
      splunk cmd python -m splunk_instrumentation.deployment_node_list https://remote_splunk:8089

    Example:

      $ splunk cmd python -m splunk_instrumentation.deployment_node_list
      {'errors': ['Could not locate any search head cluster members in this deployment',
                  'Failed to locate a Cluster Master in this deployment'],
       'nodes': [{'authMethod': 'indexer',
                  'host': u'9ac296fad4e8',
                  'roles': [u'indexer', u'license_master', u'search_peer'],
                  'uri': 'https://localhost:8090'}]}
    '''

    import sys
    from splunk_instrumentation.splunkd import Splunkd
    from splunk_instrumentation.cli_token import get_token
    from pprint import pprint

    if len(sys.argv) > 1:
        splunk_uri = sys.argv[1]
    else:
        splunk_uri = 'https://localhost:8089'

    service = Splunkd(server_uri=splunk_uri, token=get_token(splunk_uri))

    node_list = NodeList(service)
    pprint(node_list.fetch_nodes())
    def update(self,
               cherrypy,
               services=None,
               deployment_id_manager=None,
               salt_manager=None):
        '''
        Updates the volatile data members of the swa context.
        This method is hit each time an HTML page is hit, so the
        less work done here the better.
        '''

        if services is None:
            splunkd = Splunkd(token=cherrypy.session.get('sessionKey'),
                              server_uri=self.server_uri)
            telemetry_conf_service = TelemetryConfService(splunkd,
                                                          is_read_only=True)
            telemetry_conf_service.fetch()
            # Specialize the telemetry_conf_service to be read only up front,
            # use the default construction for other services.
            services = ServiceBundle(
                splunkd, telemetry_conf_service=telemetry_conf_service)

        if not self.instance_guid:
            self.instance_guid = services.server_info_service.content.get(
                'guid')

        salt_manager = salt_manager or SaltManager(services)
        self.salt = salt_manager.get_salt()

        deployment_id_manager = deployment_id_manager or DeploymentIdManager(
            splunkd, telemetry_conf_service=services.telemetry_conf_service)

        self.deployment_id = deployment_id_manager.get_deployment_id() or ''

        self.opt_in_is_up_to_date = services.telemetry_conf_service.opt_in_is_up_to_date(
        )

        self.swa_base_url = services.telemetry_conf_service.content.get(
            'swaEndpoint')

        hash_key = self.salt + splunk.auth.getCurrentUser()['name']
        if sys.version_info >= (3, 0):
            hash_key = hash_key.encode()

        self.user_id = hashlib.sha256(hash_key).hexdigest()

        self.send_anonymized_web_analytics = conf_bool(
            services.telemetry_conf_service.content.get(
                'sendAnonymizedWebAnalytics'))

        visibilities = []

        if services.server_info_service.is_cloud():
            visibilities = ['anonymous', 'support']
        else:
            if conf_bool(
                    services.telemetry_conf_service.content.get(
                        'sendAnonymizedUsage')):
                visibilities.append('anonymous')

            if conf_bool(
                    services.telemetry_conf_service.content.get(
                        'sendSupportUsage')):
                visibilities.append('support')

        self.visibility = ','.join(visibilities)

        if self.send_anonymized_web_analytics and not self.cds_url:
            self.cds_url = get_quick_draw().get('url')
예제 #16
0
class EventWriter(object):
    """ Event Writer class
    This class handles writing to the index.
    It grabs a splunkd object according to the splunkrc params provided:
        - If splunkrc is a dictionary, it will create a new splunkd object.
        - If given other object type, it will do do Dependency Injection on _splunkd

    """
    def __init__(self, splunkrc=None, index_name=None):
        self.splunkrc = splunkrc or SPLUNKRC
        self.socket = None
        self._index = None

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        if index_name:
            if self._splunkd.has_index(index_name):
                self._index = self._splunkd.get_index(index_name)
            else:
                logging.error('ERROR: INDEX IS NOT AVAILABLE')
                raise Exception("ERROR INDEX UNAVAILABLE")

    def submit(self, event, host=None, source=None, sourcetype=INSTRUMENTATION_SOURCETYPE):
        # Note: We used to use the ordinary index.submit method from splunklib,
        #       instead of using a socket. However, that method uses receivers/simple,
        #       an endpoint that bypasses index time field extraction (which we rely on).
        temp_socket = self._index.attach(host=host, source=source, sourcetype=sourcetype)
        temp_socket.send(self.marshal_event(event))
        temp_socket.close()

    def open_socket(self, host=None, source=None, sourcetype=INSTRUMENTATION_SOURCETYPE):
        '''
        Opens a socket to stream events to be indexed, saving it as
        an instance variable for later use when submit_via_socket is called.
        :param host:
        :param source:
        :param sourcetype:
        :return:
        '''
        self.socket = self._index.attach(host=host, source=source, sourcetype=sourcetype)
        return self.socket

    def close_socket(self):
        '''
        Closes socket and set it to none
        '''
        if self.socket:
            self.socket.close()
        self.socket = None

    def submit_via_socket(self, event):
        """
        Submit the event provided using socket connection.
        """
        event = self.marshal_event(event)
        if not self.socket:
            self.open_socket()
        self.socket.send(event)

    @staticmethod
    def marshal_event(event):
        '''
        Marshals the given event into a json string, suitable for passing
        to an open receivers/stream socket.
        '''
        if not isinstance(event, (str, bytes)):
            event = json.dumps(event, default=json_serial)
        if isinstance(event, str) and sys.version_info >= (3, 0):
            event = event.encode()
        return event
예제 #17
0
"""Spawn multiple workers and wait for them to complete"""

path = os.path.realpath(
    os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..',
                 'bin'))
sys.path.append(path)
from splunk_instrumentation.diag.batch_runner import BatchRunner  # noqa
from splunk_instrumentation.diag.diag_task import DiagTask  # noqa
from splunk_instrumentation.splunkd import Splunkd  # noqa
from splunk_instrumentation.diag.diag_service import DiagService  # noqa

configurationStr = sys.stdin.read()

configuration = json.loads(configurationStr)

splunkd = Splunkd(token=configuration['token'],
                  server_uri=configuration['server_uri'])

diag_service = DiagService(splunkd)

batchRunner = BatchRunner(config=configuration['payload'])
diag_service.batch_id = batchRunner.batch_id

for config in configuration['payload']['nodes']:
    batchRunner.add_task(
        DiagTask(
            {
                "node": config,
                "configuration": configuration['payload']['configuration']
            },
            diag_service=diag_service))
    def handle(self, arg):
        '''
        Takes the parsed request data passed by splunkd to
        PersistentServerConnectionApplication.handle and returns a response.
        :param arg: JSON object
        :return: JSON object
        '''

        arg = self.parse_arg(arg)
        logger.debug('arg = %s' % json.dumps(arg))
        if 'query' not in arg:
            arg['query'] = []

        try:
            if 'session' not in arg:
                raise splunk.RESTException(500, "No session found.")
            self.session = arg['session']

            if 'system_authtoken' not in arg:
                raise splunk.RESTException(500, "No system auth token found.")
            self.system_authtoken = arg['system_authtoken']

            if self.services:
                self.splunkd = self.services.splunkd
            else:
                self.splunkd = Splunkd(**self.splunkrc())
                self.services = ServiceBundle(self.splunkd)

            if not self.system_services:
                splunkd = Splunkd(**self.system_splunkrc())
                self.system_services = ServiceBundle(splunkd)

            usage_data_endpoint_table = {
                'anonymous_usage_data': {
                    'visibility': 'anonymous',
                    'action': 'export'
                },
                'license_usage_data': {
                    'visibility': 'license',
                    'action': 'export'
                },
                'support_usage_data': {
                    'visibility': 'support',
                    'action': 'export'
                },
                'send_anonymous_usage_data': {
                    'visibility': 'anonymous',
                    'action': 'send'
                },
                'send_license_usage_data': {
                    'visibility': 'license',
                    'action': 'send'
                },
                'send_support_usage_data': {
                    'visibility': 'support',
                    'action': 'send'
                }
            }

            path = arg['path_info']
            if path == 'instrumentation_eligibility':
                return self.response_to_eligibility_request(arg)
            elif path in usage_data_endpoint_table:
                visibility = usage_data_endpoint_table[path]['visibility']
                if (usage_data_endpoint_table[path]['action'] == 'export'):
                    return self.response_to_export_request(
                        path, visibility, arg)
                else:
                    return self.response_to_send_request(path, visibility, arg)
            else:
                return {'payload': '"%s" not found' % path, 'status': 404}

        except splunk.RESTException as e:
            logger.error(e)
            return {
                'payload': 'Exception caught: %s' % e.msg,
                'status': e.statusCode
            }
        except Exception as e:
            logger.error('ERROR: ' + traceback.format_exc())
            return {
                'payload': traceback.format_exception_only(type(e), e)[-1],
                'status': 500
            }
예제 #19
0
class EventWriter(object):
    """ Event Writer class
    This class handles writing to the index.
    It grabs a splunkd object according to the splunkrc params provided:
        - If splunkrc is a dictionary, it will create a new splunkd object.
        - If given other object type, it will do do Dependency Injection on _splunkd

    """
    def __init__(self, splunkrc=None, index_name=None):
        self.splunkrc = splunkrc or SPLUNKRC
        self.socket = None
        self._index = None

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        if index_name:
            if self._splunkd.has_index(index_name):
                self._index = self._splunkd.get_index(index_name)
            else:
                logging.error('ERROR: INDEX IS NOT AVAILABLE')
                raise (Exception("ERROR INDEX UNAVAILABLE"))

    def submit(self, event, host=None, source=None, sourcetype=None):
        """Submit a new event directly to the index."""
        if self._index:
            self._index.submit(event,
                               host=host,
                               source=source,
                               sourcetype=sourcetype)
        else:
            logging.error('ERROR: INDEX IS NOT AVAILABLE')
            raise Exception("ERROR INDEX UNAVAILABLE")

    def open_socket(self, host=None, source=None, sourcetype=None):
        '''
        Opens a socket to stream events to be indexed
        :param host:
        :param source:
        :return:
        '''
        self.socket = self._index.attach(host=host,
                                         source=source,
                                         sourcetype=INSTRUMENTATION_SOURCETYPE)
        return self.socket

    def close_socket(self):
        '''
        Closes socket and set it to none
        '''
        if self.socket:
            self.socket.close()
        self.socket = None

    def submit_via_socket(self, event):
        """
        Submit the event provided using socket connection.
        """
        if not isinstance(event, str):
            event = json.dumps(event, default=json_serial)
        if not self.socket:
            self.open_socket()
        self.socket.send(event)