Exemple #1
0
    def transform(self, events):
        # Bind to Splunk session and initialize variables
        service = client.Service(token=self.metadata.searchinfo.session_key)
        salt = ""

        # Get salt if "salt" was set
        if self.salt:
            # Check if configuration exists for specified salt
            try:
                service.confs['inputs']['crypto_settings://{0}'.format(
                    self.salt)]
            except:
                raise ValueError(
                    'Specified salt file "{0}" does not exist. Please check the spelling of your specified salt name or your configured salts.'
                    .format(self.salt))

            # Continue if user is authorized for salt usage
            if self.validate_user(service):
                salt = self.load_salt(service)

        # HASH
        #
        for event in events:
            for fieldname in self.fieldnames:
                if fieldname == '_time':
                    continue
                try:
                    if self.salt:
                        message = salt.encode(
                            'utf-8') + event[fieldname].encode('utf-8')
                    else:
                        message = event[fieldname].encode('utf-8')

                    if self.algorithm in [
                            'md5', 'sha1', 'sha224', 'sha256', 'sha384',
                            'sha512'
                    ]:
                        hashmethod = getattr(hashlib, self.algorithm)
                        event[self.algorithm] = hashmethod(message).hexdigest()
                    elif sys.version_info >= (3, 0) and self.algorithm in [
                            'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
                            'blake2b', 'blake2s'
                    ]:
                        hashmethod = getattr(hashlib, self.algorithm)
                        event[self.algorithm] = hashmethod(message).hexdigest()
                    elif sys.version_info < (3, 0) and self.algorithm in [
                            'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
                            'blake2b', 'blake2s'
                    ]:
                        raise RuntimeWarning(
                            'Hash algorithm "{0}" is only available when using Python 3 as Splunk\'s Python interpreter.'
                            .format(self.algorithm))
                    else:
                        raise ValueError(
                            'Invalid hash algorithm "{0}" has been specified.'.
                            format(self.algorithm))
                except Exception as e:
                    raise RuntimeWarning(
                        'Failed to hash fields: {0}'.format(e))
            yield event
Exemple #2
0
def test_kvstore():
    session_key = get_session_key(
        context.username,
        context.password,
        scheme=context.scheme,
        host=context.host,
        port=context.port,
    )
    kvstore = client.Service(
        scheme=context.scheme,
        host=context.host,
        port=context.port,
        token=session_key,
        app=context.app,
        owner=context.owner,
        autologin=True,
    ).kvstore
    fields = {"id": "string", "name": "string", "user": "******"}

    last_ex = None
    for i in range(3):
        try:
            kvstore.create("sessions", fields=fields)
            break
        except binding.HTTPError as e:
            last_ex = e
            time.sleep(2**(i + 1))
    else:
        if last_ex:
            raise last_ex

    collections = kvstore.list()
    collection_data = None
    for collection in collections:
        if collection.name == "sessions":
            collection_data = collection.data
            break
    assert collection_data

    record = {"id": uuid.uuid4().hex, "name": "session1", "user": "******"}
    _key = collection_data.insert(json.dumps(record))["_key"]
    resp_record = collection_data.query_by_id(_key)
    resp_record = {
        key: resp_record[key]
        for key in resp_record if not key.startswith("_")
    }
    assert sorted(resp_record.values()) == sorted(record.values())

    record = {"id": uuid.uuid4().hex, "name": "session4", "user": "******"}
    collection_data.update(_key, json.dumps(record))
    resp_record = collection_data.query_by_id(_key)
    resp_record = {
        key: resp_record[key]
        for key in resp_record if not key.startswith("_")
    }
    assert sorted(resp_record.values()) == sorted(record.values())

    collection_data.delete_by_id(_key)
    with pytest.raises(HTTPError):
        collection_data.query_by_id(_key)
