def handle_POST(self): self.verifyAllowRemote() try: post_args = urlencode(self.request["form"]) if sys.version_info >= (3, 0): post_args = post_args.encode() logger.debug("Logging into %s" % self._login) bundle_paths.BundleInstaller().validate_server_cert( self._login, self._sslpol) # Forward post arguments, including username and password. with closing(urlopen(self._login, post_args, URLOPEN_TIMEOUT)) as f: root = safe_lxml.parse(f).getroot() token = root.xpath("a:id", namespaces=NSMAP)[0].text if self.request["output_mode"] == "json": self.response.setHeader('content-type', 'application/json') sessDict = {"response": {"sessionKey": token}} self.response.write(json.dumps(sessDict)) else: # Generate response. response = etree.Element("response") sessionKey = etree.SubElement(response, "sessionKey") sessionKey.text = token self.response.setHeader('content-type', 'text/xml') self.response.write( etree.tostring(response, pretty_print=True)) logger.debug("Login successful") except HTTPError as e: if e.code in [401, 405]: # Returning 401 logs off current session # Splunkbase retuns 405 when only password is submitted raise splunk.RESTException(400, e.msg) raise splunk.RESTException(e.code, e.msg) except Exception as e: logger.exception(e) raise splunk.AuthenticationFailed
def handle_POST(self): """ Install a remote application in response to an HTTP POST. """ self.verifyAllowRemote() parts = len(self.pathParts) if parts == self.BASE_DEPTH + 2: default_version = True elif parts == self.BASE_DEPTH + 3: default_version = False else: raise splunk.BadRequest if not self.args.has_key(HTTP_AUTH_TOKEN): raise splunk.BadRequest("Missing argument: %s" % HTTP_AUTH_TOKEN) if not self.args.has_key(HTTP_ACTION): raise splunk.BadRequest("Missing argument: %s" % HTTP_ACTION) if self.args[HTTP_ACTION] != HTTP_ACTION_INSTALL: raise splunk.BadRequest("Invalid value '%s' for argument '%s'" % (self.args[HTTP_ACTION], HTTP_ACTION)) url = self._native_to_foreign_url() root = self._get_feed_root(url) if default_version: root = self._get_latest_version(root) href = self._parse_link(root) try: # Package up a Request with auth information. req = urllib2.Request(href) # XXX: Converting the auth token from a POST arg to a header # requires us to unquote() it. If the client did not correctly # quote() the token, login will fail. req.add_header(HTTP_AUTH_HEADER, urllib.unquote(self.args[HTTP_AUTH_TOKEN])) # Install using this Request object. installer = bundle_paths.BundleInstaller() b, status = installer.install_from_url(req) self.response.setStatus(status) if ((status == bundle_paths.BundleInstaller.STATUS_INSTALLED) or (status == bundle_paths.BundleInstaller.STATUS_UPGRADED)): # Migrate old-style bundles. logger.debug("Configuring application contents") try: b.migrate() except Exception, e: logger.exception(e) self.addMessage("WARN", "Error during configuration: %s" % e) # Redirect to local application. self.response.setHeader("Location", self._redirect_to_local(b)) # Let splunkd know about newly-installed app. logger.debug("Notifying splunkd that app has been installed") splunk.rest.simpleRequest('apps/local/_reload', sessionKey=self.sessionKey) if status == bundle_paths.BundleInstaller.STATUS_INSTALLED: self.addMessage("INFO", "Installed application: %s" % b.name()) elif status == bundle_paths.BundleInstaller.STATUS_UPGRADED: self.addMessage("INFO", "Upgraded application: %s" % b.name()) else: self.addMessage("WARN", "Could not install application: %s" % b.name())
def installApp(location, force=False): installer = bundle_paths.BundleInstaller() location = location.strip() try: if location.startswith('http'): req = urllib2.Request(url=location) return installer.install_from_url(req, force) else: return installer.install_from_tar(location, force) except splunk.ResourceNotFound, e: raise admin.ArgValidationException(e.msg)
def _get_feed_root(self, url, extra_get_args={}): """ Get an Atom feed of application information from the remote provider. """ try: target_url = url # Forward GET arguments, and add user-agent. args_dict = {} headers = {} args_dict.update(self.request["query"]) if (len(extra_get_args) > 0): args_dict.update(extra_get_args) if self._platformInfo: args_dict.update(self._platformInfo) args = urlencode(args_dict) if args != "": target_url += ("?" + args) logger.debug("Getting feed from: %s" % target_url) if self._agent: headers["User-Agent"] = self._agent bundle_paths.BundleInstaller().validate_server_cert( target_url, self._sslpol) req = Request(target_url, None, headers) f = urlopen(req, None, URLOPEN_TIMEOUT) except HTTPError as e: raise splunk.RESTException(e.code, e.msg) except URLError as e: logger.exception(e) raise splunk.RESTException( 503, "Splunk is unable to connect to the Internet to find more apps." ) except Exception as e: logger.exception(e) raise splunk.RESTException(404, "Resource not found") try: root = safe_lxml.parse(f).getroot() f.close() return root except Exception as e: raise splunk.InternalServerError(e)
def handle_POST(self): """ Install a remote application in response to an HTTP POST. """ self.verifyAllowRemote() parts = len(self.pathParts) if parts == self.BASE_DEPTH + 2: default_version = True elif parts == self.BASE_DEPTH + 3: default_version = False else: raise splunk.BadRequest if HTTP_AUTH_TOKEN not in self.args: raise splunk.BadRequest("Missing argument: %s" % HTTP_AUTH_TOKEN) if HTTP_ACTION not in self.args: raise splunk.BadRequest("Missing argument: %s" % HTTP_ACTION) if self.args[HTTP_ACTION] not in (HTTP_ACTION_INSTALL, HTTP_ACTION_DOWNLOAD): raise splunk.BadRequest("Invalid value '%s' for argument '%s'" % (self.args[HTTP_ACTION], HTTP_ACTION)) # check if this is a cloud stack if isCloud(self.sessionKey): app_name = self.pathParts[self.BASE_DEPTH + 1] # Get all cloud apps and see if the app being installed is vetted for cloud # i.e install_method == simple # TODO: Change to just querying for the app in question when BASE-4074 # is finished. getargs = {'offset': 0, 'limit': 100} vetted_apps = [] while 1: serverResponse, serverContent = splunk.rest.simpleRequest( VETTED_APPS_URI, self.sessionKey, getargs) if serverResponse.status != 200: raise splunk.BadRequest( 'Error while querying Splunkbase. Splunkd returned %s' % serverContent) vetted_app_data = json.loads(serverContent) if not vetted_app_data['results']: break else: getargs['offset'] += 100 vetted_apps.extend(vetted_app_data['results']) for app in vetted_apps: if app['appid'] == app_name and app[ 'install_method'] == VETTED_APP_INSTALL_METHOD: break else: raise splunk.BadRequest( 'App %s is not vetted for Splunk Cloud.' % app_name) url = self._native_to_foreign_url() root = self._get_feed_root(url) if default_version: root = self._get_latest_version(root) href = self._parse_link(root) try: # Package up a Request with auth information. req = Request(href) # XXX: Converting the auth token from a POST arg to a header # requires us to unquote() it. If the client did not correctly # quote() the token, login will fail. req.add_header(HTTP_AUTH_HEADER, unquote(self.args[HTTP_AUTH_TOKEN])) # Install using this Request object. installer = bundle_paths.BundleInstaller() if self.args[HTTP_ACTION] == HTTP_ACTION_INSTALL: b, status = installer.install_from_url(req, sslpol=self._sslpol) self.response.setStatus(status) if ((status == bundle_paths.BundleInstaller.STATUS_INSTALLED) or (status == bundle_paths.BundleInstaller.STATUS_UPGRADED)): # Migrate old-style bundles. logger.debug("Configuring application contents") try: b.migrate() except Exception as e: logger.exception(e) self.addMessage("WARN", "Error during configuration: %s" % e) # Redirect to local application. self.response.setHeader("Location", self._redirect_to_local(b)) # Let splunkd know about newly-installed app. logger.debug( "Notifying splunkd that app has been installed") splunk.rest.simpleRequest('apps/local/_reload', sessionKey=self.sessionKey) if status == bundle_paths.BundleInstaller.STATUS_INSTALLED: self.addMessage("INFO", "Installed application: %s" % b.name()) elif status == bundle_paths.BundleInstaller.STATUS_UPGRADED: self.addMessage("INFO", "Upgraded application: %s" % b.name()) else: self.addMessage( "WARN", "Could not install application: %s" % b.name()) else: assert self.args[HTTP_ACTION] == HTTP_ACTION_DOWNLOAD downloaded = installer.download_from_url(req, sslpol=self._sslpol) self.addMessage("INFO", "Downloaded application file: %s" % downloaded) self.response.setHeader('content-type', 'application/json') response_json = {"downloaded": downloaded} self.response.write(json.dumps(response_json)) except splunk.ResourceNotFound: raise except splunk.AuthorizationFailed: raise except splunk.InternalServerError: raise except Exception as e: logger.exception(e) raise splunk.InternalServerError(e)