def _system_mapping(system): """ create a header mapping for one system """ system_profile_exists = system["system_profile"]["system_profile_exists"] system_stale = _check_system_stale(system) insights_installed = False insights_enabled = False captured_or_updated = system.get("updated", None) if system_profile_exists: if "captured_date" in system["system_profile"]: captured_or_updated = system["system_profile"]["captured_date"] if "installed_packages" in system["system_profile"]: try: insights_installed_string = next( s for s in system["system_profile"]["installed_packages"] if "insights-client" in s) except StopIteration: insights_installed_string = "" insights_installed = "insights-client" in insights_installed_string if "enabled_services" in system["system_profile"]: insights_enabled = "insights-client" in system["system_profile"][ "enabled_services"] return { "id": system[SYSTEM_ID_KEY], "display_name": profile_parser.get_name(system), "system_profile_exists": system_profile_exists, "last_updated": captured_or_updated, "insights_installed": insights_installed, "insights_enabled": insights_enabled, "system_stale": system_stale, }
def _select_applicable_info(systems_with_profiles, baselines, historical_sys_profiles, reference_id): """ Take a list of systems with profiles, and output a "pivoted" list of profile facts, where each fact key has a dict of systems and their values. This is useful when comparing facts across systems. """ # create dicts of id + info parsed_system_profiles = [] for system_with_profile in systems_with_profiles: system_name = profile_parser.get_name(system_with_profile) parsed_system_profile = profile_parser.parse_profile( system_with_profile["system_profile"], system_name, current_app.logger) parsed_system_profiles.append({ **parsed_system_profile, "is_baseline": False }) for historical_sys_profile in historical_sys_profiles: historical_sys_profile_name = historical_sys_profile["display_name"] parsed_historical_sys_profile = profile_parser.parse_profile( historical_sys_profile["system_profile"], historical_sys_profile_name, current_app.logger, ) parsed_system_profiles.append({ **parsed_historical_sys_profile, "is_baseline": False }) # add baselines into parsed_system_profiles for baseline in baselines: baseline_facts = { "id": baseline["id"], "name": baseline["display_name"] } for baseline_fact in baseline["baseline_facts"]: if "value" in baseline_fact: baseline_facts[baseline_fact["name"]] = baseline_fact["value"] elif "values" in baseline_fact: prefix = baseline_fact["name"] for nested_fact in baseline_fact["values"]: baseline_facts[prefix + "." + nested_fact["name"]] = nested_fact["value"] parsed_system_profiles.append({**baseline_facts, "is_baseline": True}) # find the set of all keys to iterate over all_keys = set() for parsed_system_profile in parsed_system_profiles: all_keys = all_keys.union(set(parsed_system_profile.keys())) info_comparisons = [ _create_comparison(parsed_system_profiles, key, reference_id) for key in all_keys ] return info_comparisons
def _system_mapping(system): """ create a header mapping for one system """ system_profile_exists = system["system_profile"]["system_profile_exists"] captured_or_updated = system.get("updated", None) if system_profile_exists: if "captured_date" in system["system_profile"]: captured_or_updated = system["system_profile"]["captured_date"] return { "id": system[SYSTEM_ID_KEY], "display_name": profile_parser.get_name(system), "system_profile_exists": system_profile_exists, "last_updated": captured_or_updated, }
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 _select_applicable_info( systems_with_profiles, baselines, historical_sys_profiles, reference_id, short_circuit, ): """ Take a list of systems with profiles, and output a "pivoted" list of profile facts, where each fact key has a dict of systems and their values. This is useful when comparing facts across systems. Unless short_circuit is True, then we don't need a full comparison report, only one for facts present on a single baseline that is being compared with a single system for notifications if a newly checked in hsp system has drifted from an associated baseline. If the key 'drifted_from_baseline' is True, the system has drifted, else False. """ # create dicts of id + info parsed_system_profiles = [] for system_with_profile in systems_with_profiles: system_name = profile_parser.get_name(system_with_profile) parsed_system_profile = profile_parser.parse_profile( system_with_profile["system_profile"], system_name, current_app.logger ) parsed_system_profiles.append({**parsed_system_profile, "is_baseline": False}) for historical_sys_profile in historical_sys_profiles: historical_sys_profile_name = historical_sys_profile["display_name"] parsed_historical_sys_profile = profile_parser.parse_profile( historical_sys_profile["system_profile"], historical_sys_profile_name, current_app.logger, ) parsed_system_profiles.append({**parsed_historical_sys_profile, "is_baseline": False}) # add baselines into parsed_system_profiles for baseline in baselines: baseline_facts = {"id": baseline["id"], "name": baseline["display_name"]} for baseline_fact in baseline["baseline_facts"]: if "value" in baseline_fact: baseline_facts[baseline_fact["name"]] = baseline_fact["value"] elif "values" in baseline_fact: prefix = baseline_fact["name"] for nested_fact in baseline_fact["values"]: baseline_facts[prefix + "." + nested_fact["name"]] = nested_fact["value"] parsed_system_profiles.append({**baseline_facts, "is_baseline": True}) # find the set of all keys to iterate over # if short_circuit is True, we only want the facts present in this baseline # since we are comparing one baseline to one system for notifications only all_keys = set() if short_circuit: for parsed_system_profile in parsed_system_profiles: if parsed_system_profile["is_baseline"]: all_keys = set(parsed_system_profile.keys()) else: for parsed_system_profile in parsed_system_profiles: all_keys = all_keys.union(set(parsed_system_profile.keys())) # prepare regexes for obfuscated values matching obfuscated_regexes = {} for key in OBFUSCATED_FACTS_PATTERNS.keys(): obfuscated_regexes[key] = re.compile(OBFUSCATED_FACTS_PATTERNS[key]) info_comparisons = [] for key in all_keys: # obfuscated information type - key for obfuscated_key in obfuscated_regexes.keys(): if obfuscated_key in key: for system in parsed_system_profiles: system["obfuscation"] = {} system["obfuscation"][key] = False obfuscated_regex = obfuscated_regexes[obfuscated_key] value = system.get(key) # only if value is present and matches with obfuscated pattern if value and obfuscated_regex.match(value): system["obfuscation"][key] = True current_comparison = _create_comparison( parsed_system_profiles, key, reference_id, len(systems_with_profiles), short_circuit, ) if current_comparison: # if short_circuit is True, and there was a change, i.e. this system # has drifted from this associated baseline, then set the key on the # comparison 'drifted_from_baseline' to True to trigger a notification # else set it to False. if short_circuit and current_comparison["state"] == COMPARISON_DIFFERENT: current_comparison["drifted_from_baseline"] = True else: current_comparison["drifted_from_baseline"] = False info_comparisons.append(current_comparison) return info_comparisons
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()
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()