Esempio n. 1
0
    def post(self, request):
        """
        Handler which creates a new app_list data entry in kvstore for the
        current user
        """
        # Check payload is valid
        # create kvstore entry
        app_list = validate_write_request(request)
        params = {KEY: DASHBOARD_APP_LIST, APP_NAMES: app_list}

        kvstore = KvStore(USER_META_COLLECTION_NAME,
                          request[SESSION][AUTHTOKEN],
                          owner=request[SESSION][USER])
        try:
            kvstore.insert_or_update_item_containing_key(params)
            return {
                'payload':
                'Successfully wrote app_list={} for user={}'.format(
                    app_list, request[SESSION][USER]),
                'status':
                http.OK,
            }

        except Exception as e:
            raise Errors.SpacebridgeRestError(
                'Error: failed to write kvstore entry with id={}'.format(
                    DASHBOARD_APP_LIST), 400)
def set_deployment_friendly_name(auth_token, name):
    """
    Given an auth token and name, set the deployment friendly name in the 'meta' collection
    :param auth_token: A valid splunk system auth token
    :param name: the string representation of the mame you want to give the deployment
    :return:
    """
    kvstore = KvStore(constants.META_COLLECTION_NAME,
                      auth_token,
                      owner=constants.NOBODY)

    deployment_info = {
        '_key': constants.DEPLOYMENT_INFO,
        constants.DEPLOYMENT_FRIENDLY_NAME: name
    }

    kvstore.insert_or_update_item_containing_key(deployment_info)
    def post(self, request):
        """ register a new companion app. Must have valid signature"""

        app_bundle = json.loads(request['payload'])
        session_token = request['session']['authtoken']

        # Validate if provided bundle has all the required fields
        self.validate_app_bundle(app_bundle)

        # Validate provided signature
        self.validate_signature(app_bundle)

        # Write bundle to KV Store
        kvstore_payload = self.build_kvstore_payload(app_bundle)
        kvstore_client = KVStoreCollectionAccessObject(collection=self.COMPANION_APPS_COLLECTION_NAME,
                                                       session_key=session_token)
        r, content = kvstore_client.insert_or_update_item_containing_key(kvstore_payload)
        payload = json.loads(content.decode('utf-8')) if r.status == HTTPStatus.OK else content.decode('utf-8')

        return {
            'payload': payload,
            'status': r.status
        }
Esempio 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 register_device(auth_code, user, system_authtoken, temp_key):
    """
    Handler for the final DevicePairingConfirmationRequest call. This function:
        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
    """

    kvstore_temp = KvStore(constants.UNCONFIRMED_DEVICES_COLLECTION_NAME,
                           system_authtoken,
                           owner=user)
    encryption_context = SplunkEncryptionContext(
        system_authtoken, constants.SPACEBRIDGE_APP_NAME)

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

    # Retrieves temporary record from the kvstore
    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': base64.urlsafe_b64encode(device_id_raw)}
    device_public_keys = {'_key': base64.urlsafe_b64encode(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)
    pair_device(auth_code,
                SimpleUserCredentials("dummy", "dummy"),
                device_encryption_info,
                encryption_context,
                server_name=deployment_friendly_name,
                config=config)

    # Creates a new permanent record for the device in the kvstore
    kvstore_user = KvStore(constants.REGISTERED_DEVICES_COLLECTION_NAME,
                           system_authtoken,
                           owner=user)
    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': user})

    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,
    }
