def get_hsps_by_inventory_id(inventory_id, limit, offset): """ return a list of historical system profiles for a given inventory id """ validate_uuids([inventory_id]) account_number = view_helpers.get_account_number(request) query_results = db_interface.get_hsps_by_inventory_id( inventory_id, account_number, limit, offset) valid_profiles = _filter_old_hsps(query_results) if not valid_profiles: raise HTTPError( HTTPStatus.NOT_FOUND, message="no historical profiles found for inventory_id %s" % inventory_id, ) # TODO: request just these three fields from the DB, instead of fetching # the full records, then slicing and sorting profile_metadata = [] for profile in valid_profiles: profile_metadata.append({ "captured_date": profile.captured_date, "id": profile.id, "system_id": profile.inventory_id, }) sorted_profile_metadata = sorted(profile_metadata, key=lambda p: p["captured_date"], reverse=True) result = {"profiles": sorted_profile_metadata} return {"data": [result]}
def _delete_baselines(baseline_ids): """ delete baselines """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id.in_(baseline_ids)) full_results = query.all() message = "read baselines" current_app.logger.audit(message, request=request) if len(full_results) < len(baseline_ids): fetched_ids = {str(result.id) for result in full_results} missing_ids = set(baseline_ids) - fetched_ids message = "ids [%s] not available to delete" % ", ".join(missing_ids) current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.NOT_FOUND, message=message, ) for system_baseline in full_results: db.session.delete(system_baseline) db.session.commit() message = "deleted baselines" current_app.logger.audit(message, request=request)
def get_baselines(limit, offset, order_by, order_how, display_name=None): """ return a list of baselines given their ID """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number) if display_name: query = query.filter( SystemBaseline.display_name.contains(display_name, autoescape=True)) query = _create_ordering(order_by, order_how, query) query = query.limit(limit).offset(offset) query_results = query.all() return _build_paginated_baseline_list_response( len(query_results), limit, offset, order_by, order_how, query_results, withhold_facts=True, )
def get_baselines_by_system_id(system_id=None): account_number = view_helpers.get_account_number(request) if system_id: validate_uuids([system_id]) query = SystemBaselineMappedSystem.query.filter( SystemBaselineMappedSystem.account == account_number, SystemBaselineMappedSystem.system_id == system_id, ) else: query = SystemBaselineMappedSystem.query.filter( SystemBaselineMappedSystem.account == account_number ) try: query_results = query.all() except Exception: message = "Unknown error when reading baselines by system id" current_app.logger.audit(message, request=request, success=False) raise message = "read baselines with system" current_app.logger.audit(message, request=request, success=True) return [result.system_baseline_id for result in query_results]
def get_baselines(limit, offset, order_by, order_how, display_name=None): """ return a list of baselines given their display_name if no display_names given, return a list of all baselines for this account """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number) if display_name: query = query.filter( SystemBaseline.display_name.contains(display_name, autoescape=True)) count = query.count() total_available = _get_total_available_baselines() query = _create_ordering(order_by, order_how, query) query = query.limit(limit).offset(offset) query_results = query.all() json_list = [ baseline.to_json(withhold_facts=True) for baseline in query_results ] return build_paginated_baseline_list_response(limit, offset, order_by, order_how, json_list, total_available, count)
def copy_baseline_by_id(baseline_id, display_name): """ create a new baseline given an existing ID """ _validate_uuids([baseline_id]) # ensure display_name is not null if not display_name: raise HTTPError(HTTPStatus.BAD_REQUEST, message="no value given for display_name") account_number = view_helpers.get_account_number(request) _check_for_existing_display_name(display_name, account_number) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_id) copy_baseline = query.first_or_404() db.session.expunge(copy_baseline) make_transient(copy_baseline) copy_baseline.id = None copy_baseline.created_on = None copy_baseline.modified_on = None copy_baseline.display_name = display_name db.session.add(copy_baseline) db.session.commit() return copy_baseline.to_json()
def _get_total_baseline_count(): """ return a count of total number of baselines available for an account """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number) return query.count()
def _delete_baselines(baseline_ids): """ delete baselines """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id.in_(baseline_ids)) query.delete(synchronize_session="fetch") db.session.commit()
def get_hsps_by_ids(profile_ids): """ return a list of historical system profiles for the given profile IDs """ account_number = view_helpers.get_account_number(request) result = db_interface.get_hsps_by_profile_ids(profile_ids, account_number) filtered_result = _filter_old_hsps(result) result_with_updated_names = _get_current_names_for_profiles(filtered_result) return {"data": [r.to_json() for r in result_with_updated_names]}
def update_baseline(baseline_id, system_baseline_patch): """ update a baseline """ ensure_rbac_write() validate_uuids([baseline_id]) account_number = view_helpers.get_account_number(request) _check_for_whitespace_in_display_name( system_baseline_patch["display_name"]) # this query is a bit different than what's in _check_for_existing_display_name, # since it's OK if the display name is used by the baseline we are updating existing_display_name_query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id != baseline_id, SystemBaseline.display_name == system_baseline_patch["display_name"], ) if existing_display_name_query.count() > 0: raise HTTPError( HTTPStatus.BAD_REQUEST, message="display_name '%s' already used for this account" % system_baseline_patch["display_name"], ) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_id) baseline = query.first_or_404() try: updated_facts = jsonpatch.apply_patch( baseline.baseline_facts, system_baseline_patch["facts_patch"]) _validate_facts(updated_facts) baseline.baseline_facts = updated_facts except FactValidationError as e: raise HTTPError(HTTPStatus.BAD_REQUEST, message=e.message) except (jsonpatch.JsonPatchException, jsonpointer.JsonPointerException): raise HTTPError(HTTPStatus.BAD_REQUEST, message="unable to apply patch to baseline") baseline.display_name = system_baseline_patch["display_name"] baseline.baseline_facts = _sort_baseline_facts(baseline.baseline_facts) db.session.add(baseline) db.session.commit() # pull baseline again so we have the correct updated timestamp and fact count query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_id) return [query.first().to_json()]
def get_baselines_by_ids(baseline_ids, limit, offset, order_by, order_how): """ return a list of baselines given their ID """ validate_uuids(baseline_ids) if len(set(baseline_ids)) < len(baseline_ids): message = "duplicate IDs in request" current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.BAD_REQUEST, message=message) account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id.in_(baseline_ids)) full_results = query.all() message = "read baselines" current_app.logger.audit(message, request=request) if len(full_results) < len(baseline_ids): fetched_ids = {str(result.id) for result in full_results} missing_ids = set(baseline_ids) - fetched_ids message = "ids [%s] not available to display" % ", ".join(missing_ids) current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.NOT_FOUND, message=message, ) count = query.count() message = "counted baselines" current_app.logger.audit(message, request=request) total_available = _get_total_available_baselines() query = _create_ordering(order_by, order_how, query) query = query.limit(limit).offset(offset) query_results = query.all() message = "read baselines" current_app.logger.audit(message, request=request) json_list = [ baseline.to_json(withhold_facts=False) for baseline in query_results ] return build_paginated_baseline_list_response(limit, offset, order_by, order_how, json_list, total_available, count)
def delete_baselines_by_ids(baseline_ids): """ delete a list of baselines given their ID """ _validate_uuids(baseline_ids) account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id.in_(baseline_ids)) query.delete(synchronize_session="fetch") db.session.commit() return "OK"
def _get_total_available_baselines(): """ return a count of total number of baselines available for an account """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number) result = query.count() message = "counted baselines" current_app.logger.audit(message, request=request, success=True) return result
def get_baselines(limit, offset, order_by, order_how, display_name=None): """ return a list of baselines given their display_name if no display_names given, return a list of all baselines for this account """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number) link_args_dict = {} if display_name: link_args_dict["display_name"] = display_name query = query.filter( func.lower(SystemBaseline.display_name).contains( display_name.lower(), autoescape=True)) count = query.count() message = "counted baselines" current_app.logger.audit(message, request=request) total_available = _get_total_available_baselines() message = "counted total available baselines" current_app.logger.audit(message, request=request) query = _create_ordering(order_by, order_how, query) query = query.limit(limit).offset(offset) query_results = query.all() message = "read baselines" current_app.logger.audit(message, request=request) json_list = [ baseline.to_json(withhold_facts=True) for baseline in query_results ] return build_paginated_baseline_list_response( limit, offset, order_by, order_how, json_list, total_available, count, args_dict=link_args_dict, )
def delete_systems_by_ids(system_ids): """ delete a list of systems given their system IDs as a list """ validate_uuids(system_ids) account_number = view_helpers.get_account_number(request) try: SystemBaselineMappedSystem.delete_by_system_ids(system_ids, account_number) except Exception: message = "Unknown error when deleting systems by ids" current_app.logger.audit(message, request=request, success=False) raise message = "delete systems by ids" current_app.logger.audit(message, request=request, success=True) return "OK"
def update_baseline(baseline_ids, system_baseline_partial): """ update a baseline """ _validate_uuids(baseline_ids) if len(baseline_ids) > 1: raise "can only patch one baseline at a time" account_number = view_helpers.get_account_number(request) # check if we are going to conflict with an existing record's name if "display_name" in system_baseline_partial: display_name_query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.display_name == system_baseline_partial["display_name"], ) existing_display_name = display_name_query.first() if existing_display_name and existing_display_name.id is not baseline_ids[ 0]: raise HTTPError( HTTPStatus.BAD_REQUEST, message="display_name %s is in use by another record" % system_baseline_partial["display_name"], ) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_ids[0]) existing_baseline = query.first_or_404() new_baseline = existing_baseline if "baseline_facts" in system_baseline_partial: new_baseline = _merge_baselines(existing_baseline, system_baseline_partial) if "display_name" in system_baseline_partial: new_baseline.display_name = system_baseline_partial["display_name"] db.session.add(new_baseline) db.session.commit() # pull baseline again so we have the correct updated timestamp and fact count query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_ids[0]) return [query.first().to_json()]
def get_baselines(limit, offset): """ return a list of baselines given their ID """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number) total_count = query.count() query = query.order_by(SystemBaseline.created_on, SystemBaseline.id) query = query.limit(limit).offset(offset) query_results = query.all() return _build_paginated_baseline_list_response(total_count, limit, offset, query_results, withhold_facts=True)
def get_hsps_by_ids(profile_ids): """ return a list of historical system profiles for the given profile IDs """ validate_uuids(profile_ids) _check_for_duplicates(profile_ids) account_number = view_helpers.get_account_number(request) result = db_interface.get_hsps_by_profile_ids(profile_ids, account_number) # TODO: rely on captured_date and filter in SQL above filtered_result = _filter_old_hsps(result) _check_for_missing_ids(profile_ids, filtered_result) result_with_updated_names = _get_current_names_for_profiles( filtered_result) return {"data": [r.to_json() for r in result_with_updated_names]}
def _delete_baselines(baseline_ids): """ delete baselines """ account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id.in_(baseline_ids)) full_results = query.all() if len(full_results) < len(baseline_ids): fetched_ids = {str(result.id) for result in full_results} missing_ids = set(baseline_ids) - fetched_ids raise HTTPError( HTTPStatus.NOT_FOUND, message="ids [%s] not available to delete" % ", ".join(missing_ids), ) query.delete(synchronize_session="fetch") db.session.commit()
def copy_baseline_by_id(baseline_id, display_name): """ create a new baseline given an existing ID """ ensure_rbac_write() validate_uuids([baseline_id]) # ensure display_name is not null if not display_name: message = "no value given for display_name" current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.BAD_REQUEST, message=message) account_number = view_helpers.get_account_number(request) _check_for_existing_display_name(display_name, account_number) _check_for_whitespace_in_display_name(display_name) message = "counted baselines" current_app.logger.audit(message, request=request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_id) copy_baseline = query.first_or_404() db.session.expunge(copy_baseline) make_transient(copy_baseline) copy_baseline.id = None copy_baseline.created_on = None copy_baseline.modified_on = None copy_baseline.display_name = display_name db.session.add(copy_baseline) db.session.commit() message = "created baselines" current_app.logger.audit(message, request=request) return copy_baseline.to_json()
def create_systems_with_baseline(baseline_id, body): ensure_rbac_write() validate_uuids([baseline_id]) system_ids = body["system_ids"] validate_uuids(system_ids) if len(set(system_ids)) < len(system_ids): message = "duplicate IDs in request" current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.BAD_REQUEST, message=message) account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_id) baseline = query.first_or_404() message = "read baseline" current_app.logger.audit(message, request=request, success=True) try: for system_id in system_ids: baseline.add_mapped_system(system_id) db.session.commit() except ValueError as error: message = str(error) current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.BAD_REQUEST, message=message) except Exception: message = "Unknown error when creating systems with baseline" current_app.logger.audit(message, request=request, success=False) raise message = "created systems with baseline" current_app.logger.audit(message, request=request, success=True) system_ids = baseline.mapped_system_ids() return {"system_ids": system_ids}
def get_baselines_by_ids(baseline_ids, limit, order_by, order_how, offset): """ return a list of baselines given their ID """ _validate_uuids(baseline_ids) account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id.in_(baseline_ids)) query = _create_ordering(order_by, order_how, query) query = query.limit(limit).offset(offset) query_results = query.all() return _build_paginated_baseline_list_response( len(query_results), limit, offset, order_by, order_how, query_results, withhold_facts=False, )
def get_hsps_by_inventory_id(inventory_id): """ return a list of historical system profiles for a given inventory id """ account_number = view_helpers.get_account_number(request) query_results = db_interface.get_hsps_by_inventory_id(inventory_id, account_number) valid_profiles = _filter_old_hsps(query_results) profile_metadata = [] for profile in valid_profiles: profile_metadata.append( { "captured_date": profile.captured_date, "id": profile.id, "system_id": profile.inventory_id, } ) sorted_profile_metadata = sorted( profile_metadata, key=lambda p: p["captured_date"], reverse=True ) result = {"profiles": sorted_profile_metadata} return {"data": [result]}
def list_systems_with_baseline(baseline_id): validate_uuids([baseline_id]) account_number = view_helpers.get_account_number(request) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.id == baseline_id) baseline = query.first_or_404() message = "read baseline" current_app.logger.audit(message, request=request, success=True) try: system_ids = baseline.mapped_system_ids() except ValueError as error: message = str(error) current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.BAD_REQUEST, message=message) except Exception: message = "Unknown error when reading mapped system ids" current_app.logger.audit(message, request=request, success=False) raise return {"system_ids": system_ids}
def create_baseline(system_baseline_in): """ create a baseline """ ensure_rbac_write() account_number = view_helpers.get_account_number(request) if "values" in system_baseline_in and "value" in system_baseline_in: message = "'values' and 'value' cannot both be defined for system baseline" current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.BAD_REQUEST, message=message, ) _check_for_existing_display_name(system_baseline_in["display_name"], account_number) _check_for_whitespace_in_display_name(system_baseline_in["display_name"]) message = "counted baselines" current_app.logger.audit(message, request=request) baseline_facts = [] if "baseline_facts" in system_baseline_in: if "inventory_uuid" in system_baseline_in: message = ( "Both baseline facts and inventory id provided, can clone only one." ) current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.BAD_REQUEST, message=message, ) if "hsp_uuid" in system_baseline_in: message = "Both baseline facts and hsp id provided, can clone only one." current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.BAD_REQUEST, message=message, ) baseline_facts = system_baseline_in["baseline_facts"] elif "hsp_uuid" in system_baseline_in: if "inventory_uuid" in system_baseline_in: message = "Both hsp id and system id provided, can clone only one." current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.BAD_REQUEST, message=message, ) validate_uuids([system_baseline_in["hsp_uuid"]]) auth_key = get_key_from_headers(request.headers) try: hsp = fetch_historical_sys_profiles( [system_baseline_in["hsp_uuid"]], auth_key, current_app.logger, get_event_counters(), )[0] message = "read historical system profiles" current_app.logger.audit(message, request=request) except ItemNotReturned: message = "hsp UUID %s not available" % system_baseline_in[ "hsp_uuid"] current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.NOT_FOUND, message=message, ) except RBACDenied as error: message = error.message current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.FORBIDDEN, message=message) system_name = "clone_from_hsp_unused" baseline_facts = _parse_from_sysprofile(hsp["system_profile"], system_name, current_app.logger) elif "inventory_uuid" in system_baseline_in: validate_uuids([system_baseline_in["inventory_uuid"]]) auth_key = get_key_from_headers(request.headers) try: system_with_profile = fetch_systems_with_profiles( [system_baseline_in["inventory_uuid"]], auth_key, current_app.logger, get_event_counters(), )[0] message = "read system with profiles" current_app.logger.audit(message, request=request) except ItemNotReturned: message = ("inventory UUID %s not available" % system_baseline_in["inventory_uuid"]) current_app.logger.audit(message, request=request, success=False) raise HTTPError( HTTPStatus.NOT_FOUND, message=message, ) except RBACDenied as error: message = error.message current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.FORBIDDEN, message=message) system_name = profile_parser.get_name(system_with_profile) baseline_facts = _parse_from_sysprofile( system_with_profile["system_profile"], system_name, current_app.logger) try: _validate_facts(baseline_facts) except FactValidationError as error: message = error.message current_app.logger.audit(message, request=request, success=False) raise HTTPError(HTTPStatus.BAD_REQUEST, message=message) baseline = SystemBaseline( account=account_number, display_name=system_baseline_in["display_name"], baseline_facts=baseline_facts, ) baseline.baseline_facts = _sort_baseline_facts(baseline.baseline_facts) db.session.add(baseline) db.session.commit( ) # commit now so we get a created/updated time before json conversion message = "creat baselines" current_app.logger.audit(message, request=request) return baseline.to_json()
def create_baseline(system_baseline_in): """ create a baseline """ account_number = view_helpers.get_account_number(request) if "values" in system_baseline_in and "value" in system_baseline_in: raise HTTPError( HTTPStatus.BAD_REQUEST, message= "'values' and 'value' cannot both be defined for system baseline", ) _check_for_existing_display_name(system_baseline_in["display_name"], account_number) baseline_facts = [] if "baseline_facts" in system_baseline_in: baseline_facts = system_baseline_in["baseline_facts"] elif "inventory_uuid" in system_baseline_in: _validate_uuids([system_baseline_in["inventory_uuid"]]) auth_key = get_key_from_headers(request.headers) try: system_with_profile = fetch_systems_with_profiles( [system_baseline_in["inventory_uuid"]], auth_key, current_app.logger, get_event_counters(), )[0] except ItemNotReturned: raise HTTPError( HTTPStatus.BAD_REQUEST, message="inventory UUID %s not available" % system_baseline_in["inventory_uuid"], ) system_name = profile_parser.get_name(system_with_profile) parsed_profile = profile_parser.parse_profile( system_with_profile["system_profile"], system_name, current_app.logger) facts = [] for fact in parsed_profile: if fact not in ["id", "name"] and parsed_profile[fact] not in [ "N/A", "None", None, ]: facts.append({"name": fact, "value": parsed_profile[fact]}) baseline_facts = group_baselines(facts) try: _validate_facts(baseline_facts) except FactValidationError as e: raise HTTPError(HTTPStatus.BAD_REQUEST, message=e.message) baseline = SystemBaseline( account=account_number, display_name=system_baseline_in["display_name"], baseline_facts=baseline_facts, ) baseline.baseline_facts = _sort_baseline_facts(baseline.baseline_facts) db.session.add(baseline) db.session.commit( ) # commit now so we get a created/updated time before json conversion return baseline.to_json()
def create_baseline(system_baseline_in): """ create a baseline """ account_number = view_helpers.get_account_number(request) if "values" in system_baseline_in and "value" in system_baseline_in: raise HTTPError( HTTPStatus.BAD_REQUEST, message= "'values' and 'value' cannot both be defined for system baseline", ) query = SystemBaseline.query.filter( SystemBaseline.account == account_number, SystemBaseline.display_name == system_baseline_in["display_name"], ) if query.count() > 0: raise HTTPError( HTTPStatus.BAD_REQUEST, message="display_name '%s' already used for this account" % system_baseline_in["display_name"], ) baseline_facts = [] if "baseline_facts" in system_baseline_in: baseline_facts = system_baseline_in["baseline_facts"] elif "inventory_uuid" in system_baseline_in: auth_key = get_key_from_headers(request.headers) system_with_profile = fetch_systems_with_profiles( [system_baseline_in["inventory_uuid"]], auth_key, current_app.logger, get_event_counters(), )[0] system_name = profile_parser.get_name(system_with_profile) parsed_profile = profile_parser.parse_profile( system_with_profile["system_profile"], system_name, current_app.logger) facts = [] for fact in parsed_profile: if fact not in ["id", "name"] and parsed_profile[fact] not in [ "N/A", "None", None, ]: facts.append({"name": fact, "value": parsed_profile[fact]}) baseline_facts = group_baselines(facts) baseline = SystemBaseline( account=account_number, display_name=system_baseline_in["display_name"], baseline_facts=baseline_facts, ) db.session.add(baseline) db.session.commit( ) # commit now so we get a created/updated time before json conversion return baseline.to_json()