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)
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
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))
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")