class SubscriptionCleanUpModularInput(modular_input.ModularInput):
    title = 'Splunk Cloud Gateway Subscription Clean Up'
    description = 'Clean up expired subscriptions'
    app = 'Splunk App Cloud Gateway'
    name = 'splunkappcloudgateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    logger = setup_logging(SPACEBRIDGE_APP_NAME + '.log',
                           'subscription_clean_up_modular_input.app')
    input_config_key = "subscription_clean_up_modular_input://default"
    config_key_cleanup_threashold_seconds = "cleanup_threshold_seconds"

    def do_run(self, input_config):
        """
        Executes the modular input
        :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

        self.logger.debug(
            "Running Subscription Clean Up modular input on search captain node"
        )
        cleanup_time_seconds = input_config[self.input_config_key][
            self.config_key_cleanup_threashold_seconds]
        subscription_clean_up = SubscriptionCleanUp(self.session_key,
                                                    int(cleanup_time_seconds))

        try:
            subscription_clean_up.run()
        except:
            self.logger.exception(
                "Failure encountered while running Subscription Clean Up")
Example #2
0
class MetricsModularInput(modular_input.ModularInput):
    """

    Modular input to periodically collect cloudgateway metrics
    """
    title = 'Splunk Cloud Gateway Metrics Collector'
    description = 'Collects metrics for Splunk Cloud Gateway'
    app = 'Splunk App Cloud Gateway'
    name = 'splunkappcloudgateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    logger = setup_logging(constants.SPACEBRIDGE_APP_NAME + '_metrics.log',
                           'cloudgateway_metrics.app')

    def do_run(self, input_config):
        """
        Main entry path for input
        """
        self.logger.info("Running cloud gateway metrics modular input")
        if not modular_input_should_run(self.session_key, logger=self.logger):
            self.logger.debug("Modular input will not run on this node.")
            return

        try:
            time.sleep(30)
            collector = SpacebridgeaAppMetricsCollector(
                self.logger, self.session_key)
            collector.run()
        except:
            self.logger.exception("Exception calculating cloudgateway metrics")
Example #3
0
class DroneModeSubscriptionModularInput(modular_input.ModularInput):
    """
    Main entry for processing Drone Mode Subscriptions
    """
    title = 'Splunk Cloud Gateway Drone Mode Subscription Processor'
    description = ('Clean up expired subscriptions, and '
                   'send data through Splunk Cloud Gateway send message api')
    app = 'Splunk App Cloud Gateway'
    name = 'splunkappcloudgateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    logger = setup_logging(
        SPACEBRIDGE_APP_NAME + '_drone_mode_modular_input.log',
        'drone_mode_modular_input.app')

    def do_run(self, input_config):
        """
        This will spin up a drone mode subscription manager and begins the reactor loop
        :param input_config:
        :return:
        """

        try:
            sodium_client = SodiumClient(self.logger.getChild('sodium_client'))
            encryption_context = SplunkEncryptionContext(
                self.session_key, SPACEBRIDGE_APP_NAME, sodium_client)

            self.logger.debug(
                "Running Drone Mode Subscription Manager modular input")

            # 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=%s", uri)
            except Exception:
                self.logger.exception(
                    "Failed to verify load_balancer_address.")

            if not uri:
                return

            subscription_manager = DroneModeSubscriptionManager(
                input_config=input_config,
                encryption_context=encryption_context,
                session_key=self.session_key,
                async_splunk_client=AsyncSplunkClient(uri),
                parent_process_monitor=ParentProcessMonitor(),
                cluster_monitor=ClusterMonitor(
                    self.logger,
                    interval=config.get_cluster_monitor_interval()))
            subscription_manager.run()

        except Exception as e:
            self.logger.exception(
                'An error occurred running the drone mode subscription modular input'
            )
            raise e
Example #4
0
class DeviceRolesMappingModularInput(modular_input.ModularInput):
    """
    """
    title = 'Splunk Secure Gateway Role Based Notification Manager'
    description = 'Used for sending mobile alerts to users by role'
    app = 'Splunk Secure Gateway'
    name = 'splunk_secure_gateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    logger = setup_logging(SPACEBRIDGE_APP_NAME + '_modular_input.log',
                           'ssg_device_role_mapping.app')
    input_config_key = "ssg_device_role_modular_input://default"

    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")
Example #5
0
class AlertsTTLModularInput(modular_input.ModularInput):
    title = 'Splunk Cloud Gateway Mobile Alerts TTL'
    description = 'Cleans up storage of old mobile alerts'
    app = 'Splunk App Cloud Gateway'
    name = 'splunkappcloudgateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    logger = setup_logging(constants.SPACEBRIDGE_APP_NAME + '.log',
                           'alerts_ttl_modular_input.app')
    ttl_days = "ttl_days"
    input_config_key = "alerts_ttl_modular_input://default"

    def construct_ttl_list(self, ttl_days):
        return []

    def do_run(self, input_config):
        """
        Executes the modular input using the input config which specifies TTL for alerts
        """
        if not modular_input_should_run(self.session_key, logger=self.logger):
            self.logger.debug("Modular input will not run on this node.")
            return

        self.logger.info("Running Alerts TTL modular input with input=%s" %
                         str(input_config))
        alerts_ttl_utility = AlertsTtlUtility(
            self.session_key,
            float(input_config[self.input_config_key][self.ttl_days]))
        alerts_ttl_utility.run()

    def extra_arguments(self):
        """
        Override extra_arguments list for modular_input scheme
        :return:
        """
        return [{
            'name': 'ttl_days',
            'title': 'TTL in Days',
            'description': 'Alert ttl specified in days'
        }]
class RegisteredUsersListModularInput(modular_input.ModularInput):
    title = 'Splunk Secure Gateway Registered Users List'
    description = 'Sync the list of registered gateway users'
    app = 'Splunk Secure Gateway'
    name = 'splunk_secure_gateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    logger = setup_logging(SPACEBRIDGE_APP_NAME + '.log',
                           'ssg_registered_users_list_modular_input.app')
    input_config_key = "ssg_registered_users_list_modular_input://default"

    def do_run(self, input_config):
        """
        Executes the modular input
        :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

        if get_splunk_auth_type(authtoken=self.session_key) == constants.SAML:
            self.logger.debug(
                "Registered Users List modular input should not run on SAML environment"
            )
            return

        self.logger.info(
            "Running Registered Users List modular input on search captain node"
        )
        registered_users_sync = RegisteredUsersSync(self.session_key)

        try:
            registered_users_sync.run()
        except:
            self.logger.exception(
                "Failure encountered while running Registered Users List sync")
