Ejemplo n.º 1
0
def validate_subscription_credential(subscription_credential, async_splunk_client):
    if not subscription_credential:
        defer.returnValue(None)

    auth_header = SplunkAuthHeader(subscription_credential.session_key)
    is_valid_session_key = yield auth_header.validate(async_splunk_client)

    if not is_valid_session_key:
        auth_header = None

    defer.returnValue(auth_header)
Ejemplo n.º 2
0
async def validate_subscription_credential(subscription_credential,
                                           async_splunk_client):
    if not subscription_credential:
        return None

    auth_header = SplunkAuthHeader(subscription_credential.session_key)
    is_valid_session_key = await auth_header.validate(async_splunk_client)

    if not is_valid_session_key:
        auth_header = None

    return auth_header
Ejemplo n.º 3
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))
Ejemplo n.º 4
0
def handle_confirmation(auth_code, user, session_token, system_authtoken, body):
    """
    Handler for the final DevicePairingConfirmationRequest call. This function:
        1. Authenticates the supplied username and password
        2. Retrieves temporary record from the kvstore
        3. Checks if app_type has been disabled since registration
        4. Makes the DevicePairingConfirmationRequest request to the server
        5. Creates a new permanent record for the device in the kvstore
        6. Deletes the temporary kvstore record

    :param auth_code: User-entered authorization code to be returned to Spacebridge
    :param body: Parsed JSON body of the incoming POST request
    :param kvstore_unconfirmed: Access object for the temporary registration kvstore
    :param system_authtoken: System-level access token for writing to the kvstore
    :return: Success message
    """

    # Authenticates the supplied username and password
    kvstore_temp = KvStore(constants.UNCONFIRMED_DEVICES_COLLECTION_NAME, system_authtoken, owner=user)
    encryption_context = SplunkEncryptionContext(system_authtoken, constants.SPACEBRIDGE_APP_NAME)
    username = extract_parameter(body, USERNAME_LABEL, BODY_LABEL)
    password = extract_parameter(body, PASSWORD_LABEL, BODY_LABEL)

    try:
        # use what Splunk thinks the username is to generate the session token
        auth =  BasicAuthHeader(username, password)
        content = get_current_context(auth)
        username = content[constants.ENTRY][0][constants.CONTENT][constants.USERNAME]
    except SpacebridgePermissionsError as e:
        LOGGER.exception('Invalid credentials passed to current-context API')
        raise e


    LOGGER.info('Received new registration confirmation request by user=%s for device_owner=%s' % (user, username))

    # Retrieves temporary record from the kvstore
    temp_key = extract_parameter(body, KVSTORE_TEMPORARY_ID_LABEL, BODY_LABEL)
    r, temp_record = kvstore_temp.get_item_by_key(temp_key)
    temp_record = json.loads(temp_record)

    device_id = temp_record[DEVICE_ID_LABEL]
    device_id_raw = base64.b64decode(device_id)

    device_registration = {'_key': py23.urlsafe_b64encode_to_str(device_id_raw)}
    device_public_keys = {'_key': py23.urlsafe_b64encode_to_str(device_id_raw)}

    for k in temp_record.keys():
        if k in DEVICE_REGISTRATION_ATTRS:
            device_registration[k] = temp_record[k]
        if k in DEVICE_PUBLIC_KEYS_ATTRS:
            device_public_keys[k] = temp_record[k]


    # Checks if app_type has been disabled since registration
    app_name = temp_record[DEVICE_TYPE_LABEL]

    if not retrieve_state_of_app(app_name, system_authtoken):
        disabled_message = 'Registration Error: Application type app_name="%s" is disabled' % app_name
        LOGGER.info(disabled_message)
        return {
            'payload': {
                'message': disabled_message,
                'app_name': app_name,
            },
            'status': 422,
        }

    device_encryption_info = DeviceInfo(
        base64.b64decode(temp_record['encrypt_public_key']),
        base64.b64decode(temp_record['sign_public_key']),
        base64.b64decode(temp_record['device_id']),
        "NA",
        app_id=temp_record['app_id'],
        app_name=temp_record['device_type']
    )

    deployment_friendly_name = get_deployment_friendly_name(system_authtoken)

    try:
        credentials = SplunkJWTCredentials(username, password=password)
        credentials.load_jwt_token(SplunkAuthHeader(session_token))
        LOGGER.info("Successfully fetched jwt token")
    except Exception as e:
        LOGGER.info("Failed to fetch jwt token with message={}. Using basic credentials instead.".format(e))
        credentials = SimpleUserCredentials(username, password)

    pair_device(auth_code, credentials, device_encryption_info, encryption_context,
                server_name=deployment_friendly_name, config=config, server_app_id=constants.SPLAPP_APP_ID)

    # Creates a new permanent record for the device in the kvstore
    kvstore_user = KvStore(constants.REGISTERED_DEVICES_COLLECTION_NAME, system_authtoken, owner=username)
    kvstore_user.insert_single_item(device_registration)

    # Adds the user to the list of users with registered devices, if not already there
    kvstore_users = KvStore(constants.REGISTERED_USERS_COLLECTION_NAME, system_authtoken)
    kvstore_users.insert_or_update_item_containing_key({'_key': username})

    kvstore_nobody = KvStore(constants.DEVICE_PUBLIC_KEYS_COLLECTION_NAME, system_authtoken)
    kvstore_nobody.insert_single_item(device_public_keys)

    # Deletes the temporary kvstore record
    kvstore_temp.delete_item_by_key(temp_key)

    LOGGER.info('Device registration confirmed. Device with device_name=\"%s\" was recorded in the kvstore.' %
                temp_record[DEVICE_NAME_LABEL])

    return {
        'payload': 'Device registration successful',
        'status': 201,
    }
