Source code for csle_common.dao.emulation_config.emulation_trace

from typing import Optional, List, Dict, Any, Tuple, Union
import json
import os
from csle_common.logging.log import Logger
import csle_common.constants.constants as constants
import csle_collector.constants.constants as collector_constants
from csle_common.dao.emulation_action.attacker.emulation_attacker_action import EmulationAttackerAction
from csle_common.dao.emulation_action.attacker.emulation_attacker_action_id import EmulationAttackerActionId
from csle_common.dao.emulation_action.defender.emulation_defender_action import EmulationDefenderAction
from csle_common.dao.encoding.np_encoder import NpEncoder
from csle_common.dao.emulation_observation.attacker.emulation_attacker_observation_state \
    import EmulationAttackerObservationState
from csle_common.dao.emulation_observation.defender.emulation_defender_observation_state \
    import EmulationDefenderObservationState
from csle_base.json_serializable import JSONSerializable


[docs]class EmulationTrace(JSONSerializable): """ DTO class representing a trace in the emulation system """ def __init__(self, initial_attacker_observation_state: EmulationAttackerObservationState, initial_defender_observation_state: EmulationDefenderObservationState, emulation_name: str): """ Initializes the DTO :param initial_attacker_observation_state: the initial state of the attacker :param initial_defender_observation_state: the intial state of the defender :param emulation_name: the name of the emulation """ self.initial_attacker_observation_state = initial_attacker_observation_state self.initial_defender_observation_state = initial_defender_observation_state self.attacker_observation_states: List[EmulationAttackerObservationState] = [] self.defender_observation_states: List[EmulationDefenderObservationState] = [] self.attacker_actions: List[EmulationAttackerAction] = [] self.defender_actions: List[EmulationDefenderAction] = [] self.emulation_name = emulation_name self.id = -1 def __str__(self): """ :return: a string representation of the object """ return f"initial_attacker_observation_state:{self.initial_attacker_observation_state}" \ f"initial_defender_observation_state:{self.initial_defender_observation_state}" \ f"attacker_observation_states:{self.attacker_observation_states}\n" \ f"defender_observation_states:{self.defender_observation_states}\n" \ f"attacker_actions:{self.attacker_actions}\n" \ f"defender_actions:{self.defender_actions}\n" \ f"emulation_name: {self.emulation_name}," \ f"id:{self.id}"
[docs] @staticmethod def from_dict(d: Dict[str, Any]) -> "EmulationTrace": """ Converts a dict representation into an instance :param d: the dict to convert :return: the created instance """ obj = EmulationTrace( initial_attacker_observation_state=EmulationAttackerObservationState.from_dict( d["initial_attacker_observation_state"]), initial_defender_observation_state=EmulationDefenderObservationState.from_dict( d["initial_defender_observation_state"]), emulation_name=d["emulation_name"] ) obj.attacker_observation_states = list(map(lambda x: EmulationAttackerObservationState.from_dict(x), d["attacker_observation_states"])) obj.defender_observation_states = list(map(lambda x: EmulationDefenderObservationState.from_dict(x), d["defender_observation_states"])) obj.attacker_actions = list(map(lambda x: EmulationAttackerAction.from_dict(x), d["attacker_actions"])) obj.defender_actions = list(map(lambda x: EmulationDefenderAction.from_dict(x), d["defender_actions"])) return obj
[docs] def to_dict(self) -> Dict[str, Any]: """ Converts the object to a dict representation :return: a dict representation of the object """ d: Dict[str, Any] = {} d["initial_attacker_observation_state"] = self.initial_attacker_observation_state.to_dict() d["initial_defender_observation_state"] = self.initial_defender_observation_state.to_dict() d["attacker_observation_states"] = list(map(lambda x: x.to_dict(), self.attacker_observation_states)) d["defender_observation_states"] = list(map(lambda x: x.to_dict(), self.defender_observation_states)) d["attacker_actions"] = list(map(lambda x: x.to_dict(), self.attacker_actions)) d["defender_actions"] = list(map(lambda x: x.to_dict(), self.defender_actions)) d["emulation_name"] = self.emulation_name d["id"] = self.id return d
[docs] @staticmethod def save_traces_to_disk(traces_save_dir, traces: List["EmulationTrace"], traces_file: Optional[str] = None) -> None: """ Utility function for saving a list of traces to a json file :param traces_save_dir: the directory where to save the traces :param traces: the traces to save :param traces_file: the filename of the traces file :return: None """ traces_1 = list(map(lambda x: x.to_dict(), traces)) if traces_file is None: traces_file = constants.SYSTEM_IDENTIFICATION.EMULATION_TRACES_FILE if not os.path.exists(traces_save_dir): os.makedirs(traces_save_dir) with open(traces_save_dir + "/" + traces_file, 'w') as fp: json.dump({"traces": traces_1}, fp, cls=NpEncoder)
[docs] @staticmethod def load_traces_from_disk(traces_file: str) -> List["EmulationTrace"]: """ Utility function for loading and parsing a list of traces from a json file :param traces_file: (optional) a custom name of the traces file :return: a list of the loaded traces """ if os.path.exists(traces_file): with open(traces_file, 'r') as fp: d = json.load(fp) if constants.METADATA_STORE.TRACES_PROPERTY in d: traces = d[constants.METADATA_STORE.TRACES_PROPERTY] else: traces = d["emulations"] traces_1 = list(map(lambda x: EmulationTrace.from_dict(x), traces)) return traces_1 else: Logger.__call__().get_logger().info("Warning: Could not " f"read traces file, path does not exist:{traces_file}") return []
[docs] @staticmethod def from_json_str(json_str: str) -> "EmulationTrace": """ Converts json string into a DTO :param json_str: the json string representation :return: the DTO instance """ import json dto: EmulationTrace = EmulationTrace.from_dict(json.loads(json_str)) return dto
[docs] @staticmethod def from_json_file(json_file_path: str) -> "EmulationTrace": """ Reads a json file and converts it into a dto :param json_file_path: the json file path to save the DTO to :return: None """ import io with io.open(json_file_path, 'r', encoding='utf-8') as f: json_str = f.read() dto = EmulationTrace.from_json_str(json_str=json_str) return dto
[docs] def num_attributes_per_time_step(self) -> int: """ :return: approximately the number of attributes recorded per time-step of the trace """ num_attributes = 2 num_attributes = (num_attributes + (1 + len(self.attacker_observation_states)) * self.initial_attacker_observation_state.num_attributes()) num_attributes = (num_attributes + (1 + len(self.defender_observation_states)) * self.initial_defender_observation_state.num_attributes()) if len(self.defender_actions) > 0: num_attributes = num_attributes + len(self.defender_actions) * self.defender_actions[0].num_attributes() if len(self.attacker_actions) > 0: num_attributes = num_attributes + len(self.attacker_actions) * self.attacker_actions[0].num_attributes() return num_attributes
[docs] @staticmethod def schema(): """ :return: the schema of the DTO """ dto = EmulationTrace(initial_attacker_observation_state=EmulationAttackerObservationState.schema(), initial_defender_observation_state=EmulationDefenderObservationState.schema(), emulation_name="") dto.attacker_observation_states = [EmulationAttackerObservationState.schema()] dto.defender_observation_states = [EmulationDefenderObservationState.schema()] dto.attacker_actions = [EmulationAttackerAction.schema()] dto.defender_actions = [EmulationDefenderAction.schema()] return dto
[docs] def to_csv_record(self, max_time_steps: int, max_nodes: int, max_ports: int, max_vulns: int, null_value: int = -1) -> Tuple[List[Union[str, int, float]], List[str]]: """ Converts the trace into a csv row :param max_time_steps: the maximum number of time-steps to include in the row :param max_nodes: the maximum number of nodes to include metrics from :param max_ports: the maximum number of ports to include metrics from :param max_vulns: the maximum number of vulnerabilities to include metrics from :param null_value: the default null value if a metric is missing :return: the list of labels and values of the csv row """ # lookup tables for vuln names, service names, protocol names labels = [] values: List[Union[str, float]] = [] intrusion_started = False attacker_observations = [self.initial_attacker_observation_state] + self.attacker_observation_states defender_observations = [self.initial_defender_observation_state] + self.defender_observation_states for t in range(max_time_steps): labels.append(f"{t}_intrusion") if len(attacker_observations) > t: if not intrusion_started and self.attacker_actions[t].id != EmulationAttackerActionId.CONTINUE: intrusion_started = True values.append(int(intrusion_started)) else: values.append(null_value) labels.append(f"{t}_attacker_action_id") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append(self.attacker_actions[t - 1].id) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_action_name") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append(self.attacker_actions[t - 1].name) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_action_type") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append(self.attacker_actions[t - 1].type) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_action_ips") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append("-".join(self.attacker_actions[t - 1].ips)) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_action_index") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append(self.attacker_actions[t - 1].index) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_action_outcome") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append(self.attacker_actions[t - 1].action_outcome) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_action_execution_time") if (len(self.attacker_actions) + 1) > t: if t > 0: values.append(self.attacker_actions[t - 1].execution_time) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_id") if (len(self.defender_actions) + 1) > t: if t > 0: values.append(self.defender_actions[t - 1].id) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_name") if (len(self.defender_actions) + 1) > t: if t > 0: values.append(self.defender_actions[t - 1].name) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_type") if (len(self.defender_actions) + 1) > t: if t > 0: values.append(self.defender_actions[t - 1].type) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_ips") if (len(self.defender_actions) + 1) > t: if t > 0: values.append("-".join(self.defender_actions[t - 1].ips)) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_index") if (len(self.defender_actions) + 1) > t: if t > 0: values.append(self.defender_actions[t - 1].index) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_outcome") if (len(self.defender_actions) + 1) > t: if t > 0: values.append(self.defender_actions[t - 1].action_outcome) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_defender_action_execution_time") if (len(self.defender_actions) + 1) > t: if t > 0: values.append(self.defender_actions[t - 1].execution_time) else: values.append(null_value) else: values.append(null_value) labels.append(f"{t}_attacker_num_catched_flags") if len(attacker_observations) > t: values.append(attacker_observations[t].catched_flags) else: values.append(null_value) labels.append(f"{t}_defender_num_clients") if len(defender_observations) > t: values.append(defender_observations[t].avg_client_population_metrics.num_clients) else: values.append(null_value) labels.append(f"{t}_defender_clients_arrival_rate") if len(defender_observations) > t: values.append(defender_observations[t].avg_client_population_metrics.rate) else: values.append(null_value) labels.append(f"{t}_defender_num_pids") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.pids) else: values.append(null_value) labels.append(f"{t}_defender_cpu_percent") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.cpu_percent) else: values.append(null_value) labels.append(f"{t}_defender_mem_current") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.mem_current) else: values.append(null_value) labels.append(f"{t}_defender_mem_total") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.mem_total) else: values.append(null_value) labels.append(f"{t}_defender_mem_percent") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.mem_percent) else: values.append(null_value) labels.append(f"{t}_defender_blk_read") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.blk_read) else: values.append(null_value) labels.append(f"{t}_defender_blk_write") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.blk_write) else: values.append(null_value) labels.append(f"{t}_defender_net_rx") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.net_rx) else: values.append(null_value) labels.append(f"{t}_defender_net_tx") if len(defender_observations) > t: values.append(defender_observations[t].avg_docker_stats.net_tx) else: values.append(null_value) for i in range(4): labels.append(f"{t}_defender_num_snort_priority_{i}_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_snort_ids_alert_counters.priority_alerts[i]) else: values.append(null_value) for i in range(len(set(collector_constants.SNORT_IDS_ROUTER.SNORT_ALERT_IDS_ID.values()))): labels.append(f"{t}_defender_num_snort_class_{i}_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_snort_ids_alert_counters.class_alerts[i]) else: values.append(null_value) labels.append(f"{t}_defender_num_snort_severe_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_snort_ids_alert_counters.severe_alerts) else: values.append(null_value) labels.append(f"{t}_defender_num_snort_warning_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_snort_ids_alert_counters.warning_alerts) else: values.append(null_value) labels.append(f"{t}_defender_num_snort_total_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_snort_ids_alert_counters.total_alerts) else: values.append(null_value) labels.append(f"{t}_defender_num_snort_alerts_weighted_by_priority") if len(defender_observations) > t: values.append(defender_observations[t].avg_snort_ids_alert_counters.alerts_weighted_by_priority) else: values.append(null_value) labels.append(f"{t}_defender_num_ossec_severe_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_ossec_ids_alert_counters.severe_alerts) else: values.append(null_value) labels.append(f"{t}_defender_num_ossec_warning_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_ossec_ids_alert_counters.warning_alerts) else: values.append(null_value) labels.append(f"{t}_defender_num_ossec_total_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_ossec_ids_alert_counters.total_alerts) else: values.append(null_value) labels.append(f"{t}_defender_num_ossec_alerts_weighted_by_level") if len(defender_observations) > t: values.append(defender_observations[t].avg_ossec_ids_alert_counters.alerts_weighted_by_level) else: values.append(null_value) for i in range(16): labels.append(f"{t}_defender_num_ossec_level_{i}_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_ossec_ids_alert_counters.level_alerts[i]) else: values.append(null_value) for i in range(len(set(collector_constants.OSSEC.OSSEC_IDS_ALERT_GROUP_ID.values()))): labels.append(f"{t}_defender_num_ossec_group_{i}_alerts") if len(defender_observations) > t: values.append(defender_observations[t].avg_ossec_ids_alert_counters.group_alerts[i]) else: values.append(null_value) labels.append(f"{t}_defender_num_logged_in_users") if len(defender_observations) > t: values.append(defender_observations[t].avg_aggregated_host_metrics.num_logged_in_users) else: values.append(null_value) labels.append(f"{t}_defender_num_failed_login_attempts") if len(defender_observations) > t and defender_observations[t].avg_aggregated_host_metrics is not None: values.append(defender_observations[t].avg_aggregated_host_metrics.num_failed_login_attempts) else: values.append(null_value) labels.append(f"{t}_defender_num_open_connections") if len(defender_observations) > t and defender_observations[t].avg_aggregated_host_metrics is not None: values.append(defender_observations[t].avg_aggregated_host_metrics.num_open_connections) else: values.append(null_value) labels.append(f"{t}_defender_num_login_events") if len(defender_observations) > t and defender_observations[t].avg_aggregated_host_metrics is not None: values.append(defender_observations[t].avg_aggregated_host_metrics.num_login_events) else: values.append(null_value) labels.append(f"{t}_defender_num_processes") if len(defender_observations) > t and defender_observations[t].avg_aggregated_host_metrics is not None: values.append(defender_observations[t].avg_aggregated_host_metrics.num_processes) else: values.append(null_value) labels.append(f"{t}_defender_num_users") if len(defender_observations) > t and defender_observations[t].avg_aggregated_host_metrics is not None: values.append(defender_observations[t].avg_aggregated_host_metrics.num_users) else: values.append(null_value) for i in range(max_nodes): labels.append(f"{t}_node_{i}_ip") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].ips[0]) else: values.append(null_value) labels.append(f"{t}_node_{i}_os") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].os) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_discovered") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(1) else: values.append(null_value) for j in range(max_ports): labels.append(f"{t}_attacker_node_{i}_port_{j}_port_number") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].ports) > j: values.append(int(attacker_observations[t].machines[i].ports[j].port)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_port_{j}_open") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].ports) > j: values.append(int(attacker_observations[t].machines[i].ports[j].open)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_port_{j}_service") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].ports) > j: values.append(int(attacker_observations[t].machines[i].ports[j].service)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_port_{j}_protocol") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].ports) > j: values.append(int(attacker_observations[t].machines[i].ports[j].protocol)) else: values.append(null_value) for k in range(max_vulns): labels.append(f"{t}_attacker_node_{i}_vuln_{k}_name") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].cve_vulns) > k: values.append(attacker_observations[t].machines[i].cve_vulns[k].name) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_vuln_{k}_port_number") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].cve_vulns) > k: values.append(int(attacker_observations[t].machines[i].cve_vulns[k].port)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_vuln_{k}_protocol") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].cve_vulns) > k: values.append(int(attacker_observations[t].machines[i].cve_vulns[k].protocol)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_vuln_{k}_cvss") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].cve_vulns) > k: values.append(attacker_observations[t].machines[i].cve_vulns[k].cvss) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_vuln_{k}_osvdbid") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i \ and len(attacker_observations[t].machines[i].cve_vulns) > k \ and attacker_observations[t].machines[i].cve_vulns[k].osvdb_id is not None: values.append(int(attacker_observations[t].machines[i].cve_vulns[k].osvdb_id)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_shell_access") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].shell_access)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_logged_in") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].logged_in)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_root") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].root)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_num_flags_found") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(len(attacker_observations[t].machines[i].flags_found)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_file_system_searched") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].filesystem_searched)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_untried_credentials") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].untried_credentials)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_telnet_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].telnet_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_ssh_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].ssh_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_ftp_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].ftp_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_cassandra_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].cassandra_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_irc_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].irc_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_mongo_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].mongo_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_mysql_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].mysql_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_smtp_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].smtp_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_postgres_brute_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].postgres_brute_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_tools_installed") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].tools_installed)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_backdoor_installed") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].backdoor_installed)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_backdoor_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].backdoor_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_dvwa_sql_injection_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].dvwa_sql_injection_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_cve_2015_3306_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].cve_2015_3306_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_cve_2015_1427_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].cve_2015_1427_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_cve_2016_10033_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].cve_2016_10033_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_cve_2010_0426_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].cve_2010_0426_tried)) else: values.append(null_value) labels.append(f"{t}_attacker_node_{i}_cve_2015_5602_tried") if len(attacker_observations) > t and len(attacker_observations[t].machines) > i: values.append(int(attacker_observations[t].machines[i].cve_2015_5602_tried)) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_pids") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.pids) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_cpu_percent") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.cpu_percent) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_mem_current") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.mem_current) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_mem_total") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.mem_total) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_mem_percent") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.mem_percent) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_blk_read") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.blk_read) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_blk_write") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.blk_write) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_net_rx") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.net_rx) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_net_tx") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].docker_stats.net_tx) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_logged_in_users") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].host_metrics.num_logged_in_users) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_failed_login_attempts") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].host_metrics.num_failed_login_attempts) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_open_connections") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].host_metrics.num_open_connections) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_login_events") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].host_metrics.num_login_events) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_processes") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].host_metrics.num_processes) else: values.append(null_value) labels.append(f"{t}_node_{i}_defender_num_users") if len(defender_observations) > t and len(defender_observations[t].machines) > i: values.append(defender_observations[t].machines[i].host_metrics.num_users) else: values.append(null_value) assert len(values) == len(labels) return values, labels