warnings.filterwarnings('ignore', '.*service_identity.*', UserWarning)

from spacebridgeapp.util import py23

import fileinput
import sys
from cloudgateway.device import EncryptionKeys
from cloudgateway.splunk.encryption import EncryptionContext
from cloudgateway.private.sodium_client import SodiumClient
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.rest.clients.async_client_factory import AsyncClientFactory
from spacebridgeapp.subscriptions.subscription_processor import process_pubsub_subscription
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME
from twisted.internet import reactor, task, defer

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_subscription_subprocess.log",
                       "subscription_subprocess")


@defer.inlineCallbacks
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:
Example #8
0
from cloudgateway.auth import SimpleUserCredentials
from cloudgateway.splunk.auth import SplunkJWTCredentials, SplunkAuthHeader
from cloudgateway.splunk.encryption import SplunkEncryptionContext
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util import constants
from spacebridgeapp.util.config import cloudgateway_config as config
from spacebridgeapp.rest.base_endpoint import BaseRestHandler
from spacebridgeapp.rest.services.kvstore_service import KVStoreCollectionAccessObject as KvStore
from spacebridgeapp.rest.services.splunk_service import authenticate_splunk_credentials
from spacebridgeapp.rest.config.app import retrieve_state_of_app
from spacebridgeapp.rest.util.helper import extract_parameter
from spacebridgeapp.rest.config.deployment_info import get_deployment_friendly_name
from spacebridgeapp.request.request_processor import BasicAuthHeader


LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + ".log", "rest_registration_confirmation")

BODY_LABEL = 'body'
QUERY_LABEL = 'query'
AUTH_CODE_LABEL = 'auth_code'
USERNAME_LABEL = 'username'
PASSWORD_LABEL = 'password'
DEVICE_NAME_LABEL = 'device_name'
DEVICE_ID_LABEL = 'device_id'
DEVICE_TYPE_LABEL = 'device_type'
KVSTORE_TEMPORARY_ID_LABEL = 'temp_key'

