示例#1
0
async def do_trigger(alert_payload):
    auth_header = SplunkAuthHeader(alert_payload[SESSION_KEY])

    # Use default URI for alerts
    try:
        uri = rest.makeSplunkdUri()
    except Exception as e:
        LOGGER.exception("Failed to generate default URI")

    if not uri:
        return

    mtls_spacebridge_client = None
    mtls_enabled = config.get_mtls_enabled()
    if mtls_enabled:
        mtls_spacebridge_client = build_mtls_spacebridge_client(alert_payload[SESSION_KEY])

    async_client_factory = AsyncClientFactory(uri, spacebridge_client=mtls_spacebridge_client)
    async_kvstore_client = async_client_factory.kvstore_client()
    async_splunk_client = async_client_factory.splunk_client()
    async_spacebridge_client = async_client_factory.spacebridge_client()

    alert_sid = alert_payload[SEARCH_ID]
    preprocess_payload(alert_payload)

    # Default to empty string so urllib.quote doesn't fail if user doesn't exist
    user = alert_payload[RESULT].get(USER, '')
    request_context = RequestContext(auth_header=auth_header, is_alert=True, current_user=user)

    LOGGER.info("get_registered_devices alert_sid=%s", alert_sid)
    registered_devices = await get_registered_devices(request_context, async_kvstore_client, alert_payload)
    LOGGER.info("get_registered_devices ok alert_sid=%s", alert_sid)

    alert = await build_alert(request_context, alert_payload, async_splunk_client, async_kvstore_client)
    LOGGER.info("persist_alert alert_id=%s", alert_sid)
    response = persist_alert(alert, auth_header.session_token)
    LOGGER.info("persist_alert ok succeeded alert_id=%s", alert_sid)

    # If we get a proper response from KV Store, then we get the key of the stored alert
    # and create a (device_id, alert_id, timestamp) triplet for each device that should
    # receive the alert

    if response is not None and "_key" in response.keys():
        alert_id = response["_key"]
        alert.notification.alert_id = alert_id

        # Persisting (recipient device, alert id) pairs and sending push notifications happens simultaneously via async
        LOGGER.info("persist_recipient_devices alert_id=%s", alert_id)
        await persist_recipient_devices(request_context, alert_id, registered_devices, alert_payload,
                                        async_kvstore_client)
        LOGGER.info("persist_recipient_devices ok alert_id=%s", alert_id)
        LOGGER.info("send_push_notifications starting registered_devices=%s", len(registered_devices))
        await send_push_notifications(
            request_context, alert.notification, registered_devices, async_kvstore_client, async_spacebridge_client,
            async_splunk_client)
示例#2
0
def do_trigger(reactor, alert_payload):
    auth_header = SplunkAuthHeader(alert_payload[SESSION_KEY])

    # Use default URI for alerts
    try:
        uri = rest.makeSplunkdUri()
    except Exception as e:
        LOGGER.exception("Failed to generate default URI. {}".format(e))

    if not uri:
        return

    async_client_factory = AsyncClientFactory(uri)
    async_kvstore_client = async_client_factory.kvstore_client()
    async_splunk_client = async_client_factory.splunk_client()
    async_spacebridge_client = async_client_factory.spacebridge_client()

    alert_sid = alert_payload[SEARCH_ID]
    preprocess_payload(alert_payload)

    request_context = RequestContext(auth_header=auth_header, is_alert=True)

    LOGGER.info("get_registered_devices alert_sid=%s" % alert_sid)
    registered_devices = yield get_registered_devices(request_context,
                                                      async_kvstore_client,
                                                      alert_payload)
    LOGGER.info("get_registered_devices ok alert_sid=%s" % alert_sid)

    alert = yield build_alert(request_context, alert_payload,
                              async_splunk_client, async_kvstore_client)
    LOGGER.info("persist_alert alert_id=%s" % alert_sid)
    response = persist_alert(alert, auth_header.session_token)
    LOGGER.info("persist_alert ok succeeded alert_id=%s" % alert_sid)

    # If we get a proper response from KV Store, then we get the key of the stored alert
    # and create a (device_id, alert_id, timestamp) triplet for each device that should
    # receive the alert

    if response is not None and "_key" in response.keys():
        alert_id = response["_key"]
        alert.notification.alert_id = alert_id

        # Persisting (recipient device, alert id) pairs and sending push notifications happens simultaneously via async
        LOGGER.info("persist_recipient_devices alert_id=%s" % alert_id)
        persist_recipient_devices(request_context, alert_id,
                                  registered_devices, alert_payload,
                                  async_kvstore_client)
        LOGGER.info("persist_recipient_devices ok alert_id=%s" % alert_id)
        LOGGER.info("send_push_notifications starting registered_devices=%s" %
                    len(registered_devices))
        yield send_push_notifications(request_context, alert.notification,
                                      registered_devices, async_kvstore_client,
                                      async_spacebridge_client,
                                      async_splunk_client)