Exemple #3
0
    def postHandler(self, authToken, queryParams):
        try:
            kvstore = client.Service(token=authToken,
                                     app=APP_NAME,
                                     autologin=True).kvstore
            collection_data = kvstore['userpanel'].data

        except Exception as e:
            logging.error(e)
            # create kvstore collection
            collection_data, error_msg = self.create_collection(
                kvstore, 'userpanel')

            if error_msg:
                payload = {'payload': {'error': error_msg}, 'status': 500}
                return json.dumps(payload)
        try:
            params = json.loads(queryParams)
            self._validate_panel_name(params.get('name'))
            self._validate_panel_frequency(params.get('frequency'))
            key = collection_data.insert(queryParams)
            payload = {'payload': {'content': key}, 'status': 200}
            return json.dumps(payload)

        except Exception as e:
            logging.error(e)
            payload = {'payload': {'error': str(e)}, 'status': 500}
            return json.dumps(payload)
Exemple #4
0
    def test_login_with_multiple_cookies(self):
        bad_cookie = 'bad=cookie'
        self.service.login()
        self.assertIsNotNone(self.service.get_cookies())

        service2 = client.Service(**{"cookie": bad_cookie})

        # Should get an error with a bad cookie
        try:
            service2.login()
            self.fail()
        except AuthenticationError as ae:
            self.assertEqual(str(ae), "Login failed.")

            # Add on valid cookies, and try to use all of them
            service2.get_cookies().update(self.service.get_cookies())

            self.assertEqual(len(service2.get_cookies()), 2)
            self.service.get_cookies().update({'bad': 'cookie'})
            self.assertEqual(service2.get_cookies(), self.service.get_cookies())
            self.assertEqual(len(service2.get_cookies()), 2)
            self.assertTrue([cookie for cookie in service2.get_cookies() if "splunkd_" in cookie])
            self.assertTrue('bad' in service2.get_cookies())
            self.assertEqual(service2.get_cookies()['bad'], 'cookie')
            self.assertEqual(set(self.service.get_cookies()), set(service2.get_cookies()))
            service2.login()
            self.assertEqual(service2.apps.get().status, 200)
def splunkrestart(host='localhost',
                  port=8089,
                  user='******',
                  passwd='changeme'):
    """
        Restarts Splunk Services
        @param host: IP or FQDN.  default 'localhost'
        @type host: str
        @param port: splunkd service port. default 8089
        @type signed_low: int
        @param user: Splunk user with admin permission. default admin
        @type user: str
        @param passwd: Splunk user password.  default 'changeme'
        @type passwd: str
        @rtype = dict
    """
    service = client.Service(host=host,
                             port=port,
                             username=user,
                             password=passwd)
    try:
        service.login()
        response = service.restart()
        service.logout()
    except Exception as e:
        return e
    return response
Exemple #6
0
def connect():
    global splunk
    if not splunk:
        app_name = os.getenv("DLTK_APP_NAME", "dltk")

        base_request = base_handler()
        prefix = os.getenv("SPLUNK_PATH_PREFIX", "")

        def request_with_prefix(url, message, **kwargs):
            o = urlparse(url)
            url = "%s://%s:%s/%s%s" % (o.scheme, o.hostname, o.port, prefix,
                                       o.path)
            if o.query:
                url += "?" + o.query
            return base_request(url, message, **kwargs)

        splunk = client.Service(
            handler=request_with_prefix if prefix else None,
            username=os.getenv("SPLUNK_USERNAME", "admin"),
            password=os.getenv("SPLUNK_PASSWORD", "changeme"),
            host=os.getenv("SPLUNK_HOST", "localhost"),
            scheme=os.getenv("SPLUNK_SCHEME", "https"),
            port=int(os.getenv("SPLUNK_PORT", "8089")),
            sharing="app",
            app=app_name,
            autologin=True,
        )
    return splunk
    def test_login_with_multiple_cookies(self):
        bad_cookie = 'bad=cookie'
        self.service.login()
        self.assertIsNotNone(self.service.get_cookies())

        service2 = client.Service(**{"cookie": bad_cookie})
        service2.login()

        # Should get an error with a bad cookie
        try:
            service2.apps.get()
            self.fail()
        except AuthenticationError as ae:
            self.assertEqual(ae.message,
                             "Request failed: Session is not logged in.")

            # Add on valid cookies, and try to use all of them
            service2.get_cookies().update(self.service.get_cookies())

            self.assertEqual(len(service2.get_cookies()), 2)
            self.service.get_cookies().update({'bad': 'cookie'})
            self.assertEqual(service2.get_cookies(),
                             self.service.get_cookies())
            self.assertEqual(len(service2.get_cookies()), 2)
            self.assertEqual(service2.get_cookies().keys()[1][:8], "splunkd_")
            self.assertTrue('bad' in service2.get_cookies().keys())
            self.assertEqual(service2.get_cookies()['bad'], 'cookie')
            self.assertEqual(self.service.get_cookies().items(),
                             service2.get_cookies().items())
            service2.login()
            self.assertEqual(service2.apps.get().status, 200)
