def _transform_feed(self, xml): """ Make an Atom feed from the remote provider look as though we generated it by rewriting certain URLs in the feed. """ try: self._convert_remote_elements(xml) for entry in xml.xpath("//a:entry", namespaces=NSMAP): self._convert_remote_elements(entry) except Exception, e: logger.exception(e) raise splunk.InternalServerError(e)
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 _bundle_error(msg): tmp = lit("ERROR_APP_INSTALL__S") % msg logger.error(tmp) raise splunk.InternalServerError(tmp)
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()) except splunk.ResourceNotFound: raise except splunk.InternalServerError: raise except Exception, e: logger.exception(e) raise splunk.InternalServerError(e) def _native_to_foreign_url(self): """ Convert this endpoint's URL into a remote-provider URL. """ url = self._base for part in self.pathParts[self.BASE_DEPTH:]: url += "/" + part return url def _foreign_to_native_url(self, url): """ Convert a remote-provider URL into a URL pointing to this endpoint. """ if not url.startswith(self._base):
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)