def get_credentials(session_key): """ Reads the user's Twitter credentials from the `admin/passwords` endpoint on the Splunk server. These credentials are entered by the user on the setup page for this app, which is defined by `setup.xml`. """ # NOTE: Requires 'develop' version of splunklib past 0.8.0 # for 'token' parameter to be honored. service = splunklib.client.Service( host=splunk.getDefault('host'), port=splunk.getDefault('port'), scheme=splunk.getDefault('protocol'), owner='nobody', app='twitter2', token='Splunk %s' % session_key) # Return first set of credentials passwords = splunklib.client.Collection(service, 'admin/passwords') for password in passwords: return password['username'], password['clear_password'] sys.stderr.write('Could not get Twitter credentials from splunk. Error: No credentials supplied, please complete the Twitter app setup\n') exit(1)
def get_basepath(self): host = splunk.getDefault('host') if ':' in host: host = '[%s]' % host uri = '%s://%s:%s' % \ (splunk.getDefault('protocol'), host, splunk.getDefault('port')) return uri
def get_all_apps(self, **params): host = getDefault('host') port = getDefault('port') protocol = getDefault('protocol') token = self.get_session_key() service = Service(token=token, host=host, port=port, scheme=protocol) apps = [] for app in service.apps: if app['content']['disabled'] == '0': apps.append({"name": app['name']}) return self.render_json(apps)
def get_all_indexes(self, **params): host = getDefault('host') port = getDefault('port') protocol = getDefault('protocol') token = F5IndexHandler.get_session_key() service = Service(token=token, host=host, port=port, scheme=protocol) indexes = [{"name": "default"}] for index in service.indexes: if index['content']['disabled'] == '0' and index['content'][ 'isInternal'] == '0': indexes.append({"name": index['name']}) return self.render_json(indexes)
def testListing(self): listing = getEntities('saved/searches', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) self.assert_('Errors in the last hour' in listing) entityList = getEntitiesList('saved/searches', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) listContainsSearch = False for entity in entityList: if entity.name == 'Errors in the last hour': listContainsSearch = True break self.assert_(listContainsSearch)
def get_oauth_settings(session_key): """ Retrieves OAuth settings from args. :param session_key: A value identifying the current Splunk session. :return: OAuth settings tuple: 'app_key', 'app_secret', 'oauth_token', and 'oauth_token_secret' """ # NOTE: Requires 'develop' version of splunklib past 0.8.0 for 'token' # parameter to be honored service = splunklib.client.Service( host=splunk.getDefault("host"), port=splunk.getDefault("port"), scheme=splunk.getDefault("protocol"), owner="nobody", app="twitter2", token="Splunk %s" % session_key, ) passwords = splunklib.client.Collection(service, "admin/passwords") oauth_settings = None for password in passwords: oauth_settings = password break if oauth_settings is None: sys.stderr.write( "Could not retrieve Twitter OAuth settings from Splunk. Set up " + "the app to correct this issue.\n" ) exit(1) app_key = oauth_settings.content["realm"] oauth_token = oauth_settings.content["username"] secrets = oauth_settings.content["clear_password"] if None in (app_key, oauth_token, secrets): sys.stderr.write( "Splunk returned incomplete Twitter OAuth settings. Set up the " + "app to correct this issue.\n" ) exit(1) try: (app_secret, oauth_token_secret) = secrets.split(":") except ValueError as e: sys.stderr.write( "Could not parse the Twitter OAuth secrets returned by Splunk: " "%s. Set up the app to correct this issue.\n" % e.message ) exit(1) return app_key, app_secret, oauth_token, oauth_token_secret
def setupSavedSearchTest(self): sessionKey = auth.getSessionKey('admin', 'changeme') label = '12349876 foobar' searchString = 'error sourcetype="something" host="nothing"' # Ensure that saved search 'label' doesn't already exist try: newSavedSearch = createSavedSearch(searchString, label, namespace=splunk.getDefault('namespace'), sessionKey=sessionKey) history = getSavedSearchHistory(label) for job_id in history: splunk.search.getJob(job_id).cancel() except splunk.RESTException, e: deleteSavedSearch(label, namespace=splunk.getDefault('namespace')) newSavedSearch = createSavedSearch(searchString, label, namespace=splunk.getDefault('namespace'), sessionKey=sessionKey)
def do_additional_setup(self): # set log level log_level = self.inputs.get('job', {}).get('log_level', 'WARNING') logger.setLevel(log.parse_log_level(log_level)) # set up message service self.splunkd_messages_service = Service(port=getDefault('port'), token=session['authtoken'], app=APP_NAME, owner='nobody').messages # set up conf file manager self.inputs_conf = conf_manager.ConfManager( session['authtoken'], APP_NAME, port=getDefault('port')).get_conf('inputs')
def __init__(self, owner, namespace, conf_name, session_key): # NOTE: Requires 'develop' version of splunklib past 0.8.0 # for 'token' parameter to be honored. service = splunklib.client.Service( host=splunk.getDefault('host'), port=splunk.getDefault('port'), scheme=splunk.getDefault('protocol'), owner=owner, app=namespace, token='Splunk %s' % session_key) self._stanzas = {} for stanza in service.confs[conf_name]: self._stanzas[stanza.name] = stanza
def get_oauth_settings(session_key): """ Retrieves OAuth settings from args. :param session_key: A value identifying the current Splunk session. :return: OAuth settings tuple: 'app_key', 'app_secret', 'oauth_token', and 'oauth_token_secret' """ # NOTE: Requires 'develop' version of splunklib past 0.8.0 for 'token' # parameter to be honored service = splunklib.client.Service(host=splunk.getDefault('host'), port=splunk.getDefault('port'), scheme=splunk.getDefault('protocol'), owner='nobody', app='twitter2', token='Splunk %s' % session_key) passwords = splunklib.client.Collection(service, 'admin/passwords') oauth_settings = None for password in passwords: oauth_settings = password break if oauth_settings is None: sys.stderr.write( 'Could not retrieve Twitter OAuth settings from Splunk. Set up ' + 'the app to correct this issue.\n') exit(1) app_key = oauth_settings.content['realm'] oauth_token = oauth_settings.content['username'] secrets = oauth_settings.content['clear_password'] if None in (app_key, oauth_token, secrets): sys.stderr.write( 'Splunk returned incomplete Twitter OAuth settings. Set up the ' + 'app to correct this issue.\n') exit(1) try: (app_secret, oauth_token_secret) = secrets.split(':') except ValueError as e: sys.stderr.write( 'Could not parse the Twitter OAuth secrets returned by Splunk: ' '%s. Set up the app to correct this issue.\n' % e.message) exit(1) return app_key, app_secret, oauth_token, oauth_token_secret
def get_oauth_settings(session_key): """ Retrieves OAuth settings from args. :param session_key: A value identifying the current Splunk session. :return: OAuth settings tuple: 'app_key', 'app_secret', 'oauth_token', and 'oauth_token_secret' """ # NOTE: Requires 'develop' version of splunklib past 0.8.0 for 'token' # parameter to be honored service = splunklib.client.Service( host=splunk.getDefault('host'), port=splunk.getDefault('port'), scheme=splunk.getDefault('protocol'), owner='nobody', app='twitter2', token='Splunk %s' % session_key) try: conf = service.confs['twitter-application'] except KeyError: sys.stderr.write( 'Configuration file local/twitter-application.conf is missing. ' + 'Please recreate this file or reinstall the Splunk-Twitter ' + 'Connector app.\n' ) exit(1) try: stanza = conf['oauth'] except KeyError: sys.stderr.write( 'Configuration file local/twitter-application.conf does not ' + 'contain an [oauth] stanza. Please recreate this stanza ' + 'or reinstall the Splunk-Twitter Connector app.\n') exit(1) app_key = stanza.content['app_key'] app_secret = stanza.content['app_secret'] oauth_token = stanza.content['oauth_token'] oauth_token_secret = stanza.content['oauth_token_secret'] if None in (app_key, app_secret, oauth_token, oauth_token_secret): sys.stderr.write( 'Could not get Twitter OAuth settings from Splunk. Complete ' + 'application setup to correct this issue.\n') exit(1) return app_key, app_secret, oauth_token, oauth_token_secret
def testListing(self): listing = getEntities('saved/searches', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) self.assert_('Errors in the last hour' in listing)
def preview_edit(self, **kwargs): if 'preview_continue_link' in cherrypy.session: continue_link = cherrypy.session['preview_continue_link'] else: continue_link = self.make_url(FAILSAFE_CONTINUE_LINK, _qs={'preflight':'preview'}) ns = kwargs.get('ns', splunk.getDefault('namespace')) template_args = { 'ns': kwargs.get('ns', splunk.getDefault('namespace')), 'source': kwargs.get('source'), 'continue_to': continue_link, 'return_to': util.make_url_internal(kwargs.get('return_to')), 'reset_to': kwargs.get('reset_to'), 'breadcrumbs': self.prepare_breadcrumbs(kwargs.get('breadcrumbs',''), ns) } return self.render_template('/splunk_datapreview:/templates/edit.html', template_args)
def renderModule(self, host_app, module, action, **args): ''' Provides generic module content rendering endpoint. The base module JS dispatcher will always append a 'client_app' param that contains the app context from which this request was made. It is entirely different from the host_app where this module resides. ''' # strip out the cache defeater args.pop('_', None) if not self._isModuleClassInApp(module, host_app): logger.warn('Could not load module "%s" in host app "%s"' % (module, host_app)) return _('Could not find module "%(module)s" in the following host app "%(host_app)s"') % {'module':su.escape(module), 'host_app':su.escape(host_app)} args['host_app'] = host_app # put in default client_app if incoming request did not have one args.setdefault('client_app', splunk.getDefault('namespace')) # TODO: change me when the modules are registered under a module try: module_name = module.split('.').pop() handler = getattr(sys.modules[__name__], module_name) except Exception, e: logger.exception(e) traceback.print_exc(e) return _('Splunk could not find a controller to import for the following module: "%s".') % su.escape(module)
def testSearchFilterListing(self): filters = 'access_*' listing = getEntities('saved/searches', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, search=filters, owner=self.owner) self.assert_('Splunk errors last 24 hours' not in listing) self.assert_('Errors in the last 24 hours' in listing)
def enable(self, appid, state=None, return_to=None, breadcrumbs=None, enable=None, **kw): """Enable a disabled app""" if state: state = StateDict.unserialize(state) breadcrumbs = state.get('breadcrumbs') else: state = StateDict({ 'return_to': return_to if return_to else self.make_url( ['manager', splunk.getDefault('namespace')], translate=False), 'breadcrumbs': breadcrumbs }) entityURI = '/apps/local/' + appid + '/enable' en.controlEntity('enable', entityURI, sessionKey=cherrypy.session['sessionKey']) logger.info("App %s enabled" % appid) return self.checkstatus(appid, state=state)
def prompt(self, **kwargs): # determine input type if kwargs.get('endpoint_base') == 'data/inputs/monitor': input_type = 'file' elif kwargs.get('endpoint_base') == 'data/inputs/tcp/raw': input_type = 'tcp' elif kwargs.get('endpoint_base') == 'data/inputs/udp': input_type = 'udp' else: input_type = None ns = kwargs.get('ns', splunk.getDefault('namespace')) bc = kwargs.get('breadcrumbs', '') crumbs = self.prepare_breadcrumbs(bc, ns) # get the preview limit props = splunk.bundle.getConf('limits') limit_bytes = 0 try: limit_bytes = int(props['indexpreview']['max_preview_bytes'] or 0) except Exception, e: logger.warn( 'could not read preview indexing limit value from conf; skipping' )
def upload(self, appid, return_to=None, breadcrumbs=None, state=None, appfile=None, force=None, **kw): """ Present a form for direct upload of an app """ if state: state = StateDict.unserialize(state) breadcrumbs = state.get('breadcrumbs') else: breadcrumbs = parse_breadcrumbs_string(breadcrumbs) breadcrumbs.append([_('Upload app'), None]) state = StateDict({ 'return_to': return_to if return_to else self.make_url(['manager', splunk.getDefault('namespace'), 'apps','local'], translate=False), 'breadcrumbs': breadcrumbs }) error = None if appfile is not None and cherrypy.request.method == 'POST': try: force = (force == '1') appid = self.processAppUpload(appfile, force) module.moduleMapper.resetInstalledModules() memoizedViews.clearCachedViews() return self.checkstatus(appid, state=state) except SBFileUploadException, e: error = e.message except splunk.RESTException, e: error = e.get_extended_message_text()
def upload(self, appid, return_to=None, breadcrumbs=None, state=None, appfile=None, force=None, **kw): """ Present a form for direct upload of an app """ if state: state = StateDict.unserialize(state) breadcrumbs = state.get('breadcrumbs') else: breadcrumbs = parse_breadcrumbs_string(breadcrumbs) breadcrumbs.append([_('Upload app'), None]) state = StateDict({ 'return_to': return_to if return_to else self.make_url( ['manager', splunk.getDefault('namespace')], translate=False), 'breadcrumbs': breadcrumbs }) error = None if appfile is not None and cherrypy.request.method == 'POST': try: force = (force == '1') appid = self.processAppUpload(appfile, force) module.moduleMapper.resetInstalledModules() memoizedViews.clearCachedViews() return self.checkstatus(appid, state=state) except SBFileUploadException, e: error = e.message
def do_additional_setup(self): log_level = self.inputs.get('restarter').get('log_level', 'INFO') logger.setLevel(log.parse_log_level(log_level)) self.splunkd_messages_service = Service(port=getDefault('port'), token=self.session_key, app=em_constants.APP_NAME, owner='nobody').messages
def get_oauth_settings(session_key): """ Retrieves OAuth settings from args. :param session_key: A value identifying the current Splunk session. :return: OAuth settings tuple: 'app_key', 'app_secret', 'oauth_token', and 'oauth_token_secret' """ # NOTE: Requires 'develop' version of splunklib past 0.8.0 for 'token' # parameter to be honored service = splunklib.client.Service(host=splunk.getDefault('host'), port=splunk.getDefault('port'), scheme=splunk.getDefault('protocol'), owner='nobody', app='twitter2', token='Splunk %s' % session_key) try: conf = service.confs['twitter-application'] except KeyError: sys.stderr.write( 'Configuration file local/twitter-application.conf is missing. ' + 'Please recreate this file or reinstall the Splunk-Twitter ' + 'Connector app.\n') exit(1) try: stanza = conf['oauth'] except KeyError: sys.stderr.write( 'Configuration file local/twitter-application.conf does not ' + 'contain an [oauth] stanza. Please recreate this stanza ' + 'or reinstall the Splunk-Twitter Connector app.\n') exit(1) app_key = stanza.content['app_key'] app_secret = stanza.content['app_secret'] oauth_token = stanza.content['oauth_token'] oauth_token_secret = stanza.content['oauth_token_secret'] if None in (app_key, app_secret, oauth_token, oauth_token_secret): sys.stderr.write( 'Could not get Twitter OAuth settings from Splunk. Complete ' + 'application setup to correct this issue.\n') exit(1) return app_key, app_secret, oauth_token, oauth_token_secret
def __init__(self): self.svc = Service(port=getDefault('port'), token=session['authtoken'], app=em_constants.APP_NAME, owner='nobody') self.savedsearch_with_states = [] self._prepare_savedsearches() self.checkpoint = MigrationProcessControlCheckpoint.get_or_create()
def generate(self): # connect to splunk and start execution port = splunk.getDefault('port') service = splunklib.client.connect( token=self._metadata.searchinfo.session_key, port=port, owner="nobody", app="Splunk_ASX") API_URL = self.getURL() asx_lib = ASXLib(service, API_URL) self.logger.info("asxupdate.py - start") if self.list_all: self.logger.info("asxupdate.py - list all stories") stories = asx_lib.list_analytics_stories() for story in stories: self.logger.info( "asxupdate.py - processing story {0}".format(story)) yield { '_time': time.time(), 'sourcetype': "_json", '_raw': { 'name': story }, 'status': "successfully listed all stories" } # only updating specific stories if self.story and self.story != "all": self.logger.info("asxupdate.py - stories to update {0}".format( self.story)) stories = self.story.split(",") for story in stories: self.logger.info( "asxupdate.py - updating story {0}".format(story)) asx_lib.get_analytics_story(story) yield { '_time': time.time(), 'sourcetype': "_json", '_raw': story, 'status': "successfully updated story" } # lets update all stories, disabled until spec 3.0 change else: self.logger.info("asxupdate.py - updating ALL stories") stories = asx_lib.list_analytics_stories() for story in stories: self.logger.info( "asxupdate.py - updating story {0}".format(story)) #asx_lib.get_analytics_story(story) yield { '_time': time.time(), 'sourcetype': "_json", '_raw': story, 'status': "successfully updated story" } self.logger.info("asxupdate.py - COMPLETED")
def conf_stanzas(cls): svc = Service( port=getDefault('port'), token=session['authtoken'], app=cls.app_name(), owner='nobody', ) conf = svc.confs[cls.storage_name()] return conf
def do_additional_setup(self): log_level = self.inputs.get('job', {}).get('log_level', 'WARNING') logger.setLevel(log.parse_log_level(log_level)) self.service = Service( port=getDefault('port'), token=session['authtoken'], app=em_constants.APP_NAME, owner='nobody', )
def store(cls): svc = Service( port=getDefault('port'), token=session['authtoken'], app=cls.app_name(), owner='nobody', ) store = svc.kvstore[cls.storage_name()] return store
def testUpdate(self): search = getEntity('saved/searches', 'Messages by minute last 3 hours', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) testvalue = 'test subject %s' % str(time.time()) search['action.email.subject'] = testvalue setEntity(search) challenge = getEntity('saved/searches', 'Messages by minute last 3 hours', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) self.assertEquals(challenge['action.email.subject'], testvalue)
def testListing(self): listing = getEntities('saved/searches', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) self.assert_('Errors in the last hour' in listing) entityList = getEntitiesList( 'saved/searches', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) listContainsSearch = False for entity in entityList: if entity.name == 'Errors in the last hour': listContainsSearch = True break self.assert_(listContainsSearch)
def default(self, host_app=None, filename=None, template=None, count=10000, **kwargs): """ create excel report """ try: count = abs(int(count)) except: logger.warn( 'given count %s is not a positive integer, reverting to 10000' % count) count = 10000 if count > 1000000: count = 1000000 logger.warn( 'count %s was reduced so as not to exceed excel max row count' % count) if not filename: filename = 'splunk_report.xlsx' elif not filename.endswith('.xlsx'): logger.warn( 'xls file extension will be appended to given filename %s ' % filename) filename = '.'.join([filename, 'xlsx']) user = cherrypy.session['user']['name'] token = cherrypy.session.get('sessionKey') host = splunk.getDefault('host') port = splunk.getDefault('port') use_ssl = splunk.util.normalizeBoolean( splunk.rest.simpleRequest( '/services/properties/server/sslConfig/enableSplunkdSSL')[1]) try: fetcher = JSONHttpsClient(host_app, user, token, host, port, use_ssl) except Exception, ex: logger.exception(ex) raise
def generate_framework_config(global_cfg, django_cfg, path, generate_secret_key): server_ssl_config = splunk_to_cherry_cfg("server", "sslConfig") splunk_home = os.environ['SPLUNK_HOME'] splunkweb_scheme = "https" if normalizeBoolean(global_cfg.get('enableSplunkWebSSL', False)) else "http" splunkweb_host = "localhost" splunkweb_port = int(global_cfg.get("httpport")) splunkweb_mount = global_cfg.get('root_endpoint', FAILSAFE_ROOT_ENDPOINT).strip('/') splunkd_scheme = "https" if normalizeBoolean(server_ssl_config.get('enableSplunkdSSL', False)) else "http" splunkd_host = splunk.getDefault("host") splunkd_port = splunk.getDefault("port") x_frame_options_sameorigin = normalizeBoolean(global_cfg.get('x_frame_options_sameorigin', True)) mount = raw_mount = "dj" proxy_path = "/en-us/splunkd/__raw" if splunkweb_mount: mount = "/%s/%s" % (splunkweb_mount, mount) proxy_path = "/%s%s" % (splunkweb_mount, proxy_path) if ":" in splunkd_host: splunkd_host = "[%s]" % splunkd_host import appdo return appdo.create_config_file( config_file_path = path, generate_secret_key = generate_secret_key, splunk_home = splunk_home, splunkd_scheme = splunkd_scheme, splunkd_host = splunkd_host, splunkd_port = int(splunkd_port), splunkweb_scheme = splunkweb_scheme, splunkweb_host = splunkweb_host, splunkweb_port = int(splunkweb_port), splunkweb_mount = splunkweb_mount, splunkdj_port = int(splunkweb_port), x_frame_options_sameorigin = x_frame_options_sameorigin, mount = mount, raw_mount = raw_mount, proxy_path = proxy_path, debug = False, quickstart = False, splunkweb_integrated = True )
def submit(event, hostname=None, source=None, sourcetype=None, index=None): """ the interface to the 'simple' receivers endpoint """ global h #construct the uri to POST to base_uri = splunk.mergeHostPath() postargs = { 'host': hostname, 'source': source, 'sourcetype': sourcetype, 'index': index } uri = base_uri + '/services/receivers/simple?%s' % urlencode(postargs) #get default session key. If none exists, the rest call will raise a splunk.AuthenticationFailed exception sessionKey = splunk.getDefault('sessionKey') #make the call, we cannot use the rest interface here as it urlencodes the payload serverResponse, serverContent = h.request( uri, "POST", headers={'Authorization': 'Splunk %s' % sessionKey}, body=event) #process results root = et.fromstring(serverContent) #4xx error messages indicate a client side error e.g. bad request, unauthorized etc so raise a RESTException if 400 <= serverResponse.status < 500: extractedMessages = rest.extractMessages(root) msg_text = [] for msg in extractedMessages: msg_text.append( 'message type=%(type)s code=%(code)s text=%(text)s;' % msg) raise splunk.RESTException, (serverResponse.status, msg_text) #5xx error messages indicate server side error e.g. Internal server error etc so raise a SplunkdException elif serverResponse.status >= 500: extractedMessages = rest.extractMessages(root) msg_text = [] for msg in extractedMessages: msg_text.append( 'message type=%(type)s code=%(code)s text=%(text)s;' % msg) raise splunk.SplunkdException, (serverResponse.status, msg_text) #everything is kosher... else: return serverResponse
def setup(cls, session_key): """ Set up sesison key and conf manager. NOTE: Must be done before performing any further actions """ cls.conf_manager = conf_manager.ConfManager(session_key, em_constants.APP_NAME, port=getDefault('port')) try: cls.conf = get_conf_stanza(cls.conf_manager, WEBHOOK_CONF_FILE) except Exception: return EMWebhook.error_rest_api_response( message=WEBHOOK_REST_API_GET_ERROR_MESSAGE)
def _hasReadPerms(self): ''' Use services/server/settings as a proxy for read permissions. ''' # NOTE:Due SPL-21113 BETA: unify ACL actions to read/write we cannot use the settings endpoint defer to user admin for now. return True if 'admin' == au.getCurrentUser()['name'] else False entity = None try: entity = en.getEntity('/server/', 'settings', namespace=splunk.getDefault('namespace')) except Exception, e: return False
def __init__(self, logger, session_key): super(AlertsMigrationHandler, self).__init__(logger, session_key) self.saved_search_manager = SavedSearchManager( session_key=self.session_key, server_uri=em_common.get_server_uri(), app=em_constants.APP_NAME, ) self.ACL_manager = ACLManager( self.session_key, app=em_constants.APP_NAME, port=getDefault('port'), )
def setup(cls, session_key): """ Set up sesison key and conf manager. NOTE: Must be done before performing any further actions """ EMVictorOps.SESSION_KEY = session_key cls.conf_manager = conf_manager.ConfManager(EMVictorOps.SESSION_KEY, em_constants.APP_NAME, port=getDefault('port')) try: cls.conf = get_conf_stanza(cls.conf_manager, VICTOROPS_CONF_FILE) except Exception: return EMVictorOps.error_rest_api_response( message=VICTOROPS_REST_API_GENERAL_ERROR_MESSAGE)
def enable(self, appid, state=None, return_to=None, breadcrumbs=None, enable=None, **kw): """Enable a disabled app""" if state: state = StateDict.unserialize(state) breadcrumbs = state.get('breadcrumbs') else: state = StateDict({ 'return_to': return_to if return_to else self.make_url(['manager', splunk.getDefault('namespace'), 'apps','local'], translate=False), 'breadcrumbs': breadcrumbs }) entityURI = '/apps/local/'+appid+'/enable' en.controlEntity('enable', entityURI, sessionKey=cherrypy.session['sessionKey']) logger.info("App %s enabled" % appid) return self.checkstatus(appid, state=state)
def preview_edit(self, **kwargs): if 'preview_continue_link' in cherrypy.session: continue_link = cherrypy.session['preview_continue_link'] else: continue_link = self.make_url(FAILSAFE_CONTINUE_LINK, _qs={'preflight': 'preview'}) ns = kwargs.get('ns', splunk.getDefault('namespace')) template_args = { 'ns': kwargs.get('ns', splunk.getDefault('namespace')), 'source': kwargs.get('source'), 'continue_to': continue_link, 'return_to': util.make_url_internal(kwargs.get('return_to')), 'reset_to': kwargs.get('reset_to'), 'breadcrumbs': self.prepare_breadcrumbs(kwargs.get('breadcrumbs', ''), ns) } return self.render_template('/splunk_datapreview:/templates/edit.html', template_args)
def testSingle(self): entity = getEntity('saved/searches', 'Errors in the last 24 hours', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) self.assert_(isinstance(entity, Entity)) self.assertEquals(entity.name, 'Errors in the last 24 hours') self.assertEquals( entity['search'], 'error OR failed OR severe OR ( sourcetype=access_* ( 404 OR 500 OR 503 ) )' )
def getCurrentUser(): ''' Retrieves current user info from cherrypy session ''' cherryname = None if hasattr(__main__, 'IS_CHERRYPY'): import cherrypy cherryname = cherrypy.session.get('user', {}).get('name') if cherryname: cherryname = cherryname.strip().lower() return { 'userid': '-1', 'name': cherryname or splunk.getDefault('username') or 'UNDEFINED_USERNAME', 'realname': 'UNDEFINED_REALNAME', 'roles': ['UNDEFINED_ROLES'] }
def getCurrentUser(): ''' TODO: ask splunkd for the currently auth'ed user info what if there are > 1? ''' cherryname = None if hasattr(__main__, 'IS_CHERRYPY'): import cherrypy cherryname = cherrypy.session.get('user', {}).get('name') return { 'userid': '-1', 'name': cherryname or splunk.getDefault('username') or 'UNDEFINED_USERNAME', 'realname': 'UNDEFINED_REALNAME', 'roles': ['UNDEFINED_ROLES'] }
def status(self, **args): ''' Provides a debug output page for appserver config ''' hasReadPerms = self._hasReadPerms() # get overview items general = splunk.util.OrderedDict() general['Appserver boot path'] = getattr(__main__,'__file__', '<N/A>') general['Splunkd URI'] = splunk.mergeHostPath() general['Debug Mode'] = __debug__ # get various dicts configController = ConfigController() uiConfig = configController.index(asDict=True) mm = moduleMapper moduleMap = mm.getInstalledModules() uiPanels = splunk.util.OrderedDict() uiPanels['config'] = uiConfig uiPanels['views'] = en.getEntities(view.VIEW_ENTITY_CLASS, namespace=splunk.getDefault('namespace')) uiPanels['modules'] = moduleMap uiPanels['cherrypy'] = cherrypy.config uiPanels['request'] = args uiPanels['wsgi'] = cherrypy.request.wsgi_environ splunkdPanels = splunk.util.OrderedDict() #code to display splunkd debug information as well try: serverResponse, serverContent = splunk.rest.simpleRequest('/services/debug/status', sessionKey=cherrypy.session['sessionKey']) atomFeed = splunk.rest.format.parseFeedDocument(serverContent) atomFeed_prim = atomFeed.toPrimitive() general['Splunkd time'] = splunk.util.getISOTime(atomFeed.updated) general['Splunkd home'] = atomFeed_prim.get('SPLUNK_HOME', '<unknown>') for key in atomFeed_prim: splunkdPanels[key] = atomFeed_prim[key] except splunk.AuthenticationFailed, e: splunkdPanels['errors'] = 'The appserver is not authenticated with splunkd; retry login'
def submit(event, hostname=None, source=None, sourcetype=None, index=None): """ the interface to the 'simple' receivers endpoint """ global h #construct the uri to POST to base_uri = splunk.mergeHostPath() postargs = {'host': hostname, 'source': source, 'sourcetype' : sourcetype, 'index':index} uri = base_uri + '/services/receivers/simple?%s' % urlencode(postargs) #get default session key. If none exists, the rest call will raise a splunk.AuthenticationFailed exception sessionKey = splunk.getDefault('sessionKey') #make the call, we cannot use the rest interface here as it urlencodes the payload serverResponse, serverContent = h.request(uri, "POST", headers={'Authorization':'Splunk %s' % sessionKey}, body=event) #process results root = et.fromstring(serverContent) #4xx error messages indicate a client side error e.g. bad request, unauthorized etc so raise a RESTException if 400 <= serverResponse.status < 500: extractedMessages = rest.extractMessages(root) msg_text = [] for msg in extractedMessages: msg_text.append('message type=%(type)s code=%(code)s text=%(text)s;' % msg) raise splunk.RESTException, (serverResponse.status, msg_text) #5xx error messages indicate server side error e.g. Internal server error etc so raise a SplunkdException elif serverResponse.status >= 500: extractedMessages = rest.extractMessages(root) msg_text = [] for msg in extractedMessages: msg_text.append('message type=%(type)s code=%(code)s text=%(text)s;' % msg) raise splunk.SplunkdException, (serverResponse.status, msg_text) #everything is kosher... else: return serverResponse
def prompt(self, **kwargs): # determine input type if kwargs.get('endpoint_base') == 'data/inputs/monitor': input_type = 'file' elif kwargs.get('endpoint_base') == 'data/inputs/tcp/raw': input_type = 'tcp' elif kwargs.get('endpoint_base') == 'data/inputs/udp': input_type = 'udp' else: input_type = None ns = kwargs.get('ns', splunk.getDefault('namespace')) bc = kwargs.get('breadcrumbs', '') crumbs = self.prepare_breadcrumbs(bc, ns) # get the preview limit props = splunk.bundle.getConf('limits') limit_bytes = 0 try: limit_bytes = int(props['indexpreview']['max_preview_bytes'] or 0) except Exception, e: logger.warn('could not read preview indexing limit value from conf; skipping')
def simpleRequest(path, sessionKey=None, getargs=None, postargs=None, method='GET', raiseAllErrors=False, proxyMode=False, rawResult=False, timeout=SPLUNKD_CONNECTION_TIMEOUT): """ Makes an HTTP call to the main splunk REST endpoint path: the URI to fetch If given a relative URI, then the method will normalize to the splunkd default of "/services/...". If given an absolute HTTP(S) URI, then the method will use as-is. If given a 'file://' URI, then the method will attempt to read the file from the local filesystem. Only files under $SPLUNK_HOME are supported, so paths are 'chrooted' from $SPLUNK_HOME. getargs: dict of k/v pairs that are always appended to the URL postargs: dict of k/v pairs that get placed into the body of the request. If postargs is provided, then the HTTP method is auto assigned to POST. method: the HTTP verb - [GET | POST | DELETE | PUT] raiseAllErrors: indicates if the method should raise an exception if the server HTTP response code is >= 400 rawResult: don't raise an exception if a non 200 response is received; return the actual response Return: This method will return a tuple of (serverResponse, serverContent) serverResponse: a dict of HTTP status information serverContent: the body content """ # if absolute URI, pass along as-is if path.startswith('http'): uri = path # if file:// protocol, try to read file and return # the serverStatus is just an empty dict; file contents are in serverResponse # TODO: this probably doesn't work in windows elif path.startswith('file://'): workingPath = path[7:].strip(os.sep) lines = util.readSplunkFile(workingPath) return ({}, ''.join(lines)) else: # prepend convenience root path if not path.startswith(REST_ROOT_PATH): path = REST_ROOT_PATH + '/' + path.strip('/') # setup args host = splunk.getDefault('host') if ':' in host: host = '[%s]' % host uri = '%s://%s:%s/%s' % \ (splunk.getDefault('protocol'), host, splunk.getDefault('port'), path.strip('/')) if getargs: getargs = dict([(k,v) for (k,v) in getargs.items() if v != None]) uri += '?' + util.urlencodeDict(getargs) # proxy mode bypasses all header passing headers = {} sessionSource = 'direct' if not proxyMode: # get session key from known places: first the appserver session, then # the default instance cache if not sessionKey: sessionKey, sessionSource = splunk.getSessionKey(return_source=True) headers['Authorization'] = 'Splunk %s' % sessionKey payload = '' if postargs and method in ('GET', 'POST', 'PUT'): if method == 'GET': method = 'POST' payload = util.urlencodeDict(postargs) # # make request # if logger.level <= logging.DEBUG: if uri.lower().find('login') > -1: logpayload = '[REDACTED]' else: logpayload = payload #logger.debug('simpleRequest >>>\n\tmethod=%s\n\turi=%s\n\tbody=%s' % (method, uri, logpayload)) logger.debug('simpleRequest > %s %s [%s] sessionSource=%s' % (method, uri, logpayload, sessionSource)) t1 = time.time() # Add wait and tries to check if the HTTP server is up and running tries = 4 wait = 10 try: for aTry in range(tries): h = httplib2.Http(timeout=timeout, disable_ssl_certificate_validation=True) if WEB_KEYFILE and WEB_CERTFILE: h.add_certificate(WEB_KEYFILE, WEB_CERTFILE, '') serverResponse, serverContent = h.request(uri, method, headers=headers, body=payload) if serverResponse == None: if aTry < tries: time.sleep(wait) else: break except socket.error, e: raise splunk.SplunkdConnectionException, str(e)
def pdf_echo_loopback(self): ''' Adjunct endpoint used with above PDF test echo page that proxies the generated PDF back to the test page ''' # set default PDF server URI pdfServerUri = '%s://%s/services/pdfserver/renderpdf' % (splunk.getDefault('protocol'), cherrypy.config.get('mgmtHostPort')) # get alternate PDF server URI; values seem to be varied so we normalize alertSettings = en.getEntity('configs/conf-alert_actions', 'email', namespace='search') if alertSettings.get('reportServerURL') and alertSettings['reportServerURL'].strip(): pdfServerUri = alertSettings['reportServerURL'].strip() url = urlsplit(pdfServerUri) if len(url.path)<2: url = url._asdict() url['path'] = '/services/pdfserver/renderpdf' pdfServerUri = urlunsplit(SplitResult(**url)) # determine the external address that is most likely accessible urlparts = urlparse.urlparse(pdfServerUri) ai = socket.getaddrinfo(urlparts.hostname, int(urlparts.port or 80), socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)[0] af, socktype, proto, canonname, hostport = ai appserverHost = alertSettings.get('hostname') and alertSettings['hostname'].strip() if appserverHost: logger.info('using configured appserver hostname "%s"' % appserverHost) else: s = socket.socket(af, socktype, proto) s.connect(hostport) sockname = s.getsockname() logger.info('most promising interface looks like %s' % sockname[0]) appserverHost = sockname[0] appserverProtocol = 'https' if splunk.util.normalizeBoolean(cherrypy.config.get('enableSplunkWebSSL', False)) else 'http' # create a fake sso-bypass session utilizing the user's current sessionKey active_session = cherrypy.serving.session session_args = ('timeout', 'clean_freq', 'storage_path', 'servers') args = dict([ (arg_name, getattr(active_session, arg_name)) for arg_name in session_args if hasattr(active_session, arg_name)]) fake_session = cherrypy.serving.session.__class__(**args) fake_session['sessionKey'] = cherrypy.session['sessionKey'] fake_session['SSO_DISABLE'] = 1 fake_session.save() fake_session.release_lock() cherrypy.session.release_lock() # set GET args args = { 'target': '%s://%s:%s%s/debug/pdf_echo' % ( appserverProtocol, appserverHost if af == socket.AF_INET else '[%s]' % appserverHost, cherrypy.config['httpport'], cherrypy.request.script_name ), 'mode': 'default', 'session': fake_session.id } # fetch the SSL certificate, if any cert = cherrypy.request.app.root.report.get_cert() if cert: args['cert'] = cert logger.info('Testing PDF server=%s on URI=%s' % (pdfServerUri, args['target'])) # make a request to the registered PDF server for the echo page timeout = 20 h = httplib2.Http(timeout=timeout, disable_ssl_certificate_validation=True) start = time.time() try: serverResponse, serverContent = h.request(pdfServerUri, method='POST', body=urllib.urlencode(args)) except: if time.time() - start > (timeout-1): cherrypy.response.headers['content-type'] = 'text/plain' return "Timed out while waiting for a response" raise cherrypy.response.headers['content-type'] = 'application/pdf' return serverContent
def checkstatus(self, appid, state=None, return_to=None, checkstatus=None, **kw): """ Check the status of the installed app Is the app enabled? If not prompt for that Is a restart required? If so prompt for that Does the app need to be setup? If so prompt for that Else set a message and bounce the user back to the return_url """ if state: if not isinstance(state, StateDict): state = StateDict.unserialize(state) else: state = StateDict({ 'return_to': return_to if return_to else self.make_url(['manager', splunk.getDefault('namespace'), 'apps','local'], translate=False), }) app = self.getLocalApp(appid) if not app: logger.warn("Attempted to access appinstall/checkstatus point for non-installed app %s" % appid) return self.redirect_to_url(['/manager/appinstall', appid], _qs={'state': state.serialize()}) force = 0 #if self.isRestartRequired() or True: if self.isRestartRequired() or force: # check the user has restart privileges serverControls = en.getEntities("server/control") restartLink = filter((lambda x: x[0] == 'restart'), serverControls.links) displayRestartButton = len(restartLink)>0 return self.render_admin_template('/admin/appinstall/restart-required.html', { 'displayRestartButton': displayRestartButton, 'restart_target_url': self.make_url(['/manager/appinstall', appid, 'checkstatus'], _qs={'state': state.serialize()}), 'breadcrumbs': state.get('breadcrumbs', []), 'appid': appid, 'state': state }) # app is installed, does it need configuring? if self.appNeedsSetup(app): return self.render_admin_template('/admin/appinstall/setup-required.html', { 'app': app, 'state': state, 'breadcrumbs': state.get('breadcrumbs', []), 'setup_url': self.getSetupURL(appid, state) }) if self.appIsDisabled(app): return self.render_admin_template('/admin/appinstall/enable-required.html', { 'app': app, 'appid': appid, 'state': state, 'breadcrumbs': state.get('breadcrumbs', []) }) # else it's installed OK! try: msgid = MsgPoolMgr.get_poolmgr_instance()[UI_MSG_POOL].push('info', _('App "%(appname)s" was installed successfully') % {'appname': app.get('label', appid)}) except KeyError: msgid = '' return_to = state.get('return_to') return_to_success = state.get('return_to_success') if return_to_success: # an explicit success-page url was supplied return_to_success = return_to_success.replace('__appid__', splunk.util.safeURLQuote(unicode(appid))) return self.redirect_to_url(return_to_success, _qs={'msgid': msgid}) if return_to: # else use the default return to return self.redirect_to_url(return_to, _qs={'msgid': msgid}) return self.redirect_to_url(['manager', splunk.getDefault('namespace'), 'apps','local'], _qs={'msgid': msgid})
def login(self, username=None, password=None, return_to=None, cval=None, newpassword=None, **kwargs): # Force a refresh of startup info so that we know to # redirect if license stuff has expired. startup.initVersionInfo(force=True) updateCheckerBaseURL = self.getUpdateCheckerBaseURL() # set a long lived uid cookie self.updateCookieUID() templateArgs = self.getLoginTemplateArgs(return_to=return_to) if not return_to: return_to = '/' if return_to[0] != '/': return_to = '/' + return_to #dont allow new login if session established. if cherrypy.session.get('sessionKey') and return_to: raise cherrypy.HTTPRedirect(util.make_url_internal(return_to)) # Storm if cherrypy.config.get('storm_enabled'): return self.handleStormLogin(return_to=return_to, **kwargs) # # GET # if cherrypy.request.method == 'GET' and newpassword is None: # free license will auth on anything so statically seed if cherrypy.config.get('is_free_license'): # Start with a clean and minty fresh session cherrypy.session.regenerate() cherrypy.session['user'] = { 'name': 'admin', 'fullName': 'Administrator', 'id': 1 } sessionKey = splunk.auth.getSessionKey("admin", "freeneedsnopassword", hostPath=self.splunkd_urlhost) cherrypy.session['sessionKey'] = sessionKey if not updateCheckerBaseURL: return self.redirect_to_url('/app/%s' % splunk.getDefault('namespace')) # check for previously successful login templateArgs['hasLoggedIn'] = self.hasLoggedIn() if templateArgs['return_to'] is None and cherrypy.config.get('root_endpoint') not in ['/', None, '']: templateArgs['return_to'] = util.make_url_internal(cherrypy.config.get('root_endpoint')) # otherwise, show page return self.render_template('account/login.html', templateArgs) # # POST # # Check that the cookie we set when the login page was loaded has made it to us intact if 'cval' not in cherrypy.request.cookie or not self.cookieTest(cval): templateArgs['bad_cookies'] = 1 return self.render_template('account/login.html', templateArgs) ua = cherrypy.request.headers.get('user-agent', 'unknown') ip = cherrypy.request.remote.ip if username: username = username.strip().lower() try: sessionKey = splunk.auth.getSessionKey(username, password, hostPath=self.splunkd_urlhost, newPassword=newpassword) except splunk.AuthenticationFailed, e: logger.error('user=%s action=login status=failure ' \ 'reason=user-initiated useragent="%s" clientip=%s ERROR=%s' % (username, ua, ip, str(e.msg))) templateArgs['invalid_password'] = 1 forced_password_change = str(e.msg).count('fpc') forced_password_message = str(e.extendedMessages) if forced_password_change: templateArgs['fpc'] = True # cache current credentials in memory only credentials = {'username': username, 'password': password} with AccountController.credential_lock: AccountController.credential_cache[cherrypy.session.id] = credentials cherrypy.session['cval'] = cval cherrypy.session['fpc'] = True # forced password change templateArgs['err'] = _(forced_password_message) logger.info('user=%s action=login status=%s' % (username, forced_password_message)) return self.render_template('account/passwordchange.html', templateArgs) else: return self.render_template('account/login.html', templateArgs)
alert_track = util.normalizeBoolean(content['alert.track']) actions = util.normalizeBoolean(content.get('actions')) isRealtime = content['dispatch.earliest_time'].startswith('rt') and content['dispatch.latest_time'].startswith('rt') return is_scheduled and ((alert_type != 'always') or alert_track or (isRealtime and actions)) # //////////////////////////////////////////////////////////////////////////// # Test routines # //////////////////////////////////////////////////////////////////////////// if __name__ == '__main__': import unittest import time TEST_NAMESPACE = splunk.getDefault('namespace') TEST_OWNER = 'admin' class SavedSearchTests(unittest.TestCase): def assertGreaterThan(self, greaterThan, lessThan): self.assert_(greaterThan > lessThan) def assertLessThan(self, lessThan, greaterThan): self.assert_(greaterThan > lessThan) def setupSavedSearchTest(self): sessionKey = auth.getSessionKey('admin', 'changeme')
def streamingRequest(path, sessionKey=None, getargs=None, postargs=None, method='GET', timeout=SPLUNKD_CONNECTION_TIMEOUT): """ A streaming counterpart to simpleRequest Returns an instance of StreamingResponse which has a readall() method that will return a generator to stream a response from splundk rather than buffering it in memory """ # if absolute URI, pass along as-is if path.startswith('http'): uri = path pasrsedUri = urlsplit(uri) host = parsedUri.hostname path = parsedUri.path port = parsedUri.port else: # prepend convenience root path if not path.startswith(REST_ROOT_PATH): path = REST_ROOT_PATH + '/' + path.strip('/') # setup args host = splunk.getDefault('host') port = splunk.getDefault('port') urihost = '[%s]' % host if ':' in host else host uri = '%s://%s:%s/%s' % \ (splunk.getDefault('protocol'), urihost, port, path.strip('/')) if getargs: getargs = dict([(k,v) for (k,v) in getargs.items() if v != None]) querystring = '?' + util.urlencodeDict(getargs) uri += querystring path += querystring isssl = uri.startswith('https:') headers = {} sessionSource = 'direct' # get session key from known places: first the appserver session, then # the default instance cache if not sessionKey: sessionKey, sessionSource = splunk.getSessionKey(return_source=True) headers['Authorization'] = 'Splunk %s' % sessionKey payload = '' if postargs and method in ('GET', 'POST', 'PUT'): if method == 'GET': method = 'POST' payload = util.urlencodeDict(postargs) # # make request # if logger.level <= logging.DEBUG: if uri.lower().find('login') > -1: logpayload = '[REDACTED]' else: logpayload = payload logger.debug('streamingRequest > %s %s [%s] sessionSource=%s' % (method, uri, logpayload, sessionSource)) t1 = time.time() logger.debug('streamingRequest opening connection to host=%s path=%s method=%s postargs=%s payload=%s' % (host, path, method, postargs, payload)) try: conn = httplib.HTTPSConnection(host, port, WEB_KEYFILE, WEB_CERTFILE, False, timeout) if isssl else httplib.HTTPConnection(host, port, False, timeout) conn.connect() conn.putrequest(method, path) for key, val in headers.items(): conn.putheader(key, val) if payload: conn.putheader('Content-Type', 'application/x-www-form-urlencoded') conn.putheader('Content-Length', str(len(payload))) conn.endheaders() conn.send(payload) else: conn.endheaders() response = conn.getresponse() except socket.error, e: raise splunk.SplunkdConnectionException, str(e)
def testSingle(self): entity = getEntity('saved/searches', 'Errors in the last 24 hours', namespace=splunk.getDefault('namespace'), sessionKey=self.sessionKey, owner=self.owner) self.assert_(isinstance(entity, Entity)) self.assertEquals(entity.name, 'Errors in the last 24 hours') self.assertEquals(entity['search'], 'error OR failed OR severe OR ( sourcetype=access_* ( 404 OR 500 OR 503 ) )')
def login(self, username=None, password=None, return_to=None, cval=None, **kwargs): # Force a refresh of startup info so that we know to # redirect if license stuff has expired. startup.initVersionInfo(force=True) updateCheckerBaseURL = self.getUpdateCheckerBaseURL() # set a long lived uid cookie self.updateCookieUID() templateArgs = self.getLoginTemplateArgs(return_to=return_to, cval=cval) # Storm if cherrypy.config.get('storm_enabled'): return self.handleStormLogin(**kwargs) # # GET # if cherrypy.request.method == 'GET': # free license will auth on anything so statically seed if cherrypy.config.get('is_free_license'): # Start with a clean and minty fresh session cherrypy.session.regenerate() cherrypy.session['user'] = { 'name': 'admin', 'fullName': 'Administrator', 'id': 1 } sessionKey = splunk.auth.getSessionKey("admin", "freeneedsnopassword", hostPath=self.splunkd_urlhost) cherrypy.session['sessionKey'] = sessionKey if not updateCheckerBaseURL: return self.redirect_to_url('/app/%s' % splunk.getDefault('namespace')) # check for previously successful login templateArgs['hasLoggedIn'] = self.hasLoggedIn() # otherwise, show page return self.render_template('account/login.html', templateArgs) # # POST # # Check that the cookie we set when the login page was loaded has made it to us intact if 'cval' not in cherrypy.request.cookie or not self.cookieTest(cval): templateArgs['bad_cookies'] = 1 templateArgs['cval'] = self.updateCookieTest() return self.render_template('account/login.html', templateArgs) try: sessionKey = splunk.auth.getSessionKey(username, password, hostPath=self.splunkd_urlhost) except splunk.AuthenticationFailed, e: templateArgs['invalid_password'] = 1 templateArgs['cval'] = self.updateCookieTest() return self.render_template('account/login.html', templateArgs)
def start(self, appid, return_to=None, return_to_success=None, breadcrumbs=None, implicit_id_required=None, error=None, state=None, **kw): """ The main entry point for installing or updating an app params: return_to - optional return address on completion return_to_success - optional return address used in favour or return_to if the app install is succesful breadcrumbs - pipe separated list of name|url tuples. tuples themselves are joined by tabs. error - internally used error message state - internally used StateDict object """ current_app = self.getLocalApp(appid) # state is a dict sublcass for storing things like the return_to url # that can be serialized to a URL-safe string by calling .serialize() on it # and restored by passing the raw data to StateDict.unserialize() if state: state = StateDict.unserialize(state) breadcrumbs = state['breadcrumbs'] else: breadcrumbs = parse_breadcrumbs_string(breadcrumbs) breadcrumbs.append([_('Install app'), None]) state = StateDict({ 'return_to': return_to if return_to else self.make_url(['manager', splunk.getDefault('namespace'), 'apps','local'], translate=False), 'return_to_success': return_to_success, 'breadcrumbs': breadcrumbs, 'implicit_id_required': implicit_id_required }) if current_app: # check whether a newer version is available if self.appUpgradeAvailable(current_app): state['implicit_id_required'] = current_app.get('update.implicit_id_required', None) return self.render_admin_template('/admin/appinstall/upgrade-available.html', { 'app': current_app, 'appid': appid, 'breadcrumbs': breadcrumbs, 'error': error, 'state': state }) if self.isRestartRequired() or self.appNeedsSetup(current_app): # app is installed but hasn't been setup, or a restart is required return self.redirect_to_url(['/manager/appinstall', appid, 'checkstatus'], { 'state': state.serialize() }) # else the app is already installed and no upgrades are available return self.render_admin_template('/admin/appinstall/already-installed.html', { 'app': current_app, 'appid': appid, 'state': state, 'breadcrumbs': breadcrumbs }) # see whether the app exists on Splunkbase (and thus whether Splunkbase is even reachable) try: remote_app = self.getRemoteAppEntry(appid) except splunk.ResourceNotFound: # app doesn't exist on splunkbase; allow for manual upload return self.render_admin_template('/admin/appinstall/app-not-found.html', { 'appid': appid, 'breadcrumbs': breadcrumbs, 'state': state }) except splunk.RESTException, e: if e.statusCode == 503: # splunkd will return 503 if it's configured not to contact splunkbase error = None else: # else something else went wrong error = str(e) return self.render_admin_template('/admin/appinstall/no-internet.html', { 'appid': appid, 'breadcrumbs': breadcrumbs, 'state': state, 'error': error })