DEVICE_REGISTRATION_ATTRS = ['device_name', 'device_type', 'device_id', 'app_id']
DEVICE_PUBLIC_KEYS_ATTRS = ['encrypt_public_key', 'sign_public_key']

Example #9
0
from splunk.clilib.bundle_paths import make_splunkhome_path

sys.path.append(
    make_splunkhome_path(['etc', 'apps', 'splunk_secure_gateway', 'bin']))
from spacebridgeapp.util import py23

from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util import constants
from spacebridgeapp.rest.base_endpoint import BaseRestHandler
from spacebridgeapp.rest.util.helper import extract_parameter
from spacebridgeapp.rest.util import errors as Errors
from spacebridgeapp.rest.services.qr_code_service import generate_qr_code
from spacebridgeapp.rest.services.qr_code_service import get_valid_file_types
from spacebridgeapp.dashboard.dashboard_helpers import shorten_dashboard_id_from_url

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + ".log",
                       "rest_qr_code_for_dashboard")

DASHBOARD_ID_LABEL = 'dashboard_id'
QR_CODE_DASHBOARD_VERSION = '1'


class QrCodeForDashboard(BaseRestHandler,
                         PersistentServerConnectionApplication):
    """
    Main class for handling the devices_user endpoint. Subclasses the spacebridge_app
    BaseRestHandler.
    """
    def __init__(self, command_line, command_arg):
        BaseRestHandler.__init__(self)

    def get(self, request):
Example #10
0
from splunk.clilib.bundle_paths import make_splunkhome_path

sys.path.append(
    make_splunkhome_path(['etc', 'apps', 'splunk_app_cloudgateway', 'bin']))
from spacebridgeapp.util import py23

from twisted.web import http
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.rest.util import errors as Errors
from spacebridgeapp.rest.base_endpoint import BaseRestHandler
from spacebridgeapp.rest.services.splunk_service import get_app_list_request
from spacebridgeapp.rest.services.kvstore_service import KVStoreCollectionAccessObject as KvStore
from spacebridgeapp.util.constants import USER_META_COLLECTION_NAME, SPACEBRIDGE_APP_NAME, AUTHTOKEN, \
                                          SESSION, USER, DASHBOARD_APP_LIST, APP_LIST, APP_NAMES, KEY

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + ".log", "rest_app_list")


class AppList(BaseRestHandler, PersistentServerConnectionApplication):
    """
    Main class for handling the app_list endpoint. Subclasses the spacebridge_app
    BaseRestHandler.

    """
    def __init__(self, command_line, command_arg):
        BaseRestHandler.__init__(self)

    def get(self, request):
        """
        Handler which retrieves kvstore app_list data for the current user
        """
Example #11
0
"""
Copyright (C) 2009-2020 Splunk Inc. All Rights Reserved.
"""

import splunk
import sys

from spacebridgeapp.util.constants import OR_OPERATOR, AND_OPERATOR, NOT_EQUAL
from spacebridgeapp.util.splunk_utils.statestore import StateStore
import splunk.rest as rest
from spacebridgeapp.util import constants

from spacebridgeapp.logging import setup_logging
logger = setup_logging(constants.SPACEBRIDGE_APP_NAME + '_kvstore_writer.log',
                       'kvstore_writer.app')


def build_containedin_clause(key, values):
    return {OR_OPERATOR: [{key: value} for value in values]}


def build_not_containedin_clause(key, values):
    return {AND_OPERATOR: [{key: {NOT_EQUAL: value}} for value in values]}


class KVStoreBatchWriter(StateStore):
    """
    Class extending ITSI's KV Store batch writer but customizing it to support injecting our own app name
    """
    def __init__(self, **kwargs):
        super(KVStoreBatchWriter, self).__init__(**kwargs)
Example #12
0
sys.path.append(
    make_splunkhome_path(['etc', 'apps', 'splunk_secure_gateway', 'bin']))
from spacebridgeapp.util import py23

from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util import constants
from spacebridgeapp.util.config import secure_gateway_config as config
from spacebridgeapp.util.mtls import build_key_bundle
from spacebridgeapp.rest.base_endpoint import BaseRestHandler
from spacebridgeapp.rest.util.helper import extract_parameter
from spacebridgeapp.rest.services.kvstore_service import KVStoreCollectionAccessObject as KvStore
from spacebridgeapp.rest.services.spacebridge_service import delete_device_from_spacebridge
from spacebridgeapp.rest.services.splunk_service import get_devices_for_user, user_has_registered_devices

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + ".log",
                       "rest_delete_device")