Exemple #8
0
 def create_service(self):
     s = client.Service(
         #token=self.sessionKey,
         token=self.request["systemAuth"],
         sharing="app",
         app=app_name,
     )
     return s
Exemple #9
0
 def _validate(self, props):
     c = client.Service(**props)
     # check whether it installed aws add-on
     if props['host'] is not self.local_splunk_host:
         c.login()
     if TARGET_APP not in c.apps:
         return False
     return True
Exemple #10
0
 def splunk(self):
     if self._splunk != None:
         return self._splunk
     self._splunk = client.Service(
         token=self.request["systemAuth"],  # self.sessionKey,
         sharing="app",
         app=this_app_name,
     )
     return self._splunk
    def setUp(self):
        self.opts = testlib.parse([], {}, ".splunkrc")
        self.service = client.Service(**self.opts.kwargs)

        # Skip these tests if running below Splunk 6.2, cookie-auth didn't exist before
        splver = self.service.splunk_version
        if splver[:2] < (6, 2):
            self.skipTest(
                "Skipping cookie-auth tests, running in %d.%d.%d, this feature was added in 6.2+"
                % splver)
    def test_login_fails_with_no_cookie(self):
        service2 = client.Service()
        self.assertEquals(len(service2.get_cookies()), 0)

        # Should get an error when no authentication method
        try:
            service2.login()
            self.fail()
        except AuthenticationError as ae:
            self.assertEqual(ae.message, "Login failed.")
Exemple #13
0
    def setUp(self):
        self.opts = testlib.parse([], {}, ".splunkrc")
        opts = self.opts.kwargs.copy()
        opts["basic"] = True
        opts["username"] = self.opts.kwargs["username"]
        opts["password"] = self.opts.kwargs["password"]

        self.context = binding.connect(**opts)
        import splunklib.client as client
        service = client.Service(**opts)
Exemple #14
0
 def test_login_with_cookie(self):
     self.service.login()
     self.assertIsNotNone(self.service.get_cookies())
     # Use the cookie from the other service as the only auth param (don't need user/password)
     service2 = client.Service(**{"cookie": "%s=%s" % list(self.service.get_cookies().items())[0]})
     service2.login()
     self.assertEqual(len(service2.get_cookies()), 1)
     self.assertEqual(service2.get_cookies(), self.service.get_cookies())
     self.assertEqual(len(service2.get_cookies()), len(self.service.get_cookies()))
     self.assertEqual(list(service2.get_cookies().keys())[0][:8], "splunkd_")
     self.assertEqual(service2.apps.get().status, 200)
    def setUp(self):
        self.opts = testlib.parse([], {}, ".splunkrc")
        self.service = client.Service(**self.opts.kwargs)

        # Skip these tests if running below Splunk 6.2, cookie-auth didn't exist before
        splver = self.service.splunk_version
        # TODO: Workaround the fact that skipTest is not defined by unittest2.TestCase
        if splver[:2] < (6, 2):
            self.skipTest(
                "Skipping cookie-auth tests, running in %d.%d.%d, this feature was added in 6.2+"
                % splver)