示例#3
0
    def executor(job_contexts):
        deferreds = []
        for job in job_contexts:
            LOGGER.debug("Processing search job. search_key=%s", job.search_context.search.key())
            async_client_factory = AsyncClientFactory(job.splunk_uri)
            d = process_pubsub_subscription(job.auth_header, encryption_context,
                                            async_client_factory.spacebridge_client(),
                                            async_client_factory.kvstore_client(),
                                            async_client_factory.splunk_client(), job.search_context)
            deferreds.append(d)

        return FakeProcess(defer.DeferredList(deferreds, consumeErrors=True))
示例#4
0
 def __init__(self, system_auth_header,
              async_client_factory: AsyncClientFactory):
     """
     :param async_splunk_client (AsyncSplunkClient)
     :param async_kvstore_client:(AsyncKvStoreClient)
     :param system_auth_header: (AuthHeader)
     """
     self.async_splunk_client = async_client_factory.splunk_client()
     self.async_kvstore_client = async_client_factory.kvstore_client()
     self.async_spacebridge_client = async_client_factory.spacebridge_client(
     )
     self.async_telemetry_client = async_client_factory.telemetry_client()
     self.system_auth_header = system_auth_header
示例#5
0
    def do_run(self, inputs):
        """
        The entry point for the modular input.

        :param inputs: The command line arguments used when running this modular input. See the parent method definition
                       for more details.
        """
        # noinspection PyBroadException
        try:
            if not modular_input_should_run(self.session_key, LOGGER):
                LOGGER.debug('The AR modular input will not run on this host.')
                return

            uri = rest.makeSplunkdUri()
            _wait_for_kvstore_to_start(uri=uri,
                                       session_key=self.session_key,
                                       timeout_seconds=30)

            task.react(self._run_initialization, [AsyncClientFactory(uri)])
        except SystemExit as e:
            if e.code != 0:
                LOGGER.exception(
                    'Exited AR modular input with non-zero exit_code=%d message=%s',
                    e.code, e.message)
            else:
                LOGGER.debug(
                    'Successfully ran the AR initialization modular input.')
        except Exception:
            LOGGER.exception(
                'Unhandled exception while running AR modular input.')
示例#6
0
async def subprocess_subscription(job_context, mtls_enabled):
    mtls_spacebridge_client = None
    if mtls_enabled:
        mtls_spacebridge_client = build_mtls_spacebridge_client(
            job_context.auth_header.session_token)

    encryption_context = job_context.encryption_context
    async_client_factory = AsyncClientFactory(
        job_context.splunk_uri, spacebridge_client=mtls_spacebridge_client)
    result = JobResult(False)
    try:
        result = await process_pubsub_subscription(
            job_context.auth_header, encryption_context,
            async_client_factory.spacebridge_client(),
            async_client_factory.kvstore_client(),
            async_client_factory.splunk_client(), job_context.search_context,
            job_context.subscription_update_ids)
    except Exception:
        LOGGER.exception("Failed to process subscription")

    return result