Esempio n. 6
0
    def run(self):
        """
        Attempts to sync the migration. If the kvstore is not yet available, schedules
        a non-blocking retry attempt in 5 seconds
        """
        LOGGER.info("Attempting Migration from Splunk Cloud Gateway to Splunk Secure Gateway")
        try:
            meta_collection = KvStore(META_COLLECTION_NAME, self.session_key, owner=NOBODY)
            migration_info = {KEY: MIGRATION_DONE, STATUS: '0'}
            meta_keys = meta_collection.get_collection_keys()
            if MIGRATION_DONE in meta_keys:
                migration_status = meta_collection.get_item_by_key(MIGRATION_DONE)
            else:
                migration_status = '0'
            if migration_status.isdigit() and int(migration_status):
                LOGGER.debug("Migration modular input will not run because migration from Splunk Cloud Gateway "
                             "is already done")
            else:
                # List of all collections
                _, collections_content = get_all_collections(self.session_key, app_name=constants.CLOUDGATEWAY_APP_NAME)
                all_collections = json.loads(collections_content)['entry']
                app_collections = [x for x in all_collections if x['acl']['app'] == CLOUDGATEWAY_APP_NAME]
                app_collection_names = {x['name'] for x in app_collections
                                        if x['name'] not in collections_not_to_migrate}
                # Special case this collection because it doesn't show up in the SCG /collections/config endpoint
                app_collection_names.add("user_meta")

                registered_users_kvstore = KvStore(constants.REGISTERED_USERS_COLLECTION_NAME, self.session_key,
                                                   app=constants.CLOUDGATEWAY_APP_NAME, owner=NOBODY)
                _, users_content = registered_users_kvstore.get_collection_keys()
                registered_user_records = json.loads(users_content)
                all_registered_users = [registered_user_record[u'_key']
                                        for registered_user_record in registered_user_records]

                if NOBODY not in all_registered_users:
                    all_registered_users.append(NOBODY)

                for collection in app_collection_names:
                    # Iterate through all users and insert data per user
                    for user in all_registered_users:
                        cloud_gateway_kvstore = KvStore(collection, self.session_key,
                                                        app=constants.CLOUDGATEWAY_APP_NAME, owner=user)
                        _, scg_content = cloud_gateway_kvstore.get_all_items()
                        scg_content = json.loads(scg_content)
                        if scg_content:
                            if collection == constants.REGISTERED_DEVICES_COLLECTION_NAME:
                                scg_content = [resolve_device_platform_and_type(device) for device in scg_content]
                            secure_gateway_kvstore = KvStore(collection, self.session_key,
                                                             app=constants.SPACEBRIDGE_APP_NAME, owner=user)
                            _, ssg_content = secure_gateway_kvstore.insert_multiple_items(scg_content)

                # Copying passwords.conf to Splunk Secure Gateway
                for key in password_keys:
                    try:
                        value = fetch_sensitive_data(self.session_key, key, app=CLOUDGATEWAY_APP_NAME)
                        update_or_create_sensitive_data(self.session_key, key, value)
                    except splunk.ResourceNotFound:
                        LOGGER.debug('key=%s not found in storage/passwords', key)

                migration_info[STATUS] = '1'
                meta_collection.insert_or_update_item_containing_key(migration_info)

        except splunk.RESTException as e:
            if e.statusCode == HTTPStatus.SERVICE_UNAVAILABLE:
                LOGGER.info("KVStore is not yet setup. Retrying migration in 5 seconds")
                time.sleep(TIMEOUT_SECONDS)
                self.run()
            else:
                raise e
Esempio n. 7
0
def handle_saml_confirmation(auth_code, user, session_token, system_authtoken,
                             body):
    """
    Handler for the final DevicePairingConfirmationRequest call. This function:
        1. Authenticates the supplied user name
        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 user: User provided by rest handler
    :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 user name
    kvstore_temp = KvStore(constants.UNCONFIRMED_DEVICES_COLLECTION_NAME,
                           system_authtoken,
                           owner=user)
    encryption_context = SplunkEncryptionContext(
        system_authtoken, constants.SPACEBRIDGE_APP_NAME)

    LOGGER.info(
        'Received new registration confirmation request by user={}'.format(
            user))

    # 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 = {
        constants.KEY: py23.urlsafe_b64encode_to_str(device_id_raw)
    }
    device_public_keys = {
        constants.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]

    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)

    valid_request = is_valid_session_token(user, session_token)
    if valid_request:
        try:
            credentials = SplunkJWTCredentials(user)
            credentials.load_jwt_token(SplunkAuthHeader(system_authtoken))
            LOGGER.info(
                "Successfully fetched jwt token for SAML auth user with username={}"
                .format(user))
        except Exception as e:
            LOGGER.info(
                "Failed to fetch jwt token for user={} with message={}".format(
                    user, e.message))
            jwt_error_message = 'Registration Error: Failed to fetch jwt token for user={}'.format(
                user)
            return {
                'payload': {
                    'message': jwt_error_message,
                    'app_name': app_name,
                },
                'status': 422,
            }

        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=user)
        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(
            {constants.KEY: user})

        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])
    else:
        LOGGER.info("Error: Mismatched user={} and session token".format(user))
        jwt_error_message = 'Registration Error: Failed to fetch jwt token for user={}'.format(
            user)
        return {
            'payload': {
                'message': jwt_error_message,
                'app_name': app_name,
            },
            'status': 422,
        }

    return {
        'payload': 'Device registration successful',
        'status': 201,
    }