Exemple #16
0
    def test_login_fails_with_bad_cookie(self):
        bad_cookie = {'bad': 'cookie'}
        service2 = client.Service()
        self.assertEqual(len(service2.get_cookies()), 0)
        service2.get_cookies().update(bad_cookie)
        self.assertEqual(service2.get_cookies(), {'bad': 'cookie'})

        # Should get an error with a bad cookie
        try:
            service2.login()
            self.fail()
        except AuthenticationError as ae:
            self.assertEqual(str(ae), "Login failed.")
Exemple #17
0
    def test_submit_via_attach_with_multiple_cookie_headers(self):
        # Skip this test if running below Splunk 6.2, cookie-auth didn't exist before
        splver = self.service.splunk_version
        if splver[:2] < (6, 2):
            self.skipTest("Skipping cookie-auth tests, running in %d.%d.%d, this feature was added in 6.2+" % splver)

        event_count = int(self.service.indexes[self.index_name]['totalEventCount'])
        service = client.Service(**{"cookie": 'a bad cookie'})
        service.http._cookies.update(self.service.http._cookies)
        service.login()
        cn = service.indexes[self.index_name].attach()
        cn.send(b"Hello Boris!\r\n")
        cn.close()
        self.assertEventuallyTrue(lambda: self.totalEventCount() == event_count+1, timeout=60)
def connect():
    global splunk
    if not splunk:
        app_name = os.getenv("DLTK_APP_NAME", "dltk")
        splunk = client.Service(
            username=os.getenv("SPLUNK_USERNAME", "admin"),
            password=os.getenv("SPLUNK_PASSWORD", "changeme"),
            host=os.getenv("SPLUNK_HOST", "localhost"),
            port=int(os.getenv("SPLUNK_PORT", "8089")),
            sharing="app",
            app=app_name,
            autologin=True,
        )
    return splunk
    def test_login_fails_with_bad_cookie(self):
        bad_cookie = {'bad': 'cookie'}
        service2 = client.Service()
        self.assertEquals(len(service2.get_cookies()), 0)
        service2.get_cookies().update(bad_cookie)
        service2.login()
        self.assertEquals(service2.get_cookies(), {'bad': 'cookie'})

        # Should get an error with a bad cookie
        try:
            service2.apps.get()
            self.fail()
        except AuthenticationError as ae:
            self.assertEqual(ae.message,
                             "Request failed: Session is not logged in.")
Exemple #20
0
    def deleteHandler(self, authToken, query):
        try:
            kvstore = client.Service(token=authToken,
                                     app=APP_NAME,
                                     autologin=True).kvstore
            collection_data = kvstore['userpanel'].data
            key = self.parseGetParams(query)
            queryString = json.dumps({'_key': key})
            collection_data.delete(query=queryString)

            payload = {'payload': {'content': {'key': key}}, 'status': 200}
            return json.dumps(payload)
        except Exception as e:
            logging.error(e)
            payload = {'payload': {'error': str(e)}, 'status': 500}
            return json.dumps(payload)
Exemple #21
0
 def putHandler(self, authToken, payload):
     try:
         kvstore = client.Service(token=authToken,
                                  app=APP_NAME,
                                  autologin=True).kvstore
         collection_data = kvstore['userpanel'].data
         params = json.loads(payload)
         self._validate_panel_name(params.get('name'))
         self._validate_panel_frequency(params.get('frequency'))
         key = params.get('key')
         collection_data.update(key, payload)
         payload = {'payload': {'content': {'key': key}}, 'status': 200}
         return json.dumps(payload)
     except Exception as e:
         logging.error(e)
         payload = {'payload': {'error': str(e)}, 'status': 500}
         return json.dumps(payload)