示例#7
0
    def do_run(self, input_config):
        """ Spins up a websocket connection Spacebridge and begins
        the reactor loops
        """
        shard_id = default_shard_id()

        self.logger.info("Starting libsodium child process")
        sodium_logger = self.logger.getChild('sodium_client')
        sodium_logger.setLevel(logging.WARN)

        sodium_client = SodiumClient(sodium_logger)
        encryption_context = SplunkEncryptionContext(
            self.session_key, constants.SPACEBRIDGE_APP_NAME, sodium_client)

        self.logger.info(
            "Running Splunk Cloud Gateway modular input on search head, shard_id=%s",
            shard_id)

        # Fetch load balancer address if configured, otherwise use default URI
        try:
            uri = get_uri(self.session_key)
            self.logger.debug(
                "Successfully verified load_balancer_address={}".format(uri))
        except Exception as e:
            self.logger.exception(
                "Failed to verify load_balancer_address. {}".format(e))

        if not uri:
            return

        try:
            ensure_deployment_friendly_name(self.session_key)
            async_client_factory = AsyncClientFactory(uri)
            cloudgateway_message_handler = CloudgatewayMessageHandler(
                SplunkAuthHeader(self.session_key),
                logger=self.logger,
                encryption_context=encryption_context,
                async_client_factory=async_client_factory,
                shard_id=shard_id)

            client = CloudGatewayWsClient(
                encryption_context,
                message_handler=cloudgateway_message_handler,
                mode=WebsocketMode.ASYNC,
                logger=self.logger,
                config=config,
                shard_id=shard_id)

            client.connect()
        except Exception as e:
            self.logger.exception(
                "Exception connecting to cloud gateway={0}".format(e))
示例#8
0
    def do_run(self, input_config):
        """
        This will update the Device Role Mapping table in KV Store with the new mapping of a device to role
        :param input_config:
        :return:
        """
        if not modular_input_should_run(self.session_key, logger=self.logger):
            self.logger.debug("Modular input will not run on this node.")
            return

        # Use default URI for Device Role Mapping
        try:
            uri = rest.makeSplunkdUri()
        except Exception as e:
            self.logger.exception(
                "Failed to generate default URI. {}".format(e))

        if not uri:
            return

        try:
            async_client_factory = AsyncClientFactory(uri)
            kvstore_client = async_client_factory.kvstore_client()
            splunk_client = async_client_factory.splunk_client()
            asyncio.run(update(self.session_key, kvstore_client,
                               splunk_client))
        except SystemExit as e:
            if e.code == 0:
                self.logger.debug(
                    "device to role mapping updated successfully with code={}".
                    format(str(e.code)))
            else:
                self.logger.error(
                    "device to role mapping update failed with error={}".
                    format(str(e)))
        except:
            self.logger.exception(
                "Unexpected exception in device to role mapping")
def _run(job_contexts, sodium_client):
    errors = []

    LOGGER.debug("Running search process, searches=%s", len(job_contexts))

    for job in job_contexts:
        LOGGER.debug("Processing search job.  search_key=%s",
                     job.search_context.search.key())
        encryption_keys = EncryptionKeys.from_json(job.encryption_keys)
        encryption_context = EncryptionContext(encryption_keys, sodium_client)
        async_client_factory = AsyncClientFactory(job.splunk_uri)
        try:
            yield process_pubsub_subscription(
                job.auth_header, encryption_context,
                async_client_factory.spacebridge_client(),
                async_client_factory.kvstore_client(),
                async_client_factory.splunk_client(), job.search_context)
        except Exception as e:
            LOGGER.exception("Failed to process search, search_key=%s",
                             job.search_context.search.key())
            errors.append(e)

    if len(errors) > 0:
        raise errors[0]