def _to_auth_header(credentials):
    auth_header = SplunkAuthHeader(credentials.session_key)
    if credentials.session_type == JWT_TOKEN_TYPE:
        auth_header = JWTAuthHeader(credentials.user, credentials.session_key)

    return auth_header
    def do_run(self, input_config):
        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)
        self.logger.info("Loading encryption context")
        encryption_context = SplunkEncryptionContext(self.session_key,
                                                     SPACEBRIDGE_APP_NAME,
                                                     sodium_client)

        self.logger.info(
            "Running Subscription Manager modular input on search head")

        # 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:
            minimum_iteration_time_seconds = float(input_config[
                self.input_config_key][self.minimum_iteration_time_seconds])
            warn_threshold_seconds = float(input_config[self.input_config_key][
                self.warn_threshold_seconds])
            subscription_processor_parallelism_str = input_config[
                self.input_config_key][self.subscription_processor_parallelism]
            subscription_parallelism = self._resolve_parallelism(
                subscription_processor_parallelism_str)
        except:
            self.logger.exception(
                "Failed to load required configuration values")
            return

        try:
            self.logger.info("Processing subscriptions with parallelism=%s",
                             subscription_parallelism)
            auth_header = SplunkAuthHeader(self.session_key)

            self.logger.debug(
                "Using search processor python=%s, script=%s, args=%s",
                self.python_path, self.script_path, self.subprocess_args)
            start_job = start_job_using_subprocess(self.python_path,
                                                   self.subprocess_args)

            if subscription_parallelism == self.CONFIG_VALUE_SINGLE_PROCESS:
                start_job = start_job_single_process(sodium_client,
                                                     encryption_context)

            process_manager = ProcessManager(subscription_parallelism,
                                             start_job)
            job_context = JobContext(
                auth_header, uri,
                encryption_context.get_encryption_keys().to_json())

            subscription_manager = SubscriptionManager(
                input_config=input_config,
                encryption_context=encryption_context,
                auth_header=auth_header,
                shard_id=shard_id,
                job_context=job_context,
                search_loader=loader.load_search_bundle,
                parent_process_monitor=ParentProcessMonitor(),
                minimum_iteration_time_seconds=minimum_iteration_time_seconds,
                warn_threshold_seconds=warn_threshold_seconds,
                process_manager=process_manager)

            subscription_manager.run()
        except:
            self.logger.exception(
                "Unhandled exception during subscription processing")