def update_facts_by_namespace(operation, host_id_list, namespace, fact_dict): current_identity = get_current_identity() query = Host.query.filter( (Host.account == current_identity.account_number) & Host.id.in_(host_id_list) & Host.facts.has_key( namespace) # noqa: W601 JSONB query filter, not a dict ) hosts_to_update = find_non_culled_hosts( update_query_for_owner_id(current_identity, query)).all() logger.debug("hosts_to_update:%s", hosts_to_update) if len(hosts_to_update) != len(host_id_list): error_msg = ( "ERROR: The number of hosts requested does not match the number of hosts found in the host database. " "This could happen if the namespace does not exist or the account number associated with the call does " "not match the account number associated with one or more the hosts. Rejecting the fact change request." ) logger.debug(error_msg) return error_msg, 400 for host in hosts_to_update: if operation is FactOperations.replace: host.replace_facts_in_namespace(namespace, fact_dict) else: host.merge_facts_in_namespace(namespace, fact_dict) db.session.commit() logger.debug("hosts_to_update:%s", hosts_to_update) return 200
def _find_hosts_by_hostname_or_id(hostname): current_identity = get_current_identity() logger.debug("_find_hosts_by_hostname_or_id(%s)", hostname) filter_list = [ Host.display_name.comparator.contains(hostname), Host.canonical_facts["fqdn"].astext.contains(hostname.casefold()), ] try: UUID(hostname) host_id = hostname filter_list.append(Host.id == host_id) logger.debug("Adding id (uuid) to the filter list") except Exception: # Do not filter using the id logger.debug("The hostname (%s) could not be converted into a UUID", hostname, exc_info=True) return Host.query.filter( and_(*[ Host.account == current_identity.account_number, or_(*filter_list) ]))
def delete_by_id(host_id_list): current_identity = get_current_identity() payload_tracker = get_payload_tracker( account=current_identity.account_number, request_id=threadctx.request_id) with PayloadTrackerContext(payload_tracker, received_status_message="delete operation", current_operation="delete"): query = _get_host_list_by_id_list(host_id_list) if not query.count(): flask.abort(status.HTTP_404_NOT_FOUND) for host_id, deleted in delete_hosts( query, current_app.event_producer, inventory_config().host_delete_chunk_size): if deleted: log_host_delete_succeeded(logger, host_id, get_control_rule()) tracker_message = "deleted host" else: log_host_delete_failed(logger, host_id) tracker_message = "not deleted host" with PayloadTrackerProcessingContext( payload_tracker, processing_status_message=tracker_message ) as payload_tracker_processing_ctx: payload_tracker_processing_ctx.inventory_id = host_id return flask.Response(None, status.HTTP_200_OK)
def get_host_list( display_name, fqdn, hostname_or_id, insights_id, provider_id, provider_type, tags, page, per_page, param_order_by, param_order_how, staleness, registered_with, filter, fields, ): limit, offset = pagination_params(page, per_page) xjoin_order_by, xjoin_order_how = params_to_order(param_order_by, param_order_how) all_filters = query_filters( fqdn, display_name, hostname_or_id, insights_id, provider_id, provider_type, tags, staleness, registered_with, filter, ) current_identity = get_current_identity() if current_identity.identity_type == IdentityType.SYSTEM and current_identity.auth_type != AuthType.CLASSIC: all_filters += owner_id_filter() additional_fields = tuple() system_profile_fields = [] if fields.get("system_profile"): additional_fields = ("system_profile", ) system_profile_fields = list(fields.get("system_profile").keys()) variables = { "limit": limit, "offset": offset, "order_by": xjoin_order_by, "order_how": xjoin_order_how, "filter": all_filters, "fields": system_profile_fields, } response = graphql_query(QUERY, variables, log_get_host_list_failed)["hosts"] total = response["meta"]["total"] check_pagination(offset, total) return map(deserialize_host, response["data"]), total, additional_fields
def _find_hosts_by_display_name(display_name): current_identity = get_current_identity() logger.debug("find_hosts_by_display_name(%s)", display_name) return Host.query.filter( and_(Host.account == current_identity.account_number, Host.display_name.comparator.contains(display_name)))
def validate_schema(repo_fork="RedHatInsights", repo_branch="master", days=1, max_messages=10000): # Use the identity header to make sure the user is someone from our team. config = Config(RuntimeEnvironment.SERVICE) identity = get_current_identity() if not hasattr(identity, "user") or identity.user.get("username") not in config.sp_authorized_users: flask.abort(403, "This endpoint is restricted to HBI Admins.") consumer = KafkaConsumer( bootstrap_servers=config.bootstrap_servers, api_version=(0, 10, 1), value_deserializer=lambda m: m.decode(), **config.validator_kafka_consumer, ) try: response = validate_sp_for_branch( consumer, {config.host_ingress_topic, config.additional_validation_topic}, repo_fork, repo_branch, days, max_messages, ) consumer.close() return flask_json_response(response) except (ValueError, AttributeError) as e: consumer.close() flask.abort(400, str(e))
def modified_func(*args, **kwargs): if not inventory_config().rbac_enforced: return func(*args, **kwargs) if get_current_identity().identity_type != CHECKED_TYPE: return func(*args, **kwargs) # track that RBAC is being used to control access g.access_control_rule = "RBAC" logger.debug("access_control_rule set") rbac_data = get_rbac_permissions() permission_type = required_permission.value.split(":")[2] for rbac_permission in rbac_data: if (rbac_permission["permission"] == Permission.ADMIN.value # inventory:*:* or rbac_permission["permission"] == Permission.HOSTS_ALL.value # inventory:hosts:* or rbac_permission["permission"] == f"inventory:*:{permission_type}" # inventory:*:(read | write) or rbac_permission["permission"] == required_permission .value # inventory:hosts:(read | write) ): return func(*args, **kwargs) rbac_permission_denied(logger, required_permission.value, rbac_data) abort(status.HTTP_403_FORBIDDEN)
def get_sap_system(tags=None, page=None, per_page=None, staleness=None, registered_with=None, filter=None): if not xjoin_enabled(): logger.error("xjoin-search not enabled") flask.abort(503) limit, offset = pagination_params(page, per_page) variables = { "hostFilter": { # we're not indexing null timestamps in ES "OR": list(staleness_filter(staleness)) }, "limit": limit, "offset": offset, } hostfilter_and_variables = () if tags: hostfilter_and_variables = build_tag_query_dict_tuple(tags) if registered_with: hostfilter_and_variables += build_registered_with_filter( registered_with) if filter: for key in filter: if key == "system_profile": hostfilter_and_variables += build_system_profile_filter( filter["system_profile"]) else: raise ValidationException("filter key is invalid") current_identity = get_current_identity() if current_identity.identity_type == IdentityType.SYSTEM: hostfilter_and_variables += owner_id_filter() if hostfilter_and_variables != (): variables["hostFilter"]["AND"] = hostfilter_and_variables response = graphql_query(SAP_SYSTEM_QUERY, variables, log_get_sap_system_failed) data = response["hostSystemProfile"] check_pagination(offset, data["sap_system"]["meta"]["total"]) log_get_sap_system_succeeded(logger, data) return flask_json_response( build_collection_response(data["sap_system"]["data"], page, per_page, data["sap_system"]["meta"]["total"]))
def get_sap_sids(search=None, tags=None, page=None, per_page=None, staleness=None, registered_with=None, filter=None): if not xjoin_enabled(): logger.error("xjoin-search not enabled") flask.abort(503) limit, offset = pagination_params(page, per_page) variables = { "hostFilter": { # we're not indexing null timestamps in ES "OR": list(staleness_filter(staleness)) }, "limit": limit, "offset": offset, } hostfilter_and_variables = () if tags: hostfilter_and_variables = build_tag_query_dict_tuple(tags) if registered_with: variables["hostFilter"]["NOT"] = {"insights_id": {"eq": None}} if search: variables["filter"] = { # Escaped so that the string literals are not interpreted as regex "search": {"regex": f".*{custom_escape(search)}.*"} } if filter: for key in filter: if key == "system_profile": hostfilter_and_variables += build_system_profile_filter(filter["system_profile"]) else: raise ValidationException("filter key is invalid") current_identity = get_current_identity() if current_identity.identity_type == IdentityType.SYSTEM and current_identity.auth_type != AuthType.CLASSIC: hostfilter_and_variables += owner_id_filter() if hostfilter_and_variables != (): variables["hostFilter"]["AND"] = hostfilter_and_variables response = graphql_query(SAP_SIDS_QUERY, variables, log_get_sap_sids_failed) data = response["hostSystemProfile"] check_pagination(offset, data["sap_sids"]["meta"]["total"]) log_get_sap_sids_succeeded(logger, data) return flask_json_response( build_collection_response(data["sap_sids"]["data"], page, per_page, data["sap_sids"]["meta"]["total"]) )
def get_operating_system( tags=None, page: Optional[int] = None, per_page: Optional[int] = None, staleness: Optional[str] = None, registered_with: Optional[str] = None, filter=None, ): limit, offset = pagination_params(page, per_page) variables = { "hostFilter": { # we're not indexing null timestamps in ES "OR": list(staleness_filter(staleness)) }, "limit": limit, "offset": offset, } hostfilter_and_variables = () if tags: hostfilter_and_variables = build_tag_query_dict_tuple(tags) if registered_with: variables["hostFilter"]["NOT"] = {"insights_id": {"eq": None}} if filter: for key in filter: if key == "system_profile": hostfilter_and_variables += build_system_profile_filter( filter["system_profile"]) else: raise ValidationException("filter key is invalid") current_identity = get_current_identity() if current_identity.identity_type == IdentityType.SYSTEM: hostfilter_and_variables += owner_id_filter() if hostfilter_and_variables != (): variables["hostFilter"]["AND"] = hostfilter_and_variables response = graphql_query(OPERATING_SYSTEM_QUERY, variables, log_get_operating_system_failed) data = response["hostSystemProfile"] check_pagination(offset, data["operating_system"]["meta"]["total"]) log_get_operating_system_succeeded(logger, data) return flask_json_response( build_collection_response(data["operating_system"]["data"], page, per_page, data["operating_system"]["meta"]["total"]))
def _add_host(input_host): current_identity = get_current_identity() if not current_identity.is_trusted_system and current_identity.account_number != input_host.account: raise InventoryException( title="Invalid request", detail= "The account number associated with the user does not match the account number associated with the " "host", ) return add_host(input_host, staleness_timestamps(), update_system_profile=False)
def host_checkin(body): current_identity = get_current_identity() canonical_facts = deserialize_canonical_facts(body) existing_host = find_existing_host(current_identity, canonical_facts) if existing_host: existing_host._update_modified_date() db.session.commit() serialized_host = serialize_host(existing_host, staleness_timestamps(), EGRESS_HOST_FIELDS) _emit_patch_event(serialized_host, existing_host.id, existing_host.canonical_facts.get("insights_id")) return flask_json_response(serialized_host, 201) else: flask.abort(404, "No hosts match the provided canonical facts.")
def get_host_ids_list( display_name, fqdn, hostname_or_id, insights_id, provider_id, provider_type, registered_with, staleness, tags, filter, ): all_filters = query_filters( fqdn, display_name, hostname_or_id, insights_id, provider_id, provider_type, tags, staleness, registered_with, filter, ) current_identity = get_current_identity() if current_identity.identity_type == IdentityType.SYSTEM and current_identity.auth_type != AuthType.CLASSIC: all_filters += owner_id_filter() variables = { "limit": 100, "filter": all_filters } # maximum limit handled by xjoin. response = graphql_query(HOST_IDS_QUERY, variables, log_get_host_list_failed)["hosts"] return [x["id"] for x in response["data"]]
def _find_hosts_by_canonical_fact(canonical_fact, value): return single_canonical_fact_host_query(get_current_identity(), canonical_fact, value)
def _find_all_hosts(): identity = get_current_identity() query = Host.query.filter(Host.account == identity.account_number) return update_query_for_owner_id(identity, query)
def get_tags( search=None, tags=None, display_name=None, fqdn=None, hostname_or_id=None, insights_id=None, provider_id=None, provider_type=None, order_by=None, order_how=None, page=None, per_page=None, staleness=None, registered_with=None, filter=None, ): if not xjoin_enabled(): logger.error("xjoin-search not enabled") flask.abort(503) limit, offset = pagination_params(page, per_page) variables = { "order_by": order_by, "order_how": order_how, "limit": limit, "offset": offset, "hostFilter": { # we're not indexing null timestamps in ES "OR": list(staleness_filter(staleness)) }, } hostfilter_and_variables = query_filters( fqdn, display_name, hostname_or_id, insights_id, provider_id, provider_type, tags, None, registered_with, filter, ) if search: variables["filter"] = { # Escaped so that the string literals are not interpreted as regex "search": { "regex": f".*{custom_escape(search)}.*" } } current_identity = get_current_identity() if current_identity.identity_type == IdentityType.SYSTEM: hostfilter_and_variables += owner_id_filter() if hostfilter_and_variables != (): variables["hostFilter"]["AND"] = hostfilter_and_variables response = graphql_query(TAGS_QUERY, variables, log_get_tags_failed) data = response["hostTags"] check_pagination(offset, data["meta"]["total"]) log_get_tags_succeeded(logger, data) return flask_json_response( build_collection_response(data["data"], page, per_page, data["meta"]["total"]))
def owner_id_filter(): return ({"spf_owner_id": {"eq": get_current_identity().system["cn"]}}, )
def _get_host_list_by_id_list(host_id_list): current_identity = get_current_identity() query = Host.query.filter((Host.account == current_identity.account_number) & Host.id.in_(host_id_list)) return find_non_culled_hosts( update_query_for_owner_id(current_identity, query))