示例#10
0
 def __init__(self,
              input_config,
              encryption_context,
              session_key,
              async_splunk_client,
              parent_process_monitor=None,
              cluster_monitor=None,
              async_client_factory=None,
              async_kvstore_client=None,
              async_spacebridge_client=AsyncSpacebridgeClient()):
     """
     Subscription Manager constructor
     :param input_config:
     :param encryption_context:
     :param session_key:
     :param async_kvstore_client:
     :param async_splunk_client:
     :param async_spacebridge_client:
     """
     self.input_config = input_config
     self.encryption_context = encryption_context
     self.session_key = session_key
     self.parent_process_monitor = parent_process_monitor
     self.cluster_monitor = cluster_monitor
     self.async_splunk_client = async_splunk_client
     self.async_spacebridge_client = async_spacebridge_client
     self.system_auth_header = SplunkAuthHeader(self.session_key)
     if not async_client_factory:
         uri = get_uri(self.session_key)
         async_client_factory = AsyncClientFactory(uri)
     self.async_client_factory = async_client_factory
     if not async_kvstore_client:
         async_kvstore_client = self.async_client_factory.kvstore_client()
     self.async_kvstore_client = async_kvstore_client
     self.request_context = RequestContext(
         auth_header=self.system_auth_header,
         current_user=constants.ADMIN,
         system_auth_header=self.system_auth_header)
示例#11
0
 def __init__(self, command_line, command_arg):
     BaseRestHandler.__init__(self)
     Thread(target=reactor.run, args=(False, )).start()
     self.uri = rest.makeSplunkdUri()
     self.async_client_factory = AsyncClientFactory(self.uri)
     self.async_kvstore_client = self.async_client_factory.kvstore_client()