Exemple #22
0
    def _get_svc(self):
        host, port = entity.getEntity(
            'configs/conf-web',
            'settings',
            sessionKey = self.sessionKey,
            namespace = self.context['app'],
            owner = self.context['user']
        ).get(
            'mgmtHostPort', DEFAULT_HOST_PORT
        ).split(':')

        return client.Service(
            host = host,
            port = port,
            app = self.context['app'],
            owner = self.context['user'],
            token = self.sessionKey
        )
Exemple #23
0
    def getHandler(self, authToken, query):
        try:
            kvstore = client.Service(token=authToken,
                                     app=APP_NAME,
                                     autologin=True).kvstore
            collection_data = kvstore['userpanel'].data.query()

            payload = {
                'payload': {
                    'content': {
                        'entry': collection_data
                    }
                },
                'status': 200
            }

            return json.dumps(payload)
        except Exception as e:
            logging.error(e)
            payload = {'payload': {'error': str(e)}, 'status': 500}
            return json.dumps(payload)
 def __init__(self,
              app=None,
              owner='nobody',
              session_key=None,
              service=None):
     self._app = app
     self._owner = owner
     self._session_key = session_key
     if service is None:
         splunkd_host_port = self._get_entity(CONF_WEB, 'settings').get(
             'mgmtHostPort', '127.0.0.1:8089')
         host_and_port = splunkd_host_port.split(':')
         self.local_splunk_host = host_and_port[0]
         self.local_splunk_port = host_and_port[1]
         self._service = client.Service(host=self.local_splunk_host,
                                        port=self.local_splunk_port,
                                        app=self._app,
                                        owner=self._owner,
                                        token=self._session_key)
     else:
         self._service = service
Exemple #25
0
 def _get_target_service(self, target, target_app=None, target_owner=None):
     logger.info('get target service %s' % target)
     target_manager = tm.TargetManager(app=self.appName,
                                       owner=self.userName,
                                       session_key=self.getSessionKey())
     target_properties = target_manager.get_target(target)
     if target_app:
         target_properties['app'] = target_app
     if target_owner:
         target_properties['owner'] = target_owner
     if target_properties:
         logger.info('target service props %s' % target_properties)
         service = client.Service(**target_properties)
         # TODO: anyway to cache the session key?
         if not target == target_manager.local_splunk_host:
             service = service.login()
             logger.info('login %s ! %s' % (service.host, service.token))
         return service
     else:
         raise admin.ArgValidationException("target %s does not exist" %
                                            target)
    def putHandler(self, authToken, in_string):
        try:
            confs = client.Service(token=authToken,
                                   app=APP_NAME,
                                   autologin=True).confs
            macros = confs['macros']

            data = json.loads(in_string)
            jenkins = data['jenkins']
            statistics = data['jenkinsStatistics']
            console = data['jenkinsConsole']
            self._validate_user_input(jenkins)
            self._validate_user_input(statistics)
            self._validate_user_input(console)
            for stanza in macros:
                if stanza.name == 'jenkins_statistics_index':
                    stanza.update(**{'definition': 'index=' + statistics})
                elif stanza.name == 'jenkins_console_index':
                    stanza.update(**{'definition': 'index=' + console})
                elif stanza.name == 'jenkins_index':
                    stanza.update(**{'definition': 'index=' + jenkins})

            payload = {
                'payload': {
                    'content': {
                        'entry': {
                            'statistics': statistics,
                            'jenkins': jenkins,
                            'consoleIdx': console
                        }
                    }
                },
                'status': 200
            }
            return json.dumps(payload)
        except Exception as e:
            logging.error(str(e))
            payload = {'payload': {'error': str(e)}, 'status': 500}
            return json.dumps(payload)
