def input_streamfwd_exist(token): try: serverResponse, serverContent = splunk.rest.simpleRequest( app_util.make_url_internal(HTTPINPUT_STREAMFWD_URI + '?output_mode=json'), token, postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=True, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT ) # Coulnd't find the resource, and get 404 Not Found if serverResponse['status'] == '404': return False # Some other exception, raise elif serverResponse['status'] != '200': raise splunk.RESTException, (serverResponse.status, serverResponse.messages) return True except Exception as e: logger.exception(e) return False
def validate_streamfwd_auth(header_auth_key): uri = "/services/splunk_app_stream/validatestreamfwdauth" try: serverResponse, serverContent = splunk.rest.simpleRequest( util.make_url_internal(uri), getargs={ 'auth_key': header_auth_key, 'output_mode': 'json' }, sessionKey='', postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=15) jsonResp = json.loads(serverContent) logger.info(jsonResp) auth_success = jsonResp["entry"][0]["content"] return auth_success except Exception as e: logger.exception(e) logger.error( "Error getting the streamfwd auth, return streamfwd auth is disabled" ) return True
def is_hec_supported(token): # Check splunk version try: serverResponse, serverContent = splunk.rest.simpleRequest( app_util.make_url_internal(SERVER_INFO_URI + '?output_mode=json'), token, postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT ) jsonResp = json.loads(serverContent) thisVersion = LooseVersion(jsonResp['generator']['version']) hecVersion = LooseVersion("6.3") return hecVersion <= thisVersion except Exception as e: logger.exception(e) return False
def get_server_info(server_info_key, proxy_uri, sessionKey=None): global splunkd_fatal_error if splunkd_fatal_error: return None try: if not sessionKey: # proxy via splunkd REST endpoint serverResponse, serverContent = splunk.rest.simpleRequest( util.make_url_internal(proxy_uri + '?output_mode=json'), sessionKey='', postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunkd_time_out) jsonResp = json.loads(serverContent) server_info_val = jsonResp["entry"][0]["content"] else: uri = '/services/server/info' serverResponse, serverContent = splunk.rest.simpleRequest( util.make_url_internal(uri + '?output_mode=json'), sessionKey, postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunkd_time_out) jsonResp = json.loads(serverContent) server_info_val = jsonResp["entry"][0]["content"][server_info_key] logger.debug('get_server_info: server_info key::val::%s::%s', (server_info_key, server_info_val)) return server_info_val except Exception as e: logger.exception(e) if any(s in str(e) for s in splunkd_connection_exceptions): splunkd_fatal_error = True return None
def reload_TA_stream_config(session_key): serverResponse, serverContent = splunk.rest.simpleRequest( app_util.make_url_internal(TA_RELOAD_URI), session_key, postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT )
def handle_GET(self): sessionKey = None if 'systemAuth' in self.request and self.request['systemAuth']: sessionKey = self.request['systemAuth'] else: sessionKey = self.sessionKey output = {} # check for auth key auth_key = None if 'systemAuth' in self.request: auth_key = extract_auth_key(self.request, self.args) auth_success = validate_streamfwd_auth(auth_key) if not auth_success: self.response.status = 401 output = {} output['httpinputs'] = {'success': False, 'error': 'Unauthorized', 'status': 401} return output try: inputs = [] # Get list of HEC inputs uri = '/services/data/inputs/http/http?output_mode=json' serverResponse, serverContent = splunk.rest.simpleRequest( util.make_url_internal(uri), sessionKey, postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT ) if serverResponse['status'] == '200': jsonResp = json.loads(serverContent) config = jsonResp['entry'][0]['content'] output['httpinputsconfigs'] = config except Exception as e: logger.exception(e) raise splunk.RESTException(500, 'Internal error, failed to get HEC inputs') return output
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 create_input_streamfwd(token): # Coulnd't find the resource, and get 404 Not Found try: serverResponse, serverContent = splunk.rest.simpleRequest( app_util.make_url_internal(HTTPINPUT_URI + '?output_mode=json'), token, postargs={"name":"streamfwd"}, method='POST', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT ) logger.info("Create HTTP input for stream forwarder") except Exception as e: logger.exception(e)
def disable_streamfwd(flag, session_key): uri = STREAMFWD_URI #true flag to disable if flag: uri = uri + 'disable' else: uri = uri + 'enable' serverResponse, serverContent = splunk.rest.simpleRequest( app_util.make_url_internal(uri), session_key, postargs=None, method='POST', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT )
def migrate_to_kv_store(): if is_kv_store_supported_in_splunk() and is_kv_store_ready(): logger.info("starting migration...") auth_key = get_internal_shared_key() uri = '/services/splunk_app_stream/kvstoremigrate?output_mode=json&X-SPLUNK-APP-STREAM-KEY=' + auth_key try: serverResponse, serverContent = splunk.rest.simpleRequest( util.make_url_internal(uri), sessionKey='', postargs=None, method='POST', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunkd_time_out) except splunk.RESTException, re: logger.exception(re)
def is_streamfwd_disabled(session_key): disabled = True serverResponse, serverContent = splunk.rest.simpleRequest( app_util.make_url_internal(STREAMFWD_URI + '?output_mode=json'), session_key, postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunk.rest.SPLUNKD_CONNECTION_TIMEOUT ) status = serverResponse['status'] logger.info('status of streamfwd disabled state GET request %s ' % status) if status == '200': disabled_state = json.loads(serverContent)['entry'][0]['content']['disabled'] logger.info("streamfwd disabled state %s " % disabled_state) if not(disabled_state): disabled = False return disabled
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)
class AccountController(BaseController): """ Handle logging in and logging out """ # define filepath for successful login flag FLAG_FILE = util.make_splunkhome_path(['etc', '.ui_login']) # Store up to 100 credentials in memory during change password operations credential_cache = util.LRUDict(capacity=100) # The LRUDict is not thread safe; acquire a lock before operating with it credential_lock = threading.Lock() @expose_page(methods='GET') def index(self): return self.redirect_to_url('/') def updateCookieUID(self): """ Creates and sets a long-lived cookie uid. If a uid cookie already exists it will not overwrite it. """ if cherrypy.request.cookie.get('uid') is None: cherrypy.response.cookie['uid'] = splunk.util.uuid4().upper( ) # for consistency as splunkd returns uppercase guid cherrypy.response.cookie['uid']['expires'] = 5 * 365 * 24 * 3600 def genCookieTest(self): """ Creates a random cval integer """ return random.randint(0, 2**31) def cookieTest(self, cval): """ tests the given string and cval cookie value for type and value equality """ try: return int(cherrypy.request.cookie['cval'].value) == int(cval) except: return False def updateCookieTest(self): """ set a cookie to check that cookies are enabled and pass the value to the form """ cval = cherrypy.request.cookie.get('cval') if cval: try: cval = int(cval.value) except: cval = self.genCookieTest() else: cval = self.genCookieTest() cherrypy.response.cookie['cval'] = cval return cval def handleStormLogin(self, return_to=None, **kwargs): from splunk.appserver.mrsparkle.lib import storm cherrypy.session.regenerate() if cherrypy.request.method == 'POST' and kwargs.has_key('storm_token'): ts, token = storm.decrypt_token(kwargs['storm_token']) max_token_age = cherrypy.config.get('storm_max_token_age', 3600) if ts + max_token_age < time.time(): logger.warn("Storm session token has expired") token = defaults = None else: logger.info("Got storm token OK") cherrypy.session['storm_token'] = token new_session = True attempts = 2 ok = False while attempts: attempts -= 1 defaults = storm.get_storm_defaults(new_session) if not defaults: continue if splunk.auth.ping(sessionKey=defaults['sessionKey']): ok = True break if not defaults or not ok: if not defaults: logger.error( "Failed to fetch user's default settings from Storm" ) else: logger.error( "Storm issued a token with an invalid session key %s" % defaults['sessionKey']) token = defaults = None cherrypy.session['storm_token'] = None else: defaults = storm.get_storm_defaults() if not defaults: url = cherrypy.config.get('storm_user_url') if not url: storm_host = cherrypy.config.get('storm_host', '127.0.0.1') storm_port = cherrypy.config.get('storm_port', 80) if cherrypy.config['storm_port'] != 80: url = "http://%s:%s/" % (storm_host, storm_port) else: url = "http://%s/" % (storm_host) if return_to: return_quoted = urllib.quote_plus(return_to) url += "?return_to_splunkweb=" + return_quoted logger.warn( "action=storm_login_failed, redirect_url=%s, " "storm_token_set=%s", url, kwargs.has_key('storm_token')) raise cherrypy.HTTPRedirect(url) cherrypy.session['user'] = { 'name': defaults['user'], 'fullName': 'Storm User', 'id': 1 } cherrypy.session['sessionKey'] = defaults['sessionKey'] if return_to: # return_to could potentially have a query string and a fragment, and hence break in IE6 # since we're bypassing self.redirect_to_url, we have to check for that if util.is_ie_6( ) and not util.redirect_url_is_ie_6_safe(return_to): return self.client_side_redirect( util.make_url_internal(return_to)) raise cherrypy.HTTPRedirect(util.make_url_internal(return_to)) else: return self.redirect_to_url('/') def getUpdateCheckerBaseURL(self): # validate the checker URI updateCheckerBaseURL = str( cherrypy.config.get('updateCheckerBaseURL', '')).strip() if not any( map(updateCheckerBaseURL.startswith, ['http://', 'https://'])): updateCheckerBaseURL = None return updateCheckerBaseURL def getLoginTemplateArgs(self, return_to=None, session_expired_pw_change=False): """Generate the base template arguments for account/login.html""" ref = cherrypy.request.headers.get('Referer') # free license doesn't really expire; we just push the nagware here if cherrypy.config.get('is_free_license'): session_expired = False else: session_expired = ref and ref.startswith( cherrypy.request.base) and not ref.endswith( cherrypy.request.path_info) templateArgs = { 'return_to': return_to, 'session_expired': session_expired, 'session_expired_pw_change': session_expired_pw_change, 'updateCheckerBaseURL': self.getUpdateCheckerBaseURL(), 'serverInfo': self.getServerInfo(), 'isAutoComplete': self.isAutoComplete(), 'bad_cookies': False, 'cval': self.updateCookieTest(), 'loginContent': cherrypy.config.get('login_content', ''), 'hasLoggedIn': True } return templateArgs @expose_page(must_login=False, methods=['GET', 'POST'], verify_session=False) @lock_session @set_cache_level('never') 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) en = splunk.entity.getEntity('authentication/users', username, sessionKey=sessionKey) fullName = username if en and 'realname' in en and en['realname']: fullName = en['realname'] # Start with a clean and minty fresh session cherrypy.session.regenerate() cherrypy.session['sessionKey'] = sessionKey # TODO: get rest of user info cherrypy.session['user'] = { 'name': username, 'fullName': fullName, 'id': -1 } # Log user login logger.info('user=%s action=login status=success session=%s ' \ 'reason=user-initiated useragent="%s" clientip=%s' % (username, sessionKey, ua, ip)) # Stash the remote user if splunkd is in SSO mode. Note we do not stash the user if the # incoming request IP does not match any of the IP addresses in the list of trusted IPs. # This allows users to still login via SSO, logout, and login as another user # but ensures that if they logout of SSO, they will be logged out of Splunk. if util.in_sso_mode(): incoming_request_ip = cherrypy.request.remote.ip splunkweb_trusted_ip = splunk.util.stringToFieldList( cherrypy.config.get(decorators.SPLUNKWEB_TRUSTED_IP_CFG)) if incoming_request_ip in splunkweb_trusted_ip: remote_user_header = cherrypy.request.config.get( decorators.SPLUNKWEB_REMOTE_USER_CFG ) or decorators.DEFAULT_REMOTE_USER_HEADER cherrypy.session[ decorators. REMOTE_USER_SESSION_KEY] = cherrypy.request.headers.get( remote_user_header) # Check for an expired license and override any action if one is present if cherrypy.config['license_state'] == 'EXPIRED': templateArgs['return_to'] = '/licensing' # If this is the first time admin has logged in, suggest changing the password if not self.hasLoggedIn() and username == 'admin': self.setLoginFlag(True) templateArgs = {} templateArgs['return_to'] = return_to templateArgs['cpSessionKey'] = cherrypy.session.id return self.render_template('account/passwordchange.html', templateArgs) if return_to: # return_to could potentially have a query string and a fragment, and hence break in IE6 # since we're bypassing self.redirect_to_url, we have to check for that if util.is_ie_6( ) and not util.redirect_url_is_ie_6_safe(return_to): return self.client_side_redirect( util.make_url_internal(return_to)) # We need to redirect to the return_to page, but we also need to return # the new CSRF cookie. We do this by creating the redirect but not # raising it as an exception. Instead, we use set_response (which # you can read about here: http://docs.cherrypy.org/dev/refman/_cperror.html#functions), # which will set it on the cherrypy.response object. # Finally, we also do not return any content, since there is none # to return (as it is a redirect). redirect_response = cherrypy.HTTPRedirect( util.make_url_internal(return_to)) redirect_response.set_response() util.setFormKeyCookie() return return self.redirect_to_url('/')
def kv_store_rest_request(uri, method, sessionKey=None, repository=False, req_data=None): global kv_store_ready, splunkd_fatal_error jsonargs = None if splunkd_fatal_error: logger.error( 'kv_store_rest_request: fatal error splunkd is not responding hence returning error' ) return (500, { 'success': False, 'error': str("fatal error splunkd is not responding hence returning error"), 'status': 500 }) if kvstore_fatal_error: logger.error( 'kv_store_rest_request: fatal error kv store failed to start') return (500, { 'success': False, 'error': str("fatal error kv store failed to start"), 'status': 500 }) if kv_store_ready is None: kv_store_ready = is_kv_store_ready(sessionKey) if not kv_store_ready: logger.error( 'kv_store_rest_request: Timedout waiting for KVstore status %s to be ready' % kv_store_ready) return (500, { 'success': False, 'error': str("Timedout waiting for KVstore status to be ready "), 'status': 500 }) auth_key = get_internal_shared_key() if not sessionKey and method == 'GET': #proxy via splunkd REST endpoint logger.debug('kv_store_rest_request: No session key') uri_tail = uri[uri.index('data') + len('data') + 1:] uri_segments = uri_tail.split('/') uri_resource = uri_segments[0] uri_id = '' if len(uri_segments) == 2: uri_id = uri_segments[1] else: uri_resource = uri_tail if repository: uri = '/services/splunk_app_stream/' + uri_resource + '?output_mode=json&repository=true&X-SPLUNK-APP-STREAM-KEY=' + auth_key elif uri_id: uri = '/services/splunk_app_stream/' + uri_resource + '?output_mode=json' + '&id=' + uri_id + '&X-SPLUNK-APP-STREAM-KEY=' + auth_key else: uri = '/services/splunk_app_stream/' + uri_resource + '?output_mode=json&X-SPLUNK-APP-STREAM-KEY=' + auth_key logger.info( 'kv_store_rest_request: new uri generated for no session key ') try: serverResponse, serverContent = splunk.rest.simpleRequest( util.make_url_internal(uri), sessionKey='', postargs=None, method='GET', raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=None, timeout=splunkd_time_out) jsonResp = json.loads(serverContent) content = jsonResp["entry"][0]["content"] return (serverResponse, json.dumps(content)) except splunk.ResourceNotFound: # no need to log the 404s since it will return empty result in response raise except Exception as e: logger.exception(e) if any(s in str(e) for s in splunkd_connection_exceptions): splunkd_fatal_error = True raise if req_data: jsonargs = json.dumps(req_data) try: url_internal = util.make_url_internal( uri + '?output_mode=json&X-SPLUNK-APP-STREAM-KEY=' + auth_key) result = splunk.rest.simpleRequest(url_internal, sessionKey, postargs=None, method=method, raiseAllErrors=True, proxyMode=False, rawResult=None, jsonargs=jsonargs, timeout=splunkd_time_out) return result except splunk.ResourceNotFound: # no need to log the 404s since it will return empty result in response raise except Exception as e: logger.exception(e) if any(s in str(e) for s in splunkd_connection_exceptions): splunkd_fatal_error = True raise
def handleStormLogin(self, return_to=None, **kwargs): from splunk.appserver.mrsparkle.lib import storm cherrypy.session.regenerate() if cherrypy.request.method == 'POST' and kwargs.has_key('storm_token'): ts, token = storm.decrypt_token(kwargs['storm_token']) max_token_age = cherrypy.config.get('storm_max_token_age', 3600) if ts + max_token_age < time.time(): logger.warn("Storm session token has expired") token = defaults = None else: logger.info("Got storm token OK") cherrypy.session['storm_token'] = token new_session = True attempts = 2 ok = False while attempts: attempts -= 1 defaults = storm.get_storm_defaults(new_session) if not defaults: continue if splunk.auth.ping(sessionKey=defaults['sessionKey']): ok = True break if not defaults or not ok: if not defaults: logger.error("Failed to fetch user's default settings from Storm") else: logger.error("Storm issued a token with an invalid session key %s" % defaults['sessionKey']) token = defaults = None cherrypy.session['storm_token'] = None else: defaults = storm.get_storm_defaults() if not defaults: url = cherrypy.config.get('storm_user_url') if not url: storm_host = cherrypy.config.get('storm_host', '127.0.0.1') storm_port = cherrypy.config.get('storm_port', 80) if cherrypy.config['storm_port'] != 80: url = "http://%s:%s/" % (storm_host, storm_port) else: url = "http://%s/" % (storm_host) if return_to: return_quoted = urllib.quote_plus(return_to) url += "?return_to_splunkweb=" + return_quoted logger.warn("action=storm_login_failed, redirect_url=%s, " "storm_token_set=%s", url, kwargs.has_key('storm_token')) raise cherrypy.HTTPRedirect(url) cherrypy.session['user'] = { 'name': defaults['user'], 'fullName': 'Storm User', 'id': 1 } cherrypy.session['sessionKey'] = defaults['sessionKey'] if return_to: # return_to could potentially have a query string and a fragment, and hence break in IE6 # since we're bypassing self.redirect_to_url, we have to check for that if util.is_ie_6() and not util.redirect_url_is_ie_6_safe(return_to): return self.client_side_redirect(util.make_url_internal(return_to)) raise cherrypy.HTTPRedirect(util.make_url_internal(return_to)) else: return self.redirect_to_url('/')
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)
self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs(return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) except splunk.RESTException, e: err = e.get_message_text() if ':' in err: err = err[err.find(':')+2:] logger.error("Failed to change the password: %s." % err) templateArgs['err'] = err return self.render_template('account/passwordchange.html', templateArgs) if return_to and return_to[0]=='/': try: return self.redirect_to_url(util.make_url_internal(return_to), translate=False) except util.InvalidURLException: # invalid character in the URL supplied; fall through and redirect to / instead logger.warn("Invalid return_to URL passed to login page") pass return self.redirect_to_url('/') @expose_page(must_login=False, methods='GET') @lock_session def insecurelogin(self, username=None, password=None, return_to=None): ''' Provide insecure login endpoint for HTTP GET-based credential passing ''' # Force a refresh of startup info so that we know to
def handleStormLogin(self, return_to=None, **kwargs): from splunk.appserver.mrsparkle.lib import storm cherrypy.session.regenerate() if cherrypy.request.method == 'POST' and kwargs.has_key('storm_token'): ts, token = storm.decrypt_token(kwargs['storm_token']) max_token_age = cherrypy.config.get('storm_max_token_age', 3600) if ts + max_token_age < time.time(): logger.warn("Storm session token has expired") token = defaults = None else: logger.info("Got storm token OK") cherrypy.session['storm_token'] = token new_session = True attempts = 2 ok = False while attempts: attempts -= 1 defaults = storm.get_storm_defaults(new_session) if not defaults: continue if splunk.auth.ping(sessionKey=defaults['sessionKey']): ok = True break if not defaults or not ok: if not defaults: logger.error( "Failed to fetch user's default settings from Storm" ) else: logger.error( "Storm issued a token with an invalid session key %s" % defaults['sessionKey']) token = defaults = None cherrypy.session['storm_token'] = None else: defaults = storm.get_storm_defaults() if not defaults: url = cherrypy.config.get('storm_user_url') if not url: storm_host = cherrypy.config.get('storm_host', '127.0.0.1') storm_port = cherrypy.config.get('storm_port', 80) if cherrypy.config['storm_port'] != 80: url = "http://%s:%s/" % (storm_host, storm_port) else: url = "http://%s/" % (storm_host) if return_to: return_quoted = urllib.quote_plus(return_to) url += "?return_to_splunkweb=" + return_quoted logger.warn( "action=storm_login_failed, redirect_url=%s, " "storm_token_set=%s", url, kwargs.has_key('storm_token')) raise cherrypy.HTTPRedirect(url) cherrypy.session['user'] = { 'name': defaults['user'], 'fullName': 'Storm User', 'id': 1 } cherrypy.session['sessionKey'] = defaults['sessionKey'] if return_to: # return_to could potentially have a query string and a fragment, and hence break in IE6 # since we're bypassing self.redirect_to_url, we have to check for that if util.is_ie_6( ) and not util.redirect_url_is_ie_6_safe(return_to): return self.client_side_redirect( util.make_url_internal(return_to)) raise cherrypy.HTTPRedirect(util.make_url_internal(return_to)) else: return self.redirect_to_url('/')
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)
return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) except splunk.RESTException, e: err = e.get_message_text() if ':' in err: err = err[err.find(':') + 2:] logger.error("Failed to change the password: %s." % err) templateArgs['err'] = err return self.render_template('account/passwordchange.html', templateArgs) if return_to and return_to[0] == '/': try: return self.redirect_to_url(util.make_url_internal(return_to), translate=False) except util.InvalidURLException: # invalid character in the URL supplied; fall through and redirect to / instead logger.warn("Invalid return_to URL passed to login page") pass return self.redirect_to_url('/') @expose_page(must_login=False, methods='GET') @lock_session def insecurelogin(self, username=None, password=None, return_to=None): ''' Provide insecure login endpoint for HTTP GET-based credential passing '''
class DataPreviewController(controllers.BaseController): ''' Represents the data preview feature ''' # # attach common template args # def render_template(self, template_path, template_args={}): template_args['appList'] = self.get_app_manifest() return super(DataPreviewController, self).render_template(template_path, template_args) def get_app_manifest(self): ''' Returns a dict of all available apps to current user ''' output = cached.getEntities('apps/local', search=['disabled=false', 'visible=true'], count=-1) return output # # routed controllers # @route('/') @expose_page() 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' ) 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'}) template_args = { 'ns': ns, 'input_type': input_type, 'preview_limit_bytes': limit_bytes, 'endpoint_base': kwargs.get('endpoint_base'), 'cancel_link': util.make_url_internal( kwargs.get('return_to', self.make_url('/manager'))), 'manual_link': continue_link, 'breadcrumbs': crumbs, 'source': kwargs.get('source', ''), 'preview_base_link': self.make_url(['custom', 'splunk_datapreview', 'steps', 'preview']) } return self.render_template( '/splunk_datapreview:/templates/prompt.html', template_args)