示例#12
0
class AsyncBridge(BaseRestHandler, PersistentServerConnectionApplication):
    """
    Main class for handling the async_bridge endpoint. Subclasses the spacebridge_app
    BaseRestHandler.

    """
    def __init__(self, command_line, command_arg):
        BaseRestHandler.__init__(self)
        Thread(target=reactor.run, args=(False, )).start()
        self.uri = rest.makeSplunkdUri()
        self.async_client_factory = AsyncClientFactory(self.uri)
        self.async_kvstore_client = self.async_client_factory.kvstore_client()

    def get(self, request):
        """
        Handler which passes off requests to the relevant GET handler
        """

        request_type = request[QUERY].get(REQUEST_TYPE)

        if request_type not in VALID_GET_REQUESTS:
            return {
                'payload': 'No request_type supplied',
                'status': http.BAD_REQUEST,
            }

        authtoken = request[SESSION][AUTHTOKEN]
        user = request[SESSION][USER]
        auth_header = SplunkAuthHeader(authtoken)

        request_context = RequestContext(auth_header,
                                         current_user=user,
                                         system_auth_header=auth_header)

        if request_type == DASHBOARD_LIST_REQUEST:
            response = dashboard_list_request(request,
                                              self.async_client_factory,
                                              request_context)

        elif request_type == APP_LIST_REQUEST:
            response = get_app_list_request(request, self.async_client_factory,
                                            request_context)

        elif request_type == ALL_APPS_REQUEST:
            response = get_all_apps_request(request, self.async_client_factory,
                                            request_context)

        elif request_type == TV_LIST_REQUEST:
            response = get_tv_request(request, self.async_kvstore_client,
                                      request_context)

        elif request_type == TV_BOOKMARK_REQUEST:
            response = get_tv_bookmark_request(request,
                                               self.async_kvstore_client,
                                               request_context)

        status = http.OK
        if 'error' in response:
            status = http.INTERNAL_SERVER_ERROR
        return {
            'payload': response,
            'status': status,
        }

    def post(self, request):
        """
        Handler which passes off requests to the relevant POST handler
        """
        authtoken = request[SESSION][AUTHTOKEN]
        request_type = request[QUERY].get(REQUEST_TYPE)
        user = request[SESSION][USER]
        auth_header = SplunkAuthHeader(authtoken)
        system_auth_header = auth_header
        request_context = RequestContext(auth_header,
                                         current_user=user,
                                         system_auth_header=system_auth_header)

        if request_type not in VALID_POST_REQUESTS:
            return {
                'payload': 'No request_type supplied',
                'status': http.BAD_REQUEST,
            }

        if request_type == APP_LIST_REQUEST:
            response = post_app_list_request(request,
                                             self.async_client_factory,
                                             request_context)

        elif request_type == TV_CONFIG_REQUEST:
            response = post_tv_config_request(request,
                                              self.async_client_factory,
                                              request_context)

        elif request_type == TV_CONFIG_BULK_REQUEST:
            response = post_tv_config_bulk_request(request,
                                                   self.async_client_factory,
                                                   request_context)

        elif request_type == TV_BOOKMARK_REQUEST:
            response = post_tv_bookmark_request(request,
                                                self.async_kvstore_client,
                                                request_context)

        elif request_type == ACTIVATE_TV_BOOKMARK_REQUEST:
            response = activate_tv_bookmark_request(request,
                                                    self.async_client_factory,
                                                    request_context)

        elif request_type == DRONE_MODE_IPAD_SUBSCRIBE_REQUEST:
            response = drone_mode_ipad_subscribe_request(
                request, self.async_client_factory, request_context)

        elif request_type == DRONE_MODE_TV_SUBSCRIBE_REQUEST:
            response = drone_mode_tv_subscribe_request(
                request, self.async_client_factory, request_context)

        elif request_type == MPC_BROADCAST_REQUEST:
            response = mpc_broadcast_request(request,
                                             self.async_client_factory,
                                             request_context)

        elif request_type == TV_INTERACTION_REQUEST:
            response = tv_interaction_request(request,
                                              self.async_client_factory,
                                              request_context)

        elif request_type == TV_CAPTAIN_URL_REQUEST:
            response = tv_captain_url_request(request,
                                              self.async_client_factory,
                                              request_context)

        elif request_type == SUBSCRIPTION_PING:
            response = subscription_ping(request, self.async_client_factory,
                                         request_context)

        status = http.OK
        if 'error' in response:
            status = http.INTERNAL_SERVER_ERROR

        return {
            'payload': response,
            'status': status,
        }

    def delete(self, request):
        """
        Handler which passes off requests to the relevant DELETE handler
        """
        authtoken = request[SESSION][AUTHTOKEN]
        request_type = request[QUERY].get(REQUEST_TYPE)
        user = request[SESSION][USER]
        auth_header = SplunkAuthHeader(authtoken)
        system_auth_header = auth_header
        request_context = RequestContext(auth_header,
                                         current_user=user,
                                         system_auth_header=system_auth_header)

        if request_type not in VALID_DELETE_REQUESTS:
            return {
                'payload':
                'Invalid request_type supplied or request_type not present',
                'status': http.BAD_REQUEST,
            }

        if request_type == TV_BOOKMARK_REQUEST:
            response = delete_tv_bookmark_request(request,
                                                  self.async_kvstore_client,
                                                  request_context)

        elif request_type == TV_CONFIG_REQUEST:
            response = delete_tv_config_request(request,
                                                self.async_client_factory,
                                                request_context)

        status = http.OK
        if 'error' in response:
            status = http.INTERNAL_SERVER_ERROR

        return {
            'payload': response,
            'status': status,
        }
 def __init__(self, command_line, command_arg, async_client_factory=None):
     # command_line and command_arg are passed in (but for some reason unused??) by the Splunk REST framework.
     # Accepting them at this level saves us from making all subclasses accept them.
     super(AsyncBaseRestHandler, self).__init__()
     self.async_client_factory = async_client_factory or AsyncClientFactory(
         rest.makeSplunkdUri())
 def __init__(self, command_line, command_arg):
     BaseRestHandler.__init__(self)
     self.base_uri = rest.makeSplunkdUri()
     self.async_client_factory = AsyncClientFactory(self.base_uri)