Exemple #27
0
 def __init__(self, app=None, owner=None, session_key=None):
     self._app = app
     self._owner = 'nobody'  # so that conf file will be saved in app
     self._sessionKey = session_key
     splunkd_host_port = self._get_entity(CONF_WEB, 'settings').get(
         'mgmtHostPort', '127.0.0.1:8089')
     host_and_port = splunkd_host_port.split(':')
     self.local_splunk_host = host_and_port[0]
     self.local_splunk_port = host_and_port[1]
     logger.info('app %s, owner %s, host %s, port %s' %
                 (self._app, self._owner, self.local_splunk_host,
                  self.local_splunk_port))
     self._service = client.Service(host=self.local_splunk_host,
                                    port=self.local_splunk_port,
                                    app=self._app,
                                    owner=self._owner,
                                    token=self._sessionKey)
     if "Splunk_TA_snow" not in self._service.apps:
         raise admin.InternalException(
             "Splunk ServiceNow Add-on is not found on server")
     if CONF_TARGET not in self._service.confs:
         self._service.confs.create(CONF_TARGET)
    def getHandler(self, authToken, params):
        try:
            confs = client.Service(token=authToken,
                                   app=APP_NAME,
                                   autologin=True).confs
            macros = confs['macros']

            for stanza in macros:
                if stanza.name == 'jenkins_statistics_index':
                    statistics = stanza.content
                elif stanza.name == 'jenkins_console_index':
                    console = stanza.content
                elif stanza.name == 'jenkins_index':
                    jenkins = stanza.content

            payload = {
                'payload': {
                    'content': {
                        'entry': {
                            'statistics': statistics,
                            'consoleIdx': console,
                            'jenkins': jenkins
                        }
                    }
                },
                'status': 200
            }

            return json.dumps(payload)
        except Exception as e:
            logging.error(str(e))
            payload = {
                'payload': {
                    'error': str(e),
                },
                'status': 500
            }
            return json.dumps(payload)
    def post(self, **kwargs):
        app_name = "%s" % cherrypy.request.path_info.split("/")[-3]

        try:
            lib_path = sys.path.append(
                make_splunkhome_path(
                    ["etc", "apps", "splunk_as_a_service", "lib"]))
            if lib_path not in sys.path:
                sys.path.insert(0, lib_path)

            bin_path = sys.path.append(
                make_splunkhome_path(
                    ["etc", "apps", "splunk_as_a_service", "bin"]))
            if bin_path not in sys.path:
                sys.path.insert(0, bin_path)

            import capabilities
            import apps
            import app_bundles

            import importlib
            importlib.reload(capabilities)
            importlib.reload(apps)
            importlib.reload(app_bundles)

            if not capabilities.has(
                    "saas_manage_apps") and not capabilities.has(
                        "admin_all_objects"):
                cherrypy.response.status = 403
                return "missing capability"

            app_field = kwargs.get('app')
            # if not isinstance(app_field, cgi.FieldStorage):
            #    cherrypy.response.status = 400
            #    return "Missing app field: %s" % dir(app_field)

            import splunklib.client as client
            splunk = client.Service(
                token=cherrypy.session.get('sessionKey'),
                sharing="app",
                app=app_name,
            )

            app_path = None
            try:
                with tempfile.NamedTemporaryFile(delete=False) as temp_file:
                    shutil.copyfileobj(app_field.file, temp_file)
                    app_path = temp_file.name

                if app_bundles.is_bundle(app_path):
                    bundle_name = app_bundles.add_bundle(
                        splunk, app_path, app_field.filename)
                    return self.render_json(
                        dict(
                            kind="bundle",
                            name=bundle_name,
                        ))
                else:
                    app_name, app_version = apps.add_app(splunk, app_path)
                    return self.render_json(
                        dict(kind="app", name=app_name, version=app_version))
            finally:
                if app_path:
                    os.remove(app_path)

        except:
            cherrypy.response.status = 500
            return traceback.format_exc()
