import datetime import logging import pandas as pd from flows.prepPolicy import selectPolicies from services.API import AirlockAPIWrapper from services.policyhandler import getPolicyInfo from utils.selector import Selector from utils.utils import colorText, load_env logger = logging.getLogger(__name__) async def findQuietAgents(api: AirlockAPIWrapper): working_dir = load_env("WORKING_DIR") selected_policy = await selectPolicies(api, False) if selected_policy: agents = await api.agents_find_by_group(selected_policy[0].groupid) history_days = await Selector.select_value( prompt="Enter how many days of history to pull (1–150): ", value_type=int, valid_range=(1, 150), ) required_quiet = await Selector.select_value( prompt="Enter how many days without an untrusted execution before these are considered ready for enforcement? (1–150): ", value_type=int, valid_range=(1, 150), ) policy_exec_history = await getPolicyInfo( api, selected_policy[0], [1, 2, 6, 7], history_days ) if policy_exec_history.empty: logging.info("No execution history found for the selected policy and time range.") return policy_exec_history["datetime"] = pd.to_datetime( policy_exec_history["datetime"], format="%Y-%m-%dT%H:%M:%SZ", utc=True ) now = datetime.datetime.now(datetime.timezone.utc) policy_exec_history["days_ago"] = policy_exec_history["datetime"].apply( lambda dt: (now - dt).days ) hostname_counts = policy_exec_history["hostname"].value_counts() agents["execution_count"] = agents["hostname"].map(hostname_counts).fillna(0).astype(int) most_recent_exec = policy_exec_history.sort_values(by="days_ago").drop_duplicates( subset="hostname", keep="first" ) agents["days_since"] = agents["hostname"].map( most_recent_exec.set_index("hostname")["days_ago"] ) agents["required_quiet"] = required_quiet agents["enforce_ready"] = agents["days_since"].apply( lambda x: True if pd.isna(x) or x > required_quiet else False ) agents = agents.sort_values(by=["execution_count", "hostname"], ascending=[True, True]) filename = f"{working_dir}\\{selected_policy[0].name}_agents_last_{history_days}_days.csv" logging.debug(f"Saving CSV to {filename}") print(colorText(f"Saving CSV to {filename}", "green")) agents.to_csv(filename, index=False) total_agents = len(agents) ready_agents = agents["enforce_ready"].sum() not_ready_agents = total_agents - ready_agents ready_percentage = (ready_agents / total_agents) * 100 message = ( f"Total agents: {total_agents}\n" f"Agents marked as 'enforce_ready': {ready_agents}\n" f"Agents not ready: {not_ready_agents}\n" f"Percentage ready for enforcement: {ready_percentage:.2f}%" ) logger.info(message) colorText(message, "green")