DEVICE_KEY_LABEL = 'device_key'


class DeleteDevice(BaseRestHandler, PersistentServerConnectionApplication):
    """
    Main rest handler class for the delete device functionality
    """
    def __init__(self, command_line, command_arg):
        BaseRestHandler.__init__(self)

    def post(self, request):
        """
        Deletes the specified device from the kvstore. Parses necessary data and credentials
        out of the request object, validates permissions, and makes the deletion request.
Example #13
0
from spacebridgeapp.ar.ar_util import is_non_string_iterable
from spacebridgeapp.ar.data.asset_data import AssetData
from spacebridgeapp.ar.permissions.async_permissions_client import Capabilities, AccessQuantity, ARObjectType
from spacebridgeapp.ar.storage.queries import get_query_matching_keys
from spacebridgeapp.exceptions.spacebridge_exceptions import SpacebridgeApiRequestError, SpacebridgeARPermissionError
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util.constants import (KEY, ASSETS_COLLECTION_NAME,
                                           SPACEBRIDGE_APP_NAME, ASSET_OBJECTS,
                                           ASSET_GROUP, AND_OPERATOR,
                                           OR_OPERATOR, ASSET_GROUP_OBJECTS,
                                           ASSET_GROUPS_COLLECTION_NAME, QUERY,
                                           MANAGE_PERMISSION_REQUIRED)
from twisted.internet import defer
from twisted.web import http

LOGGER = setup_logging('{}_assets.log'.format(SPACEBRIDGE_APP_NAME), "assets")
ASSET_MANAGE_PERMISSION_REQUIRED = MANAGE_PERMISSION_REQUIRED.format(
    object_type='asset')


class MissingAssetIDException(SpacebridgeApiRequestError):
    def __init__(self, message):
        super(MissingAssetIDException,
              self).__init__(message, status_code=http.BAD_REQUEST)


class NoSuchAssetException(SpacebridgeApiRequestError):
    def __init__(self, asset_id):
        super(NoSuchAssetException, self).__init__(
            message='asset_id={} does not exist'.format(asset_id),
            status_code=http.NOT_FOUND)
Example #14
0
class SpacebridgeModularInput(modular_input.ModularInput):
    """ Main entry path for launching the Spacebridge Application
    Modular Input
    Arguments:
        modular_input {[type]} -- [description]
    """
    title = 'Splunk Cloud Gateway'
    description = 'Initializes the Splunk Cloud Gateway application to talk to mobile clients over websockets'
    app = 'Splunk App Cloud Gateway'
    name = 'splunkappcloudgateway'
    use_kvstore_checkpointer = False
    use_hec_event_writer = False
    health_check_rerun_seconds = 60
    logger = setup_logging(
        constants.SPACEBRIDGE_APP_NAME + '_modular_input.log',
        'cloudgateway_modular_input.app')

    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))
Example #15
0
DASHBOARD_LIST_REQUEST = 'dashboard_list'
APP_LIST_REQUEST = 'app_list'
ALL_APPS_REQUEST = 'all_apps'
TV_LIST_REQUEST = 'tv_list'
TV_CONFIG_REQUEST = 'tv_config'
TV_CONFIG_BULK_REQUEST = 'tv_config_bulk'
TV_BOOKMARK_REQUEST = 'tv_bookmark'
ACTIVATE_TV_BOOKMARK_REQUEST = 'activate_tv_bookmark'
DRONE_MODE_TV_SUBSCRIBE_REQUEST = 'drone_mode_tv_subscribe'
DRONE_MODE_IPAD_SUBSCRIBE_REQUEST = 'drone_mode_ipad_subscribe'
MPC_BROADCAST_REQUEST = 'mpc_broadcast'
TV_INTERACTION_REQUEST = 'tv_interaction'
TV_CAPTAIN_URL_REQUEST = 'captain_url'
SUBSCRIPTION_PING = 'subscription_ping'

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + ".log", "rest_async_bridge")
VALID_GET_REQUESTS = {
    DASHBOARD_LIST_REQUEST, APP_LIST_REQUEST, ALL_APPS_REQUEST,
    TV_LIST_REQUEST, TV_BOOKMARK_REQUEST
}
VALID_POST_REQUESTS = {
    APP_LIST_REQUEST, TV_CONFIG_REQUEST, TV_CONFIG_BULK_REQUEST,
    TV_BOOKMARK_REQUEST, ACTIVATE_TV_BOOKMARK_REQUEST,
    DRONE_MODE_TV_SUBSCRIBE_REQUEST, DRONE_MODE_IPAD_SUBSCRIBE_REQUEST,
    MPC_BROADCAST_REQUEST, TV_INTERACTION_REQUEST, TV_CAPTAIN_URL_REQUEST,
    SUBSCRIPTION_PING
}
VALID_DELETE_REQUESTS = {TV_BOOKMARK_REQUEST, TV_CONFIG_REQUEST}


class AsyncBridge(BaseRestHandler, PersistentServerConnectionApplication):
Example #16
0
from cloudgateway.private.encryption.encryption_handler import sign_detached
from twisted.internet import defer
from twisted.web import http
from spacebridge_protocol import http_pb2
from spacebridgeapp.dashboard.udf_util import parse_hosted_resource_path, HostedResourceType, \
    build_encrypted_resource, get_collection_from_resource_type
from spacebridgeapp.exceptions.spacebridge_exceptions import SpacebridgeApiRequestError
from spacebridgeapp.util import constants
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.messages.util import fetch_device_info
from spacebridgeapp.request.request_processor import SpacebridgeAuthHeader

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + "_udf_request_processor", "udf_request_processor")


@defer.inlineCallbacks
def process_udf_hosted_resource_get(request_context,
                                    client_single_request,
                                    server_single_response,
                                    async_kvstore_client=None,
                                    async_spacebridge_client=None,
                                    encryption_context=None):
    """
    Process a UDF hosted resource get request. This used for fetching assets which are used within UDF dashboards
    such as images.
    :param request_context:
    :param client_single_request:
    :param server_single_response:
    :param async_kvstore_client:
    :param async_spacebridge_client:
    :param encryption_context:
Copyright (C) 2009-2020 Splunk Inc. All Rights Reserved.
"""

import json
import time
import splunk
import splunk.rest as rest
from spacebridgeapp.util import py23
from spacebridgeapp.util import constants
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util.constants import NOBODY
from spacebridgeapp.util.string_utils import encode_whitespace, append_path_to_uri

import urllib.parse as urllib

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + "_kvstore_service.log",
                       "kvstore_service")


class KVStoreCollectionAccessObject(object):
    def __init__(self,
                 collection=None,
                 session_key=None,
                 app=constants.SPACEBRIDGE_APP_NAME,
                 owner=NOBODY,
                 timestamp_attribute_name='timestamp'):
        rest_uri = rest.makeSplunkdUri()
        path = f'servicesNS/{owner}/{app}/storage/collections/data/{collection}'
        self.uri = append_path_to_uri(rest_uri, path)
        self.session_key = session_key
        self.timestamp_attribute_name = timestamp_attribute_name
"""
(C) 2019 Splunk Inc. All rights reserved.

REST endpoint handler for accessing and setting kvstore records
"""

import splunk.rest as rest
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.exceptions.load_balancer_exceptions import GetConfigError, AddressVerificationError
from spacebridgeapp.util import constants
from spacebridgeapp.util.config import cloudgateway_config as config

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + ".log",
                       "load_balancer_verification")
from spacebridgeapp.util import py23


def get_uri(session_key):
    """
    Construct URI for REST API calls using the load balancer address or the Splunkd URI if not provided
    :param session_key:
    :return: URI string
    """
    uri = config.get_config(stanza=config.SETUP,
                            key=config.LOAD_BALANCER_ADDRESS,
                            default=rest.makeSplunkdUri())
    if not uri:
        raise GetConfigError(
            "Failed to get load balancer address from cloudgateway.conf")

    # If load balancer address is given, verify that it is correct
Example #19
0
import json
from collections import defaultdict

from spacebridgeapp.data.subscription_data import Subscription, SearchUpdate, SubscriptionCredential
from spacebridgeapp.exceptions.spacebridge_exceptions import SpacebridgeApiRequestError
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.subscriptions.subscription_requests import fetch_searches_for_shard
from spacebridgeapp.util.constants import SEARCH_KEY, SUBSCRIPTION_KEY, KEY, QUERY, SPACEBRIDGE_APP_NAME, NOBODY, \
    SUBSCRIPTIONS_COLLECTION_NAME, SEARCH_UPDATES_COLLECTION_NAME, SUBSCRIPTION_CREDENTIALS_COLLECTION_NAME
from spacebridgeapp.util.kvstore import build_containedin_clause
from splapp_protocol.common_pb2 import Error
from twisted.internet import defer
from twisted.web import http

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_subscription_loader.log",
                       "subscription_loader")


def _noop(arg):
    return arg


def _collect(arr, grouping_key):
    grouped = defaultdict(list)
    for item in arr:
        value = getattr(item, grouping_key)
        grouped[value].append(item)
    return grouped


@defer.inlineCallbacks
import sys
import json
from splunk.persistconn.application import PersistentServerConnectionApplication
from splunk.clilib.bundle_paths import make_splunkhome_path

sys.path.append(
    make_splunkhome_path(['etc', 'apps', 'splunk_secure_gateway', 'bin']))
from spacebridgeapp.util import py23

from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util import constants
from spacebridgeapp.rest.base_endpoint import BaseRestHandler
from spacebridgeapp.rest.services import splunk_service
from spacebridgeapp.util.constants import ENCRYPTION_KEYS

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + ".log",
                       "sign_credentials_handler")


class SignCredentialsHandler(BaseRestHandler,
                             PersistentServerConnectionApplication):
    def __init__(self, command_line, command_arg):
        BaseRestHandler.__init__(self)

    def get(self, request):
        """
        Fetch public and private keys for signing messages from the passwords endpoint
        :param request:
        :return:
        """
        LOGGER.info('Received request for fetching encrypted credentials')
        system_authtoken = request['system_authtoken']
Example #21
0
import json
from twisted.internet import defer
from twisted.web import http
from cloudgateway.splunk.auth import SplunkAuthHeader
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME, SEARCHES_COLLECTION_NAME, \
    SUBSCRIPTIONS_COLLECTION_NAME, SEARCH_KEY, QUERY, NOBODY, \
    SUBSCRIPTION_CREDENTIALS_COLLECTION_NAME, FIELDS, KEY, PARENT_SEARCH_KEY, SHARD_ID, VERSION, SUBSCRIPTION_VERSION_2, \
    SEARCH, AND_OPERATOR, SUBSCRIPTION_TYPE, SUBSCRIPTION_KEY
from spacebridgeapp.exceptions.spacebridge_exceptions import SpacebridgeApiRequestError
from spacebridgeapp.request.dashboard_request_processor import fetch_dashboard_description
from spacebridgeapp.data.subscription_data import SubscriptionSearch, Subscription, SubscriptionCredential
from spacebridgeapp.data.search_type import SearchType
from spacebridgeapp.logging import setup_logging


LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_subscription_requests.log",
                       "subscription_requests")


@defer.inlineCallbacks
def fetch_searches_for_shard(auth_header, shard_id, async_kvstore_client):
    query = {SHARD_ID: shard_id, VERSION: SUBSCRIPTION_VERSION_2}
    params = {QUERY: json.dumps(query)}

    LOGGER.debug("Querying for searches, params=%s", params)

    searches = yield fetch_searches(auth_header=auth_header,
                                    params=params,
                                    async_kvstore_client=async_kvstore_client)

    LOGGER.debug("Found active searches count=%d", len(searches))
Example #22
0
"""
(C) 2019 Splunk Inc. All rights reserved.