Exemple #30
0
    def generate(self):
        self.logger.debug("Generating %s events" % self.incident_id)

        service = client.Service(token=self.metadata.searchinfo.session_key)

        # Check if configuration exists for collect_data_results
        try:
            collect_data_results = service.confs['alert_manager']['settings'][
                'collect_data_results']
        except:
            raise RuntimeWarning(
                'Specified setting ""collect_data_results" in "alert_manager.conf" does not exist.'
            )

        # Check if configuration exists for index_data_results
        try:
            index_data_results = service.confs['alert_manager']['settings'][
                'index_data_results']
        except:
            raise RuntimeWarning(
                'Specified setting ""index_data_results" in "alert_manager.conf" does not exist.'
            )

        # Fetch Results from KV Store by default if enabled
        if collect_data_results == '1':
            service.namespace['owner'] = "Nobody"

            collection_name = "incident_results"
            collection = service.kvstore[collection_name]

            query_dict = {}
            query_dict['incident_id'] = self.incident_id
            query = json.dumps(query_dict)

            data = collection.data.query(query=query)

            incident_data = {}

            incident_data = data[0].get("fields")[0]

            for k, v in incident_data.items():
                incident_data[k] = urllib.parse.quote(v)

        # If KV Store Data is not enabled, get indexed data
        elif index_data_results == '1' and collect_data_results == '0':
            # Get index location
            try:
                index = service.confs['alert_manager']['settings']['index']
            except:
                raise RuntimeWarning(
                    'Specified setting ""index_data_results" in "alert_manager.conf" does not exist.'
                )

            # Get earliest time first for incident results
            service.namespace['owner'] = "Nobody"

            collection_name = "incidents"
            collection = service.kvstore[collection_name]

            query_dict = {}
            query_dict['incident_id'] = self.incident_id
            query = json.dumps(query_dict)

            data = collection.data.query(query=query)
            earliest_time = data[0].get("alert_time")

            # Fetch events
            events = []
            incident_data = {}

            kwargs_oneshot = json.loads(
                '{{"earliest_time": "{}", "latest_time": "{}"}}'.format(
                    earliest_time, "now"))

            searchquery_oneshot = "search index={} sourcetype=alert_data_results incident_id={} |dedup incident_id".format(
                index, self.incident_id)
            oneshotsearch_results = service.jobs.oneshot(
                searchquery_oneshot, **kwargs_oneshot)
            reader = results.ResultsReader(oneshotsearch_results)

            for result in reader:
                for k, v in result.items():
                    if k == '_raw':
                        events.append(json.loads(v))

            for event in events:
                incident_data = event.get("fields")[0]

            for k, v in incident_data.items():
                incident_data[k] = urllib.parse.quote(v)

        # Get Incident
        query_dict = {}
        query_dict['incident_id'] = self.incident_id

        collection_name = "incidents"
        collection = service.kvstore[collection_name]
        query = json.dumps(query_dict)

        data = collection.data.query(query=query)

        alert = data[0].get('alert')

        # Get Incident Settings
        query_dict = {}
        query_dict['alert'] = alert

        collection_name = "incident_settings"
        collection = service.kvstore[collection_name]
        query = json.dumps(query_dict)

        data = collection.data.query(query=query)

        drilldown_references = data[0].get('drilldowns')

        # Get Drilldown Settings
        if len(drilldown_references) > 0:
            query_dict = {}

            drilldown_references = drilldown_references.split()

            query_prefix = '{ "$or": [ '

            for drilldown_reference in drilldown_references:
                query_prefix += '{ "name": "' + drilldown_reference + '" } '

            query_prefix = query_prefix + '] }'

            collection_name = "drilldown_actions"
            collection = service.kvstore[collection_name]
            query = query_prefix.replace("} {", "}, {")

            data = collection.data.query(query=query)

            drilldowns = []

            # Substitute variables with field values
            for drilldown_action in data:

                url = drilldown_action.get("url")
                label = drilldown_action.get("label")

                url = re.sub(r'(?<=\w)\$', '', url)

                class FieldTemplate(StringTemplate):
                    idpattern = r'[a-zA-Z][_a-zA-Z0-9.]*'

                url_template = FieldTemplate(url)

                url = url_template.safe_substitute(incident_data)

                drilldown = r'''{{ "label": "{}", "url": "{}" }}'''.format(
                    label, url)

                yield (json.loads(drilldown))