def get_api_config(api): if api == 'kobotoolbox': url_field = 'kobo_api_url' username_field = 'kobo_api_username' credential_entity = 'kobo_api_password' if api == 'splunk': url_field = 'splunk_ec_url' credential_entity = 'splunk_ec_token' username = '' try: kobotoolbox_config = entity.getEntity(['admin', 'conf-app'], 'kobotoolbox', namespace='TA-kobotoolbox', owner='nobody', sessionKey=session_key) credential = entity.getEntity(['admin', 'passwords'], credential_entity, namespace='TA-kobotoolbox', owner='nobody', sessionKey=session_key) url = kobotoolbox_config[url_field] if api == 'kobotoolbox': username = kobotoolbox_config[username_field] except Exception, e: print_status('ERROR', "Could not get API config for %s: %s" % (api, str(e))) sys.exit()
def disableIndexAndForward(cls, sessionKey): try: # Try to get the existing entry indexAndForward_entity = en.getEntity( 'configs/conf-outputs', "indexAndForward", namespace=ConfigCEFApp.DEFAULT_NAMESPACE, owner=ConfigCEFApp.DEFAULT_OWNER, sessionKey=sessionKey) except splunk.ResourceNotFound: # Otherwise, create a new one indexAndForward_entity = en.getEntity( 'configs/conf-outputs', "_new", namespace=ConfigCEFApp.DEFAULT_NAMESPACE, owner=ConfigCEFApp.DEFAULT_OWNER, sessionKey=sessionKey) indexAndForward_entity.namespace = ConfigCEFApp.DEFAULT_NAMESPACE indexAndForward_entity.owner = ConfigCEFApp.DEFAULT_OWNER indexAndForward_entity['name'] = "indexAndForward" indexAndForward_entity['index'] = 0 en.setEntity(indexAndForward_entity, sessionKey=sessionKey)
def save(self, new=False, session_key=None, namespace=None, owner=None): """ Saves the notable event status. If an ID is set, then the existing status will be updated. Otherwise, a new one will be created. """ ## Get the owner and namespace if namespace is None: namespace = NotableEventSuppression.DEFAULT_NAMESPACE if owner is None: owner = NotableEventSuppression.DEFAULT_OWNER ## Try to get the session key if not provided session_key = NotableEventSuppression.__get_session_key__(session_key) ## If the ID is not set, create a new entry if new: ## Get the default entity notable_suppression = en.getEntity(NotableEventSuppression.EVENTTYPES_REST_URL, '_new', sessionKey=session_key) ## Otherwise, edit the existing entity else: ## Get the existing entity notable_suppression = en.getEntity(NotableEventSuppression.EVENTTYPES_REST_URL, self.id, namespace=namespace, owner=owner, sessionKey=session_key) ## Update the entity notable_suppression = self.__populate_entity__(notable_suppression, new) ## Save the entity en.setEntity(notable_suppression, sessionKey=session_key) return True
def pdf(self): ''' Provides debug services for PDF server ''' status = { 'pdfIsInstalled': False, 'pdfIsEnabled': False, 'smtpIsSet': False, 'configuration': {} } # check that PDF app is installed try: if comm.isWindows: en.getEntity('/pdfserver', 'renderpdf') else: en.getEntity('admin/localapps', 'pdfserver', namespace='search') status['pdfIsInstalled'] = True except splunk.ResourceNotFound: pass except Exception, e: logger.exception(e) status['pdfIsInstalled'] = e
def is_enabled(self): """ Determine whether the PDF server is installed and enabled for the current user """ try: installed = False settings = en.getEntity(ALERT_ACTIONS_ENTITY, 'email') serverURL = settings.get('reportServerURL') or '' if serverURL.strip() == '': # if reportServerURL is blank then this system should actually have the app installed; check for that. # will raise a ResourceNotFound exception if not installed if comm.isWindows: # will raise a ResourceNotFound exception if our PDF driver is not installed en.getEntity('/pdfserver', 'renderpdf') else: en.getEntity('/apps/local', 'pdfserver') installed = True # next check that it's actually turned on in email settings; # on Windows, ther server is always enabled status = 'enabled' if comm.isWindows or splunk.util.normalizeBoolean( settings.get('reportServerEnabled')) else 'disabled' except splunk.ResourceNotFound: status = 'notinstalled' except splunk.AuthorizationFailed: status = 'denied' except splunk.LicenseRestriction: status = 'denied' response = {'installed': installed, 'status': status} return self.render_json(response)
def is_enabled(self): """ Determine whether the PDF server is installed and enabled for the current user """ try: installed = False settings = en.getEntity(ALERT_ACTIONS_ENTITY, 'email') serverURL = settings.get('reportServerURL') or '' if serverURL.strip() == '': # if reportServerURL is blank then this system should actually have the app installed; check for that. # will raise a ResourceNotFound exception if not installed if comm.isWindows: # will raise a ResourceNotFound exception if our PDF driver is not installed en.getEntity('/pdfserver', 'renderpdf') else: en.getEntity('/apps/local', 'pdfserver') installed = True # next check that it's actually turned on in email settings; # on Windows, ther server is always enabled status = 'enabled' if comm.isWindows or splunk.util.normalizeBoolean(settings.get('reportServerEnabled')) else 'disabled' except splunk.ResourceNotFound: status = 'notinstalled' except splunk.AuthorizationFailed: status = 'denied' except splunk.LicenseRestriction: status = 'denied' response = { 'installed': installed, 'status': status } return self.render_json(response)
def create_new_scripted_inputs(self, data): inputdata = entity.getEntity('data/inputs/script', '_new', sessionKey=self.getSessionKey()) inputdata[ "name"] = '$SPLUNK_HOME\\etc\\apps\\TA-CMX\\bin\\Server.py' \ if platform.system().lower() == 'windows' else '$SPLUNK_HOME/etc/apps/TA-CMX/bin/Server.py' inputdata["interval"] = ["0"] inputdata["disabled"] = ["false"] inputdata["passAuth"] = ["splunk-system-user"] inputdata.namespace = "TA-CMX" entity.setEntity(inputdata, sessionKey=self.getSessionKey()) index = data["INDEX"][0] if data["INDEX"] else "main" inputdata = entity.getEntity('data/inputs/script', '_new', sessionKey=self.getSessionKey()) inputdata[ "name"] = '$SPLUNK_HOME\\etc\\apps\\TA-CMX\\bin\\CMXRestAPIMAP.py' \ if platform.system().lower() == 'windows' else '$SPLUNK_HOME/etc/apps/TA-CMX/bin/CMXRestAPIMAP.py' inputdata["interval"] = ["86400"] inputdata["disabled"] = ["false"] inputdata["index"] = [index] inputdata["sourcetype"] = ["cmxmap"] inputdata["passAuth"] = ["splunk-system-user"] inputdata.namespace = "TA-CMX" entity.setEntity(inputdata, sessionKey=self.getSessionKey()) inputdata = entity.getEntity('data/inputs/script', '_new', sessionKey=self.getSessionKey()) inputdata[ "name"] = '$SPLUNK_HOME\\etc\\apps\\TA-CMX\\bin\\CMXRestAPIAnalytics.py' \ if platform.system().lower() == 'windows' else '$SPLUNK_HOME/etc/apps/TA-CMX/bin/CMXRestAPIAnalytics.py' inputdata["interval"] = ["540"] inputdata["disabled"] = ["false"] inputdata["index"] = [index] inputdata["sourcetype"] = ["cmxanalytics"] inputdata["passAuth"] = ["splunk-system-user"] inputdata.namespace = "TA-CMX" entity.setEntity(inputdata, sessionKey=self.getSessionKey()) inputdata = entity.getEntity('data/inputs/script', '_new', sessionKey=self.getSessionKey()) inputdata[ "name"] = '$SPLUNK_HOME\\etc\\apps\\TA-CMX\\bin\\CMXRestAPIActive.py' \ if platform.system().lower() == 'windows' else '$SPLUNK_HOME/etc/apps/TA-CMX/bin/CMXRestAPIActive.py' inputdata["interval"] = ["960"] inputdata["disabled"] = ["false"] inputdata["index"] = [index] inputdata["sourcetype"] = ["cmxactive"] inputdata["passAuth"] = ["splunk-system-user"] inputdata.namespace = "TA-CMX" entity.setEntity(inputdata, sessionKey=self.getSessionKey())
def getCredentials(sessionKey): try: api_obj = entity.getEntity('scalr_setup/api_input', 'api', namespace=myapp, owner='nobody', sessionKey=sessionKey) api_secret = entity.getEntity('storage/passwords', 'api:secret', namespace=myapp, owner='nobody', sessionKey=sessionKey) except Exception as e: sys.stderr.write("DATALOADER_SCRIPT_ERROR - Could not get Scalr API Credentials from Splunk. Exception: %s\n" % (str(e))) exit(2) #print(api_obj) #print(api_secret) return api_obj['url'], api_obj['key'], api_secret['clear_password'], str2bool(api_obj['verify_ssl'])
def check_restart_required(): ''' Indicates if splunkd has raised the restart flag as a result of new configuration changes. ''' try: en.getEntity('messages', 'restart_required') return True except splunk.ResourceNotFound: return False except Exception, e: logger.warn('unable to determine if restart is required: %s' % e)
def setIndexers(cls, indexers, sessionKey): # Validate the input cls.validateIndexers(indexers) # Get the default output group in tcpout defaultOutput = cls.getDefaultOutputGroup(sessionKey) # No group is defined, make it defaultGroupSet = True if defaultOutput is None: defaultGroupSet = False # See if the default group already exists #defaultOutput = Output.search('name=tcpout:indexCluster"', count_per_req=100, sessionKey=sessionKey) try: defaultOutput = en.getEntity('admin/conf-outputs', "tcpout:indexCluster", sessionKey=sessionKey) except splunk.ResourceNotFound: defaultOutput = None if defaultOutput is not None: pass # Otherwise, make the new group else: #defaultOutput = Output(ConfigCEFApp.DEFAULT_NAMESPACE, ConfigCEFApp.DEFAULT_OWNER, "tcpout:indexCluster") defaultOutput = en.getEntity('admin/conf-outputs', '_new', sessionKey=sessionKey) defaultOutput.namespace = ConfigCEFApp.DEFAULT_NAMESPACE defaultOutput.owner = ConfigCEFApp.DEFAULT_OWNER defaultOutput['name'] = "tcpout:indexCluster" # Update and save the entry #defaultOutput.server = indexers #defaultOutput.save() defaultOutput['server'] = indexers defaultOutput.namespace = ConfigCEFApp.DEFAULT_NAMESPACE defaultOutput.owner = ConfigCEFApp.DEFAULT_OWNER en.setEntity(defaultOutput, sessionKey=sessionKey) # Set this as the default group if not defaultGroupSet: cls.setDefaultTcpOutGroup(defaultOutput.name, sessionKey) # Disable local indexing cls.disableIndexAndForward(sessionKey)
def which_pdf_service(sessionKey, viewId=None, owner=None, namespace=None): pdfService = "none" if is_pdfgen_available(): if viewId is None or (len(viewId) == 0): pdfService = "pdfgen" else: import lxml.etree as et # this is either a simple dashboard, simple form, or advanced XML view # get the entity of the view and then check the root node entityId = entity.buildEndpoint('data/ui/views', viewId, namespace=namespace, owner=owner) viewEntity = entity.getEntity('data/ui/views', None, sessionKey=sessionKey, uri=entityId) data = viewEntity['eai:data'] if data: root = et.fromstring(unicode(data).encode('utf-8')) if root.tag == "dashboard": pdfService = "pdfgen" else: pdfService = "deprecated" else: pdfService = "deprecated" if pdfService is "deprecated" and not is_deprecated_service_available( sessionKey): pdfService = "none" return pdfService
def generateBaseLink(): """ Construct a link suitable for giving to the PDF server Utilize the configured link hostname if available, else use the url from this instance of splunkweb """ settings = en.getEntity('/configs/conf-alert_actions', 'email', namespace='system') linkhost = settings.get('hostname') if linkhost: linkhost = linkhost.strip() if not linkhost: result = cherrypy.request.base elif linkhost.startswith('http://') or linkhost.startswith('https://'): result = linkhost else: port = cherrypy.request.local.port hasport = False if '[' in linkhost: addrend = linkhost.find(']') if addrend < 2: raise ValueError('Incorrect IPv6 address specified for link hostname') hasport = len(linkhost) > (addrend + 3) and linkhost[addrend+1] == ':' elif ':' in linkhost: addrend = linkhost.find(':') hasport = len(linkhost) > (addrend + 3) result = cherrypy.request.scheme + '://' + linkhost if not hasport and port not in (80, 443): result += ':%s' % port return result
def _initAlertActionsDefaults(self): """ use alertActions entity to determine default papersize return in form of "<size>" or "<size>-landscape" """ paperSize = DEFAULT_PAPER_SIZE paperOrientation = DEFAULT_PAPER_ORIENTATION try: # SPL-107168 Passing namespace and owner to generate context specifc endpoint settings = entity.getEntity(self.ALERT_ACTIONS_ENTITY, 'email', namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) # paperSize is 'letter', 'legal', 'A4', etc paperSize = settings.get('reportPaperSize') or DEFAULT_PAPER_SIZE # paperOrientation is 'portrait' or 'landscape' paperOrientation = settings.get('reportPaperOrientation') or DEFAULT_PAPER_ORIENTATION self._includeSplunkLogo = normalizeBoolean(settings.get('reportIncludeSplunkLogo', self._includeSplunkLogo)) cidFontListString = settings.get('reportCIDFontList', '') or '' self._cidFontList = cidFontListString.split(' ') self._fileNamePattern = settings.get('reportFileName') # retrieve pdf settings for k, v in settings.iteritems(): if k.startswith(pdfrenderer.SETTING_PREFIX): self._pdfSettings[k] = v keyNoPrefix = k[len(pdfrenderer.SETTING_PREFIX):len(k)] # SSL settings are stored in pdf namespace, but the ssl_context # won't find these settings if they are prefixed w/ pdf self._requestSettings['pdf'][keyNoPrefix] = v except Exception as e: logger.error("Could not access or parse email stanza of alert_actions.conf. Error=%s" % str(e)) if paperOrientation == 'landscape': self._paperSize = paperSize + '-landscape' else: self._paperSize = paperSize
def controlJob(self, sid, ctl, action, wait=True, ttl=None): ''' Executes control for a given job ''' resp = JsonResponse() # SDK does not have any functionality to change ACLs, so i have # had to add these custom actions for now. # TODO - if/when SDK has support for changing ACL's, rewrite this # code to not use the Entity class. if (action == "makeWorldReadable" or action == "undoWorldReadable"): jobPath = "search/jobs/" + sid entityName = "acl" aclEntity = en.getEntity( jobPath, entityName, namespace="system", owner=splunk.auth.getCurrentUser()['name']) if (action == "makeWorldReadable"): aclEntity.properties['perms.read'] = ["*"] else: aclEntity.properties['perms.read'] = [] try: result = en.setEntity(aclEntity, uri=jobPath + "/acl") except Exception, e: logger.exception(e) resp.addError( _("Splunk could not update permissions for this job")) return self.render_json(resp)
def setSharing(viewstate, shareMode): ''' Sets the sharing mode: 'global', 'app', 'user' ''' if not isinstance(viewstate, Viewstate): raise ValueError, 'Cannot update viewstate; Only viewstate objects supported' # first fetch all the ACL data vsACL = en.getEntity( VIEWSTATE_ENTITY_CLASS + '/' + buildStanzaName(viewstate.view, viewstate.id), 'acl', namespace=viewstate.namespace, owner=viewstate.owner ) # create new object and update mininum set of properties to support sharing aclWrapper = en.Entity( VIEWSTATE_ENTITY_CLASS + '/' + buildStanzaName(viewstate.view, viewstate.id), 'acl', namespace=viewstate.namespace, owner=viewstate.owner ) aclWrapper['owner'] = viewstate.owner aclWrapper['sharing'] = shareMode # commit en.setEntity(aclWrapper) return True
def update(self, **params): app, user = self._namespace_and_owner() ent = en.getEntity(self._endpoint, self.callerArgs.id, namespace=app, owner=user, sessionKey=self.getSessionKey()) for arg in params.keys(): if arg in self._required_args + self._optional_args: ent[arg] = params[arg] #check which args are allowed to be posted allowedArgs = [] if 'eai:attributes' in ent and 'requiredFields' in ent[ 'eai:attributes'] and 'optionalFields' in ent['eai:attributes']: allowedArgs = ent['eai:attributes']['requiredFields'] + ent[ 'eai:attributes']['optionalFields'] #filter out args that aren't allowed for arg in ent.keys(): if arg not in allowedArgs: del ent.properties[arg] en.setEntity(ent, sessionKey=self.getSessionKey())
def controlJob(self, sid, ctl, action, ttl=None): """ Executes control for a given job """ resp = JsonResponse() # SDK does not have any functionality to change ACLs, so i have # had to add these custom actions for now. # TODO - if/when SDK has support for changing ACL's, rewrite this # code to not use the Entity class. if action == "makeWorldReadable" or action == "undoWorldReadable": jobPath = "search/jobs/" + sid entityName = "acl" aclEntity = en.getEntity( jobPath, entityName, namespace="system", owner=splunk.auth.getCurrentUser()["name"] ) if action == "makeWorldReadable": aclEntity.properties["perms.read"] = ["*"] else: aclEntity.properties["perms.read"] = [] try: result = en.setEntity(aclEntity, uri=jobPath + "/acl") except Exception, e: logger.exception(e) resp.addError(_("Splunk could not update permissions for this job")) return self.render_json(resp)
def getMailSettings(self): import splunk.entity as entity try: namespace = "search" ent = entity.getEntity('admin/alert_actions', 'email', namespace=namespace, owner='nobody', sessionKey=self.sessionKey) self.server = ent['mailserver'] self.sender = ent['from'] if ent['use_ssl'] == "1": self.use_ssl = True else: self.use_ssl = False if ent['use_tls'] == "1": self.use_tls = True else: self.use_tls = False if 'auth_username' in ent and 'clear_password' in ent: self.username = ent['auth_username'] self.password = ent['clear_password'] except Exception, e: raise Exception, "Could not get email settings from splunk. SessionKey=%s Error: %s" % ( self.sessionKey, str(e))
def _initAlertActionsDefaults(self): """ use alertActions entity to determine default papersize return in form of "<size>" or "<size>-landscape" """ paperSize = DEFAULT_PAPER_SIZE paperOrientation = DEFAULT_PAPER_ORIENTATION try: settings = entity.getEntity(self.ALERT_ACTIONS_ENTITY, 'email', sessionKey=self.sessionKey) # paperSize is 'letter', 'legal', 'A4', etc paperSize = settings.get('reportPaperSize') or DEFAULT_PAPER_SIZE # paperOrientation is 'portrait' or 'landscape' paperOrientation = settings.get( 'reportPaperOrientation') or DEFAULT_PAPER_ORIENTATION self._includeSplunkLogo = normalizeBoolean( settings.get('reportIncludeSplunkLogo', self._includeSplunkLogo)) cidFontListString = settings.get('reportCIDFontList', '') or '' self._cidFontList = cidFontListString.split(' ') except Exception as e: logger.error( "Could not access or parse email stanza of alert_actions.conf. Error=%s" % str(e)) if paperOrientation == 'landscape': self._paperSize = paperSize + '-landscape' else: self._paperSize = paperSize
def getViewObject(self, view_id, namespace, outputEntity=False): ''' Returns a native ViewObject version of the requested view_id ''' viewEntity = en.getEntity(VIEW_ENTITY_CLASS, view_id, namespace=namespace) parser = et.XMLParser(remove_blank_text=True, remove_comments=True, remove_pis=True) root = et.XML(viewEntity[en.EAI_DATA_KEY], parser) if root.tag == 'dashboard': objectClass = dashboard.SimpleDashboard( isStorm=splunk.util.normalizeBoolean( cherrypy.config.get('storm_enabled'))) elif root.tag == 'form': objectClass = form.SimpleForm() else: raise NotImplementedError, 'Cannot manage view object of type: %s' % root.tag objectClass.fromXml(root) if outputEntity: return objectClass, viewEntity else: return objectClass
def get_rest_info(self, session_key=None, namespace=None): """ Returns a session key, namespace and owner (in that order). The namespace and owner will be populated with default values if they do not have a value already. """ # Try to get the session key if not provided session_key = CorrelationSearch.__get_session_key__(session_key) # If this is an existing search, get the namespace if self.sid: try: saved_search = en.getEntity( CorrelationSearch.SAVED_SEARCHES_REST_URL, self.sid, sessionKey=session_key) namespace = saved_search.get('eai:acl').get('app') except Exception: pass # Validate the namespace namespace = self.validate_namespace(session_key, namespace) self.namespace = namespace # Force user to "nobody" to permit role-based editing. owner = 'nobody' self.owner = owner return session_key, namespace, owner
def getDefaultOutputGroup(cls, sessionKey): # Get the default group output = cls.getMainOutput(sessionKey) if 'defaultGroup' in output: defaultGroup = output['defaultGroup'] else: return None # No group is defined if defaultGroup is None: return None # Get the default group #defaultOutput = Output.get(Output.build_id("tcpout:" + defaultGroup, None, None), sessionKey=sessionKey) try: defaultOutput = en.getEntity('admin/conf-outputs', "tcpout:" + defaultGroup, sessionKey=sessionKey) except splunk.ResourceNotFound: return None # Return the indexers return defaultOutput
def getRemoteAppEntry(self, appid): """ Used to determine whether the app is available on Splunkbase and whether splunkd can even talk to Splunkbase """ return en.getEntity('/apps/remote/entriesbyid', appid, sessionKey=cherrypy.session['sessionKey'])
def handleEdit(self, confInfo): name = self.callerArgs.id ent = en.getEntity(ENDPOINT, name, namespace=self.appName, owner=self.userName, sessionKey=self.getSessionKey()) for arg in optional_args: try: if arg in ['disabled']: continue ent[arg] = self.callerArgs[arg] except: pass for arg in required_args: try: if arg in ['disabled']: continue ent[arg] = self.callerArgs[arg] except: pass en.setEntity(ent, sessionKey=self.getSessionKey())
def edit(self, app, viewName, **params): owner = splunk.auth.getCurrentUser()['name'] pdfPreviewUrl = None if "pdfPreviewUrl" in params: pdfPreviewUrl = params.get('pdfPreviewUrl') viewLabel = viewName if "viewLabel" in params: viewLabel = params.get('viewLabel') id = ScheduledView.build_id(name=viewName, owner=owner, namespace=app) scheduled_view = ScheduledView.get(id) if scheduled_view.schedule.cron_schedule == None: scheduled_view.schedule.cron_schedule = '*/30 * * * *' frequency, manual_cron = self._cronSchedule_to_UI(scheduled_view.schedule.cron_schedule) # TODO: refactor out to share code with pdfgen_endpoint ALERT_ACTIONS_ENTITY="/configs/conf-alert_actions" settings = entity.getEntity(ALERT_ACTIONS_ENTITY, 'email') # paperSize is 'letter', 'legal', 'A4', etc paperSize = settings.get('reportPaperSize') or 'letter' # paperOrientation is 'portrait' or 'landscape' paperOrientation = settings.get('reportPaperOrientation') or 'portrait' if scheduled_view.action.email.papersize == None: scheduled_view.action.email.papersize = paperSize paperSize = scheduled_view.action.email.papersize if scheduled_view.action.email.paperorientation == None: scheduled_view.action.email.paperorientation = paperOrientation paperOrientation = scheduled_view.action.email.paperorientation return self.render_template('scheduledview/edit.html', dict(app=app, scheduled_view=scheduled_view, frequency=frequency, manual_cron=manual_cron, paperSize=paperSize, paperOrientation=paperOrientation, pdfPreviewUrl=pdfPreviewUrl, viewLabel=viewLabel))
def _initWebDefaults(self): defaultSplunkdConnectionTimeout = 30 try: # SPL-107168 Passing namespace and owner to generate context specifc endpoint settings = entity.getEntity(self.WEB_ENTITY, 'settings', namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) splunkdConnectionTimeout = \ int(settings.get('splunkdConnectionTimeout', defaultSplunkdConnectionTimeout)) if splunkdConnectionTimeout \ < defaultSplunkdConnectionTimeout: splunkdConnectionTimeout = \ defaultSplunkdConnectionTimeout splunk.rest.SPLUNKD_CONNECTION_TIMEOUT = \ splunkdConnectionTimeout except Exception, e: logger.error( 'Exception while trying to get splunkdConnectionTimeout from web.conf e=%s' % e) splunk.rest.SPLUNKD_CONNECTION_TIMEOUT = \ defaultSplunkdConnectionTimeout
def setSharing(viewstate, shareMode): ''' Sets the sharing mode: 'global', 'app', 'user' ''' if not isinstance(viewstate, Viewstate): raise ValueError, 'Cannot update viewstate; Only viewstate objects supported' # first fetch all the ACL data vsACL = en.getEntity(VIEWSTATE_ENTITY_CLASS + '/' + buildStanzaName(viewstate.view, viewstate.id), 'acl', namespace=viewstate.namespace, owner=viewstate.owner) # create new object and update mininum set of properties to support sharing aclWrapper = en.Entity(VIEWSTATE_ENTITY_CLASS + '/' + buildStanzaName(viewstate.view, viewstate.id), 'acl', namespace=viewstate.namespace, owner=viewstate.owner) aclWrapper['owner'] = viewstate.owner aclWrapper['sharing'] = shareMode # commit en.setEntity(aclWrapper) return True
def _initWebDefaults(self): defaultSplunkdConnectionTimeout = 30 try: # SPL-107168 Passing namespace and owner to generate context specifc endpoint settings = entity.getEntity(self.WEB_ENTITY, 'settings', namespace=self._namespace, owner=self._owner, sessionKey=self.sessionKey) self._enableInsecurePdfgen = normalizeBoolean( settings.get('enable_insecure_pdfgen', self._enableInsecurePdfgen)) splunkdConnectionTimeout = int( settings.get('splunkdConnectionTimeout', defaultSplunkdConnectionTimeout)) if splunkdConnectionTimeout < defaultSplunkdConnectionTimeout: splunkdConnectionTimeout = defaultSplunkdConnectionTimeout splunk.rest.SPLUNKD_CONNECTION_TIMEOUT = splunkdConnectionTimeout except Exception as e: logger.error( "Could not access or parse settings stanza of web.conf. Error=%s" % e) splunk.rest.SPLUNKD_CONNECTION_TIMEOUT = defaultSplunkdConnectionTimeout finally: logger.info("splunkdConnectionTimeout=%s" % splunk.rest.SPLUNKD_CONNECTION_TIMEOUT)
def getEntity(entityPath, name, namespace=None, owner=None, sessionKey=None, hostPath=None, available=True): conn = en.getEntity(entityPath, name, namespace=namespace, owner=owner, sessionKey=sessionKey, hostPath=hostPath) params = conn.properties if available: for n, v in params.items(): if n in ["disabled"] and util.normalizeBoolean(v): raise ResourceNotFound(msg="%s Resource is disabled." % name) elif n.endswith(".disabled"): if v in ["-1"]: raise ResourceNotFound(msg="%s in %s Resource not found." % (n[:len(n) - 9], name)) elif util.normalizeBoolean(v): raise ResourceNotFound( msg="%s in %s Resource is disabled." % (n[:len(n) - 9], name)) return conn
def getCredentials(sessionKey, namespace): try: ent = entity.getEntity('admin/alert_actions', 'email', namespace=namespace, owner='nobody', sessionKey=sessionKey) if 'auth_username' in ent and 'clear_password' in ent: return ent['auth_username'], ent['clear_password'] except Exception, e: logger.error("Could not get email credentials from splunk, using no credentials. Error: %s" % (str(e)))
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)
def getMailSettings(self): import splunk.entity as entity try: namespace = "search" ent = entity.getEntity( "admin/alert_actions", "email", namespace=namespace, owner="nobody", sessionKey=self.sessionKey ) self.server = ent["mailserver"] self.sender = ent["from"] if ent["use_ssl"] == "1": self.use_ssl = True else: self.use_ssl = False if ent["use_tls"] == "1": self.use_tls = True else: self.use_tls = False if "auth_username" in ent and "clear_password" in ent: self.username = ent["auth_username"] self.password = ent["clear_password"] except Exception, e: raise Exception, "Could not get email settings from splunk. SessionKey=%s Error: %s" % ( self.sessionKey, str(e), )
def get(self): app, user = self._namespace_and_owner() return en.getEntity(self._endpoint, self.callerArgs.id, namespace=app, owner=user, sessionKey=self.getSessionKey())
def get(self, name): user, app = self.user_app() ent = entity.getEntity(self.endpoint, name, namespace=app, owner=user, sessionKey=self.getSessionKey()) return self.decode(name, ent)
def get_notable_suppression(id=id, session_key=None): """ Get the given notable event suppression. """ notable_suppression = en.getEntity(NotableEventSuppression.EVENTTYPES_REST_URL, id, namespace=NotableEventSuppression.DEFAULT_NAMESPACE, owner=NotableEventSuppression.DEFAULT_OWNER, sessionKey=session_key) return NotableEventSuppression.__create_from_dict__(id, notable_suppression)
def get(self): return en.getEntity( self._endpoint, self.callerArgs.id, namespace=self.appName, owner=self.userName, sessionKey=self.getSessionKey(), )
def get_total_event_count( server, index, username, password ): from splunk import entity, auth, mergeHostPath mergeHostPath( server, True ) auth.getSessionKey( username=username, password=password ) properties = entity.getEntity( entityPath='/data/indexes', entityName=index ).properties if 'totalEventCount' in properties: return int( properties['totalEventCount'] ) else: return 0
def getCredentials(sessionKey, namespace): try: ent = entity.getEntity( "admin/alert_actions", "email", namespace=namespace, owner="nobody", sessionKey=sessionKey ) if "auth_username" in ent and "clear_password" in ent: return ent["auth_username"], ent["clear_password"] except Exception, e: logger.error("Could not get email credentials from splunk, using no credentials. Error: %s" % (str(e)))
def _initLimitsDefaults(self): """ use limits entity to determine defaults """ try: settings = entity.getEntity(self.LIMITS_ENTITY, 'pdf', sessionKey=self.sessionKey) logger.debug("limitsPDFStanza=%s" % (str(settings))) self._maxRowsPerTable = int(settings.get('max_rows_per_table', self._maxRowsPerTable)) self._timeoutDuration = int(settings.get('render_endpoint_timeout', self._timeoutDuration)) except Exception as e: logger.error("Could not access or parse pdf stanza of limits.conf. Error=%s" % str(e))
def addInput(sessionKey, source, namespace, owner, sourcetype, index): mon = en.getEntity('/data/inputs/monitor/','_new', sessionKey=sessionKey) mon["name"] = source if sourcetype != None: mon["sourcetype"] = sourcetype if index != None: mon["index"] = index mon.namespace = namespace mon.owner = owner en.setEntity(mon, sessionKey=sessionKey)
def update(self, **params): ent = en.getEntity( self._endpoint, self.callerArgs.id, namespace=self.appName, owner="nobody", sessionKey=self.getSessionKey() ) for arg in params.keys(): if arg in self._required_args + self._optional_args: ent[arg] = params[arg] en.setEntity(ent, sessionKey=self.getSessionKey())
def _getAppData(self, app): output = {app:{}} try: appData = en.getEntity('apps/local', app, namespace=app) output[app]['label'] = _(appData.get('label')) except splunk.ResourceNotFound: logger.error("Unable to retrieve apps/local/%s" % app) return output
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 reap(reap_list, token): ''' reap all jobs in given list ''' if not reap_list: return logger.info('attempting to reap %i job(s)' % len(reap_list)) for job in reap_list: en = entity.getEntity(ENTITY_PATH, job, namespace=APP_NAME, owner='nobody', sessionKey=token) if en['status'] and en['status'] != 2: logger.warning('job %s cannot be reaped - status is %s' % (job, en['status'])) next entity.deleteEntity(ENTITY_PATH, job, APP_NAME, 'nobody', sessionKey=token) logger.info('successfully reaped job %s' % job)
def set_status(job_list, status, token): if job_list and (len(job_list) < 1 or not isinstance(job_list, list)): return try: status = int(status) except: logger.error('set_status will only accept status integers') sys.exit() if status < 0 or status > 2: logger.error('set_status will only accept status integers between 0 and 2') for job in job_list: en = entity.getEntity(ENTITY_PATH, job, namespace=APP_NAME, owner='nobody', sessionKey=token) en['status'] = status entity.setEntity(en, sessionKey=token)
def update(self, **params): app, user = self._namespace_and_owner() ent = en.getEntity( self._endpoint, self.callerArgs.id, namespace=app, owner=user, sessionKey=self.getSessionKey() ) for arg in self._optional_args: if arg in ["disabled"]: continue try: ent[arg] = params[arg] except: pass for arg in self._required_args: if arg in ["disabled"]: continue ent[arg] = params[arg] en.setEntity(ent, sessionKey=self.getSessionKey())
def _initAlertActionsDefaults(self): """ use alertActions entity to determine default papersize return in form of "<size>" or "<size>-landscape" """ paperSize = DEFAULT_PAPER_SIZE paperOrientation = DEFAULT_PAPER_ORIENTATION try: settings = entity.getEntity(self.ALERT_ACTIONS_ENTITY, 'email', sessionKey=self.sessionKey) # paperSize is 'letter', 'legal', 'A4', etc paperSize = settings.get('reportPaperSize') or DEFAULT_PAPER_SIZE # paperOrientation is 'portrait' or 'landscape' paperOrientation = settings.get('reportPaperOrientation') or DEFAULT_PAPER_ORIENTATION self._includeSplunkLogo = normalizeBoolean(settings.get('reportIncludeSplunkLogo', self._includeSplunkLogo)) cidFontListString = settings.get('reportCIDFontList', '') or '' self._cidFontList = cidFontListString.split(' ') except Exception as e: logger.error("Could not access or parse email stanza of alert_actions.conf. Error=%s" % str(e)) if paperOrientation == 'landscape': self._paperSize = paperSize + '-landscape' else: self._paperSize = paperSize
def getViewObject(self, view_id, namespace, outputEntity=False): ''' Returns a native ViewObject version of the requested view_id ''' viewEntity = en.getEntity(VIEW_ENTITY_CLASS, view_id, namespace=namespace) parser = et.XMLParser(remove_blank_text=True, remove_comments=True, remove_pis=True) root = et.XML(viewEntity[en.EAI_DATA_KEY], parser) if root.tag == 'dashboard': objectClass = dashboard.SimpleDashboard(isStorm=splunk.util.normalizeBoolean(cherrypy.config.get('storm_enabled'))) elif root.tag == 'form': objectClass = form.SimpleForm() else: raise NotImplementedError, 'Cannot manage view object of type: %s' % root.tag objectClass.fromXml(root) if outputEntity: return objectClass, viewEntity else: return objectClass
def generateSelfHelpLink(context=None): ''' Generates the contexual URI to the splunk.com help system ''' import i18n, urllib locale = i18n.current_lang_url_component() if not context: # generate standard help link by passing a keyword that is composed # of a cleansed URI (remove locale and namespace) context = cherrypy.request.path_info.strip('/').split('/') appContext = '' if context[0].startswith(locale): context.pop(0) if context[0] in ('manager'): context.pop(1) if context[0] in ('app'): appName = context[1] entity = en.getEntity('apps/local', appName) if filter((lambda x: x[0] == 'disable'), entity.links): # make sure it's not an internal Splunk app appVersion = entity.get('version') appContext = '[%s:%s]' % (appName, appVersion) context = appContext + '.'.join(context) uri = make_url('/help') params = { 'license': 'free' if cherrypy.config.get('is_free_license') else 'pro', 'installType': 'trial' if cherrypy.config.get('is_trial_license') else 'prod', 'versionNumber': cherrypy.config.get('version_label'), 'location': context, 'skin': 'default', 'locale': locale } return uri + '?' + urllib.urlencode(params)
def update(self, **params): app, user = self._namespace_and_owner() ent = en.getEntity(self._endpoint, self.callerArgs.id, namespace=app, owner=user, sessionKey=self.getSessionKey()) for arg in params.keys(): if arg in self._required_args + self._optional_args: ent[arg] = params[arg] #check which args are allowed to be posted allowedArgs = [] if 'eai:attributes' in ent and 'requiredFields' in ent['eai:attributes'] and 'optionalFields' in ent['eai:attributes']: allowedArgs = ent['eai:attributes']['requiredFields'] + ent['eai:attributes']['optionalFields'] #filter out args that aren't allowed for arg in ent.keys(): if arg not in allowedArgs: del ent.properties[arg] en.setEntity(ent, sessionKey=self.getSessionKey())
def avro_decorated(*args, **argv): # find the rpc port from inputs config. port = 9998 if hasattr(avro_decorated, "_sessionKey_"): import splunk.entity as en ent = en.getEntity("/configs/conf-inputs", "rpcstart://default", namespace="splunk-demo-opcda", sessionKey=avro_decorated._sessionKey_, owner="nobody") port = ent["port"] logger.debug("ent=%s" %ent) server_addr = ("localhost", port) # server_addr = load_server_addr(argv, f._sessionKey_) client = ipc.HTTPTransceiver(server_addr[0], server_addr[1]) requestor = ipc.Requestor(load_protocol(), client) def call(*argus): sn, val = schema.items()[0] params = {} reqs = val["request"] for i in range(len(reqs)): k = reqs[i]["name"] if len(argus) > i: params[k] = argus[i] logger.debug("sn=%s, parameters = %s" % (sn, params)) ret = requestor.request(sn , params) return ret avro_decorated.call = call avro_decorated.__name__ = f.__name__ return f(*args, **argv)
def load_server_addr(argv, sessionKey): import splunk.entity as en ent = en.getEntity("/configs/conf-inputs", "rpcstart://default", sessionKey=sessionKey) logger.debug("ent=%s" %ent) return ("localhost", 9998)
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
# check that PDF app is installed try: if comm.isWindows: en.getEntity('/pdfserver', 'renderpdf') else: en.getEntity('admin/localapps', 'pdfserver', namespace='search') status['pdfIsInstalled'] = True except splunk.ResourceNotFound: pass except Exception, e: logger.exception(e) status['pdfIsInstalled'] = e # check for enabled, SMTP, and PDF config try: alertSettings = en.getEntity('configs/conf-alert_actions', 'email', namespace='search') status['pdfIsEnabled'] = splunk.util.normalizeBoolean(alertSettings.get('reportServerEnabled')) status['smtpIsSet'] = True if alertSettings.get('mailserver') else False for k in alertSettings: if k.startswith('report'): status['configuration'][k] = alertSettings[k] except Exception, e: logger.exception(e) status['pdfIsInstalled'] = e return self.render_template('debug/pdf.html', {'status': status}) @expose_page() def pdf_echo(self): '''