Separate module to capture send methods
"""

from twisted.internet import defer
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME
from spacebridge_protocol import websocket_pb2, sb_common_pb2

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_send_processor.log",
                       "send_processor")


@defer.inlineCallbacks
def send_response(request_context, message_sender, server_application_response,
                  websocket_protocol, encrypt, sign, generichash):
    if not server_application_response.WhichOneof('app_message'):
        LOGGER.info("No response necessary")
        defer.returnValue(None)

    # Take server payload and wrap in an envelope
    payload = server_application_response.SerializeToString()
    encrypted_payload = encrypt(payload)

    signed_envelope = yield build_envelope(encrypted_payload, message_sender,
                                           websocket_protocol,
                                           request_context.request_id, sign,
                                           generichash)
Example #23
0
"""Copyright (C) 2009-2020 Splunk Inc. All Rights Reserved."""
import random

from spacebridgeapp.logging import setup_logging
from spacebridgeapp.rest.clients.async_client_factory import AsyncClientFactory
from spacebridgeapp.subscriptions.job_result import JobResult
from spacebridgeapp.subscriptions.subscription_processor import process_pubsub_subscription
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME
from spacebridgeapp.util.mtls import build_mtls_spacebridge_client
from spacebridgeapp.util.config import secure_gateway_config as config
from multiprocessing import Pool
import asyncio

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + '_process_manager.log',
                       'process_manager')


class JobContext(object):
    def __init__(self,
                 auth_header,
                 splunk_uri,
                 encryption_context,
                 search_context=None,
                 subscription_update_ids=None):
        self.auth_header = auth_header
        self.splunk_uri = splunk_uri
        self.encryption_context = encryption_context
        self.search_context = search_context

        if subscription_update_ids is None:
            subscription_update_ids = {}
Example #24
0
import sys
from functools import reduce

from splunk.clilib.bundle_paths import make_splunkhome_path
from splunk.persistconn.application import PersistentServerConnectionApplication

sys.path.append(
    make_splunkhome_path(['etc', 'apps', 'splunk_secure_gateway', 'bin']))
from spacebridgeapp.util import py23

from spacebridgeapp.logging import setup_logging
from spacebridgeapp.util import constants
from spacebridgeapp.rest.base_endpoint import BaseRestHandler
from spacebridgeapp.rest.services.splunk_service import get_all_mobile_users, get_all_users, get_devices_for_user

LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + ".log",
                       "rest_users_devices")


class DevicesForUser(BaseRestHandler, PersistentServerConnectionApplication):
    """
    Main class for handling the devices_user endpoint. Subclasses the spacebridge_app
    BaseRestHandler.
    """
    def __init__(self, command_line, command_arg):
        BaseRestHandler.__init__(self)

    def get(self, request):
        """
        Handler which retrieves all devices in the kvstore belonging to all users.
        """
        # Retrieves all devices from that user's devices kvstore collection
Example #25
0
(C) 2020 Splunk Inc. All rights reserved.

Module for representation of data objects for event_handler
"""

import json
import os

os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'

from splapp_protocol import event_handler_pb2, common_pb2
from spacebridgeapp.data.base import SpacebridgeAppBase
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME, VALUE, LABEL, MATCH
from spacebridgeapp.logging import setup_logging

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_event_handler.log", "event_handler")


class Change(SpacebridgeAppBase):
    """
    Container for data for change element. A change element contains set, unset, eval, link and conditions
    """

    def __init__(self, link=None, sets=None, evals=None, unsets=None, conditions=None):
        self.link = link
        self.sets = sets or []
        self.evals = evals or []
        self.unsets = unsets or []
        self.conditions = conditions or []

    def set_protobuf(self, proto):
Example #26
0
from spacebridgeapp.dashboard.dashboard_request_json import fetch_dashboard_list_json
from spacebridgeapp.data.dashboard_data import DashboardData
from spacebridgeapp.data.dashboard_data import DashboardVisualizationId
from spacebridgeapp.data.dashboard_data import UserDashboardMeta
from spacebridgeapp.util.config import secure_gateway_config as config
from spacebridgeapp.metrics.dashboard_request_metrics import send_dashboard_list_request_metrics_to_telemetry
from spacebridgeapp.request.app_list_request_processor import fetch_dashboard_app_list_with_default

if sys.version_info < (3, 0):
    import urllib

else:
    import urllib.parse as urllib

LOGGER = setup_logging(
    constants.SPACEBRIDGE_APP_NAME + "_dashboard_request_processor.log",
    "dashboard_request_processor")

# API Name Constants
DASHBOARD_LIST_REQUEST = "DASHBOARD_LIST_REQUEST"


async def process_dashboard_list_request(request_context,
                                         client_single_request,
                                         server_single_response,
                                         async_client_factory):
    """
    This method will process dashboard list requests

    :param request_context:
    :param client_single_request:
Example #27
0
import sys
from twisted.internet import defer
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.exceptions.spacebridge_exceptions import SpacebridgeApiRequestError
from spacebridgeapp.dashboard.dashboard_request_json import fetch_dashboard_list_json
from spacebridgeapp.dashboard.dashboard_helpers import shorten_dashboard_id_from_url, parse_dashboard_id, \
    generate_dashboard_id

if sys.version_info < (3, 0):
    from urlparse import urlparse, parse_qsl

else:
    from urllib.parse import urlparse, parse_qsl

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_drilldown_helpers.log",
                       "drilldown_helpers")

FORM_PREFIX = "form."
SPLUNK_URL_PREFIX = '/app/'


def parse_dashboard_link(url=None):
    """
    Helper to parse dashboard_id and input_map from drilldown link
    :param url:
    :return:
    """
    dashboard_id = ''
    input_map = {}

    if url and url.startswith(SPLUNK_URL_PREFIX):
from spacebridgeapp.util.kvstore import build_containedin_clause
from spacebridgeapp.util.time_utils import get_current_timestamp_str
from spacebridgeapp.logging import setup_logging
from spacebridgeapp.messages.request_context import RequestContext
from spacebridgeapp.drone_mode.data.drone_mode_data import TVConfig, TVList
from spacebridgeapp.drone_mode.data.enums import TVEventType, IPadEventType
from spacebridgeapp.data.subscription_data import Subscription, SubscriptionCredential, DroneModeTVEvent, DroneModeiPadEvent
from spacebridgeapp.request.request_processor import SpacebridgeAuthHeader
from spacebridgeapp.rest.devices.user_devices import public_keys_for_device
from spacebridgeapp.drone_mode.drone_mode_subscription_update_message import build_drone_mode_subscription_update
from spacebridgeapp.subscriptions.subscription_update_message import build_send_subscription_update_request
from spacebridgeapp.drone_mode.drone_mode_utils import get_drone_mode_tvs, get_registered_tvs, has_grid
from spacebridgeapp.request.request_processor import get_splunk_cookie, JWTAuthHeader

LOGGER = setup_logging(
    constants.SPACEBRIDGE_APP_NAME + "_drone_mode_subscription_requests.log",
    "drone_mode_subscription_requests")


@defer.inlineCallbacks
def fetch_valid_tvs(request_context,
                    async_kvstore_client,
                    user=None,
                    tv_ids=None):
    """
    Function to fetch valid tvs for drone mode
    :param request_context: request context used to make kvstore requests
    :param async_kvstore_client: async client used to make kvstore requests
    :param device_id: optional device id to filter on
    """
    # fetch list of all registered tvs
"""
Copyright (C) 2009-2020 Splunk Inc. All Rights Reserved.
"""

import os

os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
from spacebridge_protocol import http_pb2
from spacebridge_protocol import sb_common_pb2
from splapp_protocol import envelope_pb2
from spacebridgeapp.util import constants

TTL_SECONDS = 259200

from spacebridgeapp.logging import setup_logging
LOGGER = setup_logging(constants.SPACEBRIDGE_APP_NAME + '_mobile_alert.log', 'ssg_mobile_alert')


def build_notification_request(device_id, device_id_raw, sender_id, notification, encrypt, sign):
    """

    :param device_id: A string representation of the device id
    :param device_id_raw: A byte representation of the device id
    :param sender_id: A byte representation of the sender
    :param notification: A Notification proto object
    :param encrypt: a 1 argument function that encrypts some plaintext
    :param sign: a 1 argument function that will calculate a signature for some byte input
    :return: A proto notification message if encryption and signing succeed, None otherwise
    """

    LOGGER.info("Building notification alert_id=%s, device_id=%s" % (notification.alert_id, device_id))
Example #30
0
import jsonpickle
import sys
from http import HTTPStatus
from spacebridgeapp.data.dashboard_data import UserDashboardMeta
from spacebridgeapp.exceptions.spacebridge_exceptions import SpacebridgeApiRequestError
from spacebridgeapp.util.constants import SPACEBRIDGE_APP_NAME, DASHBOARD_META_COLLECTION_NAME
from spacebridgeapp.logging import setup_logging

if sys.version_info < (3, 0):
    import urllib

else:
    import urllib.parse as urllib

LOGGER = setup_logging(SPACEBRIDGE_APP_NAME + "_dashboard_meta.log",
                       "dashboard_meta")


async def fetch_dashboard_meta(request_context,
                               dashboard_id=None,
                               async_kvstore_client=None):
    """
    Helper to fetch dashboard_meta
    :param request_context:
    :param dashboard_id:
    :param async_kvstore_client:
    :return:
    """
    # Only set the key_id if a dashboard_id is provided
    key_id = urllib.quote_plus(dashboard_id) if dashboard_id else None
    response = await async_kvstore_client.async_kvstore_get_request(