// ========================================== // RULE 1: Classification // ========================================== // Classifies raw ESXi logs into event types using regex patterns for supporting Virtualization Story. [RULE: esxi_event_classification] alter is_command_execution = if( _raw_log ~= "(?i)user\s+\'\w+\'\s+running\s+command\s+\'.+\'" OR _raw_log ~= "\s+(?i)shell\[\d+\]\:\s+\[\w+\]\:\s.+" OR _raw_log ~= "\s+Console\s+log\s+content\s+for\s+the\s+command\s+.+" OR _raw_log ~= "started\s+from\s+\'\w+\'\s+\d+\s+with\s+cmdline\s+\'.+\'\,\s+parent\s+\d+" OR _raw_log ~= "crond\[\d+\]\:\s+USER\s+\w+\s+pid\s+\d+\s+cmd\s+.+" ), is_connection = if( _raw_log ~= "\s+(?i)SSH\s+session\s+was\s+opened\s+" OR _raw_log ~= "\s+(?i)SSH\s+login\s+has\s+failed\s+for\s+" OR _raw_log ~= "session\s+opened\s+for\s+(?:local)?\s*user\s+\w+\s+(?:on|from|by)\s+" OR _raw_log ~= "(?i:rejected|accepted)\s+connection\s+from\s+.*\:\d+" OR _raw_log ~= "Connect\s+from\s+remote\s+socket\s+\(.+\:\d+\)" OR _raw_log ~= "(?:Accepted|Failed|Postponed)\s+keyboard\-interactive\/pam\s+for\s+(?:invalid user |user )?\w+\s+from\s+.+\s+port\s+\d+\s+\w+" ), is_login = if( _raw_log ~= "Accepted\s+password\s+for\s+user\s+\w+\s+from\s+.+session" OR _raw_log ~= "User\s+\w*\@\S*\s+logged\s+in.*" OR _raw_log ~= "Cannot\s+login\s+(?:user\s)?\w*\@\S*" ), is_service_status_changed = if( _raw_log ~= "(?i)The\s+(?i)ESXi\s+command\s+line\s+shell\s+has\s+been\s+\w+" OR _raw_log ~= "Administrator\s+access\s+to\s+the\s+host\s+has\s+been\s+\w+" OR _raw_log ~= "SSH\s+access\s+has\s+been\s+\w+" ), is_fw_status_changed = if( _raw_log ~= "Firewall\s+configuration\s+has\s+changed\.\s+Operation\s+\S+\s+for\s+rule\s+set\s+" OR _raw_log ~= "Firewall\s+has\s+been\s+\w+" ), is_account_operations = if( _raw_log ~= "Password\s+was\s+changed\s+for\s+account\s+\w+\s+on\s+host\s+\S+" OR _raw_log ~= "Account\s+\w+\s+was\s+\w+\s+on\s+host\s+.+" ), is_file_or_datastore = if( _raw_log ~= "Deletion\s+of\s+file\s+or\s+directory\s+\S+\s+from\s+\S+\s+was\s+initiated\s+from" OR _raw_log ~= "File\s+upload\s+to\s+path\s+\'\[\S+\]\S+\'\s+was\s+initiated\s+from\s+\S+\s+and\s+completed" ), is_vm_operations = if( _raw_log ~= "Created\s+virtual\s+machine\s+\w+\s+on\s+\w+" OR _raw_log ~= "\w+\s+on\s+\w+\s+in\s+\S+\s+(?:has|is)?\s+powered\s+(?:on|off)" OR _raw_log ~= "Guest\s+OS\s+(?:reboot|shut down)?\s+for\s+\w+\s+on\s+\w+\s+in" OR _raw_log ~= "(?:Removed|Registered)\s+\w+\s+on\s+\S+\s+(?:in|from)\s+\S+" ), is_task = if( _raw_log ~= "Task\s+Completed\s+\:\s+\S+\-\d+\s+Status\s+\w+" ) | alter esxi_event_type = if( is_command_execution = TRUE, "Command Execution", is_connection = TRUE, "Connection", is_login = TRUE, "Login", is_service_status_changed = TRUE, "Service Status Changed", is_fw_status_changed = TRUE, "Firewall Status Changed", is_account_operations = TRUE, "Account operations", is_file_or_datastore = TRUE, "File/Datastore Event", is_vm_operations = TRUE, "VM Operations", is_task = TRUE, "Task Events" ); // ========================================== // RULE 2: General Field Mapping // ========================================== // Extracts Syslog priority, facility and severity from the header, and maps them to XDM fields that are mutual to all event types. [RULE: esxi_general_fields_mapping] alter // Extract the value from the syslog header syslog_priority = to_integer(parsed_fields -> pri) | alter // Extract the syslog facility from the priority value by dividing it by 8 syslog_facility = floor(divide(syslog_priority, 8)) | alter // Extract the severity remainder by subtracting (facility * 8) from the priority syslog_severity = subtract(syslog_priority, multiply(syslog_facility, 8)) | alter // Convert the numeric severity result back to string for mapping compatibility severity = to_string(syslog_severity), msg = parsed_fields -> msg | alter xdm.event.log_level = if( severity = "0", XDM_CONST.LOG_LEVEL_EMERGENCY , severity = "1", XDM_CONST.LOG_LEVEL_ALERT , severity = "2", XDM_CONST.LOG_LEVEL_CRITICAL, severity = "3", XDM_CONST.LOG_LEVEL_ERROR, severity = "4", XDM_CONST.LOG_LEVEL_WARNING, severity = "5", XDM_CONST.LOG_LEVEL_NOTICE, severity = "6", XDM_CONST.LOG_LEVEL_INFORMATIONAL, severity = "7", XDM_CONST.LOG_LEVEL_DEBUG, severity), xdm.event.description = msg, xdm.event.type = esxi_event_type, xdm.event.format = if(_raw_log ~= "\<\d+\>1", "RFC-5424", _raw_log ~= "\<\d+\>", "RFC-3164"), xdm.event.tags = arraycreate("VIRTUALIZATION"); // ========================================== // Modeling Rule // ========================================== [MODEL: dataset="vmware_esxi_raw"] // ------------------------------------------ // Virtualization event type 1: Command Execution // ------------------------------------------ // Log pattern 1#: User '' running command ' call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Command Execution" AND _raw_log ~= "(?i)user\s+\'\w+\'\s+running\s+command\s+\'.+\'" | alter // Extract fields source_process = arrayindex(regextract(parsed_fields -> process_pid, "(.+)\["),0), source_pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "User\s+\'(\S+)\'\s+"),0), command_line = arrayindex(regextract(msg, "command\s+\'(.+)\'"),0) | alter // Derive target process from the command line target_first_token = arrayindex(regextract(command_line, "^(\S+)"),0) | alter target_process_name = arrayindex(regextract(target_first_token, "([^\/]+)$"),0), target_process_path = if(target_first_token ~= "\/", target_first_token, null) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = source_process, xdm.source.process.pid = to_integer(source_pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.target.process.name = target_process_name, xdm.target.process.executable.path = target_process_path, xdm.target.process.command_line = command_line, xdm.event.operation = XDM_CONST.OPERATION_TYPE_EXECUTION, xdm.event.operation_sub_type = "User interactive"; // Log pattern 2#: (?i)shell\[]: ?(\[\]:) call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Command Execution" AND _raw_log ~= "\s+(?i)shell\[\d+\]\:\s+\[\w+\]\:\s.+" | alter // Extract fields process = arrayindex(regextract(parsed_fields -> process_pid, "(.+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "\[(\w+)\]\:"),0), command_line = arrayindex(regextract(msg, "\[\w+\]\:\s(.+)"),0) | alter // Derive target process from the command line target_first_token = arrayindex(regextract(command_line, "^(\S+)"),0) | alter target_process_name = arrayindex(regextract(target_first_token, "([^\/]+)$"),0), target_process_path = if(target_first_token ~= "\/", target_first_token, null) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = process, xdm.source.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.target.process.name = target_process_name, xdm.target.process.executable.path = target_process_path, xdm.target.process.command_line = command_line, xdm.event.operation = XDM_CONST.OPERATION_TYPE_EXECUTION, xdm.event.operation_sub_type = "User interactive"; // Log pattern 3#: \[script_name\] :: Console log content for the command call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Command Execution" AND _raw_log ~= "\s+Console\s+log\s+content\s+for\s+the\s+command\s+.+" | alter // Extract fields process = arrayindex(regextract(parsed_fields -> process_pid, "(.+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), script_name = arrayindex(regextract(msg, "\[\w+\]\s+\:+\s+\[(.+)\]"),0), command_line = arrayindex(regextract(msg, "command\s+(.+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process, xdm.target.process.pid = to_integer(pid), xdm.target.virtualization.script_name = script_name, xdm.target.process.command_line = command_line, xdm.event.operation = XDM_CONST.OPERATION_TYPE_EXECUTION, xdm.event.operation_sub_type = "Script commands"; // Log format 4#: started from with cmdline '', parent call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Command Execution" AND _raw_log ~= "started\s+from\s+\'\w+\'\s+\d+\s+with\s+cmdline\s+\'.+\'\,\s+parent\s+\d+" | alter // Extract fields source_process_name = arrayindex(regextract(msg, "started\s+from\s+\'(\w+)\'"),0), target_pid = arrayindex(regextract(msg, "started\s+from\s+\'\w+\'\s+(\d+)"),0), command_line = arrayindex(regextract(msg, "with\s+cmdline\s+\'(.+)\'"),0), source_pid = arrayindex(regextract(msg, "parent\s+(\d+)"),0) | alter // Derive target process from the cmdline target_first_token = arrayindex(regextract(command_line, "^(\S+)"),0) | alter target_process_name = arrayindex(regextract(target_first_token, "([^\/]+)$"),0), target_process_path = if(target_first_token ~= "\/", target_first_token, null) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = source_process_name, xdm.source.process.pid = to_integer(source_pid), xdm.target.process.pid = to_integer(target_pid), xdm.target.process.name = target_process_name, xdm.target.process.executable.path = target_process_path, xdm.target.process.command_line = command_line, xdm.event.operation = XDM_CONST.OPERATION_TYPE_PROCESS_START, xdm.event.operation_sub_type = "System process start"; // Log format 5#: crond\[\]: USER pid cmd call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Command Execution" AND _raw_log ~= "crond\[\d+\]\:\s+USER\s+\w+\s+pid\s+\d+\s+cmd\s+.+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), src_pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "USER\s+(\w+)"),0), pid = arrayindex(regextract(msg, "pid\s+(\d+)"),0), command_line = arrayindex(regextract(msg, "cmd\s+(.+)"),0) | alter exec_token = arrayindex(regextract(command_line, "^(\S+)"),0) | alter exec_name = arrayindex(regextract(exec_token, "([^\/]+)$"),0), exec_path = if(exec_token ~= "\/", exec_token, null) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = process_name, xdm.source.process.pid= to_integer(src_pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.target.process.pid = to_integer(pid), xdm.target.process.command_line = command_line, xdm.target.process.name = exec_name, xdm.target.process.executable.path = exec_path, xdm.event.operation = XDM_CONST.OPERATION_TYPE_PROCESS_START, xdm.event.operation_sub_type = "crond process start"; // ------------------------------------------ // Virtualization event type 2: Connection // ------------------------------------------ // Log format 1#: "Event \d+ : SSH session was opened ?for '@'." // Log format 2#: "Event \d+ : SSH login has failed for '@'" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "\s+(?i)SSH\s+(?:session|login)\s+(?:was|has)\s+(?:opened|failed)\s+for\s+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\[*"),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "\'(\w+)\@"),0), source_ip = arrayindex(regextract(msg, "\'\w+\@(.+)?\'"),0), outcome_reason = arrayindex(regextract(msg, "SSH\s+.+"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = if(pid != null, to_integer(pid), null), xdm.target.user.username = user_name, xdm.target.identity.username = user_name, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.event.outcome = if( msg ~= "SSH\s+session\s+was\s+opened",XDM_CONST.OUTCOME_SUCCESS, msg ~= "SSH\s+login\s+has\s+failed", XDM_CONST.OUTCOME_FAILED), xdm.event.outcome_reason = coalesce(outcome_reason,msg), xdm.network.application_protocol = "ssh", xdm.event.operation = XDM_CONST.OPERATION_TYPE_AUTHENTICATION, xdm.event.operation_sub_type = if( msg ~= "SSH\s+session\s+was\s+opened", "ssh opened", msg ~= "SSH\s+login\s+has\s+failed", "ssh failed"); // Log format 3#: "session opened for ?local user from []" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "session\s+opened\s+for\s+(?:local)?\s*user\s+\w+\s+from\s+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\[*"),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "user\s+(\w+)\s+"),0), source_ip = arrayindex(regextract(msg, "user\s+\w+\s+from\s+\[(.+)?\]"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.source.user.scope = if(msg ~= "session\s+opened\s+for\s+local\s+user\s+", XDM_CONST.SCOPE_TYPE_LOCAL), xdm.source.identity.scope = if(msg ~= "session\s+opened\s+for\s+local\s+user\s+", XDM_CONST.SCOPE_TYPE_LOCAL), xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "session opened", xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = msg; // Log format 4#: "session opened for ?local user by (uid=)" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "session\s+opened\s+for\s+(?:local)?\s*user\s+\w+\s+by\s+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\[*"),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "user\s+(\w+)\s+"),0), uid = arrayindex(regextract(msg, "user\s+\w+\s+by\s+\(uid\=(\d+)"),0), outcome_reason = arrayindex(regextract(msg, "session\s+opened\s+for.+"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.source.user.identifier = uid, xdm.source.identity.identifier = uid, xdm.source.user.scope = if(msg ~= "session\s+opened\s+for\s+local\s+user\s+", XDM_CONST.SCOPE_TYPE_LOCAL), xdm.source.identity.scope = if(msg ~= "session\s+opened\s+for\s+local\s+user\s+", XDM_CONST.SCOPE_TYPE_LOCAL), xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "session opened", xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg); // Log format 5#: "rejected connection from .*.*:" // Log format 6#: "accepted connection from .*.*:" // Log format 7#: "Accepted connection from <:>" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "(?i:rejected|accepted)\s+connection\s+from\s+.*\:\d+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), source_ip = arrayindex(regextract(msg, "connection\s+from\s+[\'\"\<]*(.+?)\:"),0), source_ipv4 = arrayindex(regextract(msg, "[\<\"\'].+\:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:\>|\"|\')"),0), source_ipv6 = arrayindex(regextract(msg, "[\<\"\'](.+)\:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:\>|\"|\')"),0), source_port = arrayindex(regextract(msg, "connection\s+from\s+.+\:(\d+)[\"\'\>]"),0), error = arrayindex(regextract(msg, "error\s+\"(.+?)\""),0), server_name = arrayindex(regextract(msg, "ServerName\s+\"([^\"]+)"),0), outcome_reason = arrayindex(regextract(msg, "((?i:rejected|accepted).+)"),0) | alter // Map to XDM xdm.target.host.hostname = coalesce(server_name, parsed_fields -> hostname), xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip, is_ipv4(source_ipv4) = TRUE, source_ipv4), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip, is_ipv6(source_ipv6) = TRUE, source_ipv6), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip), is_known_private_ipv4(source_ipv4) = TRUE, arraycreate(source_ipv4)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip), is_known_private_ipv6(source_ipv6) = TRUE, arraycreate(source_ipv6)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip), is_known_private_ipv4(source_ipv4) = FALSE, arraycreate(source_ipv4)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip), is_known_private_ipv6(source_ipv6) = FALSE, arraycreate(source_ipv6)), xdm.source.port = to_integer(source_port), xdm.event.outcome_reason = coalesce(error, outcome_reason, msg), xdm.event.outcome = if( msg ~= "accepted", XDM_CONST.OUTCOME_SUCCESS, msg ~= "rejected", XDM_CONST.OUTCOME_FAILED), xdm.event.operation = if( msg ~= "rejected",XDM_CONST.OPERATION_TYPE_REJECT, msg ~= "accepted", XDM_CONST.OPERATION_TYPE_AUTHENTICATION), xdm.event.operation_sub_type = if( msg ~= "rejected","rejected connection", msg ~= "accepted", "accepted connection"); // Log format 8#: "Connect from remote socket (:)." call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "Connect\s+from\s+remote\s+socket\s+\(.+\:\d+\)" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), source_ip = arrayindex(regextract(msg, "\((.+)?\:"),0), source_port = arrayindex(regextract(msg, "\(.+\:(\d+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.source.port = to_integer(source_port), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = msg, xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "remote socket connection"; // Log format 9#: "Accepted keyboard-interactive/pam for from port " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "Accepted\s+keyboard\-interactive\/pam\s+for\s+(?:invalid user |user )?\w+\s+from\s+.+\s+port\s+\d+\s+\w+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "for\s+(?:user |invalid user )?(\w+)?"),0), source_ip = arrayindex(regextract(msg, "from\s+(\S+)"),0), source_port = arrayindex(regextract(msg, "port\s+(\d+)"),0), protocol = arrayindex(regextract(msg, "port\s+\d+\s+(\w+)"),0) | alter // Map XDM mapping xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.source.port = to_integer(source_port), xdm.network.application_protocol = protocol, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = msg, xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "keyboard interactive session"; // Log format 10#: "Failed|Postponed keyboard-interactive/pam for ?invalid user from port " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Connection" AND _raw_log ~= "(?:Failed|Postponed)\s+keyboard\-interactive\/pam\s+for\s+(?:invalid user |user )?\w+\s+from\s+.+\s+port\s+\d+\s+\w+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "for\s+(?:user |invalid user )?(\w+)?"),0), source_ip = arrayindex(regextract(msg, "from\s+(\S+)"),0), source_port = arrayindex(regextract(msg, "port\s+(\d+)"),0), protocol = arrayindex(regextract(msg, "port\s+\d+\s+(\w+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.target.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.target.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.target.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.target.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.target.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.target.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.target.port = to_integer(source_port), xdm.network.application_protocol = protocol, xdm.event.outcome = XDM_CONST.OUTCOME_FAILED, xdm.event.outcome_reason = msg, xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "interactive session failed"; // ------------------------------------------ // Virtualization event type 3: Login // ------------------------------------------ // Log format 1#: "Accepted password for user from - session=" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Login" AND _raw_log ~= "Accepted\s+password\s+for\s+user\s+\w+\s+from\s+.+session" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "user\s+(\S+)\s+"),0), source_ip = arrayindex(regextract(msg, "from\s+(\S+)\s+"),0), session_id = arrayindex(regextract(msg, "session\=(\S+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.network.session_id = session_id, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = "Accepted password", xdm.event.operation = XDM_CONST.OPERATION_TYPE_AUTHENTICATION, xdm.event.operation_sub_type = "login success"; // Log format 2#: "Event \d+ : "Event \d+ : User @ logged in ?as ?" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Login" AND _raw_log ~= "User\s+\w*\@\S*\s+logged\s+in.*" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "User\s+([^@]+)"),0), user_agent = arrayindex(regextract(msg, "logged\s+in\s+(?:as\s*)*(.+)"),0), source_ip = arrayindex(regextract(msg, "\@(\S+)\s+logged"),0), outcome_reason = arrayindex(regextract(msg, "Event\s+\d+\s+\:\s+(User.+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.source.user_agent = user_agent, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_AUTH_LOGIN, xdm.event.operation_sub_type = "login success"; // Log format 3#: "Event \d+ : Cannot login ?user @ ?(: )" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Login" AND _raw_log ~= "Cannot\s+login\s+(?:user\s)?\w*\@\S*" | alter // Extract fields process_name1 = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), process_name2 = arrayindex(regextract(msg, "(\w+)\["),0), pid1 = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), pid2 = arrayindex(regextract(msg, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "login\s+(?:user\s*)*([^@]+)"),0), source_ip = arrayindex(regextract(msg, "login.+\@([^:]+)"),0), reason = arrayindex(regextract(msg, "login.+\@\S+\:\s+(.+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = coalesce(process_name2, process_name1), xdm.target.process.pid = coalesce(to_integer(pid2),to_integer(pid1)), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.event.outcome_reason = reason, xdm.event.outcome = XDM_CONST.OUTCOME_FAILED, xdm.event.operation = XDM_CONST.OPERATION_TYPE_AUTH_LOGIN, xdm.event.operation_sub_type = "login failed"; // ------------------------------------------ // Virtualization event type 4: Service Status Changed // ------------------------------------------ // Log format 1#: "(?i)The ESX?(i) command line shell has been " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Service Status Changed" AND _raw_log ~= "(?i)The\s+(?i)ESXi\s+command\s+line\s+shell\s+has\s+been\s+\w+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), command_line = arrayindex(regextract(msg, "command\s+line\s+(.+?)\s+has"),0), status = arrayindex(regextract(msg, "has\s+been\s+(\w+)"),0), outcome_reason = arrayindex(regextract(msg, "\:\s(The.+)"),0) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = process_name, xdm.source.process.pid = to_integer(pid), xdm.source.process.command_line = command_line, xdm.event.operation_sub_type = status, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_UPDATE; // Log format 2#: "Event \d+ : Administrator access to the host has been " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Service Status Changed" AND _raw_log ~= "Administrator\s+access\s+to\s+the\s+host\s+has\s+been\s+\w+" | alter // Extract fields process_name1 = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), process_name2 = arrayindex(regextract(msg, "(\w+)\["),0), pid1 = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), pid2 = arrayindex(regextract(msg, "\[(\d+)"),0), status = arrayindex(regextract(msg, "has\s+been\s+(\w+)"),0), outcome_reason = arrayindex(regextract(msg, "Event\s+\d+\s+\:\s+(.+)"),0) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = coalesce(process_name2, process_name1), xdm.source.process.pid = coalesce(to_integer(pid2), to_integer(pid1)), xdm.event.operation_sub_type = status, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_UPDATE; // Log format 3#: "Event \d+ : SSH access has been " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Service Status Changed" AND _raw_log ~= "SSH\s+access\s+has\s+been\s+\w+" | alter // Extract fields process_name1 = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), process_name2 = arrayindex(regextract(msg, "(\w+)\["),0), pid1 = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), pid2 = arrayindex(regextract(msg, "\[(\d+)"),0), status = arrayindex(regextract(msg, "has\s+been\s+(\w+)"),0), outcome_reason = arrayindex(regextract(msg, "\:\s(SSH.+)"),0) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = coalesce(process_name2, process_name1), xdm.source.process.pid = coalesce(to_integer(pid2), to_integer(pid1)), xdm.event.operation_sub_type = status, xdm.network.application_protocol = "ssh", xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_UPDATE; // ------------------------------------------ // Virtualization event type 5: Firewall Status Changed // ------------------------------------------ // Log format 1#: "Firewall configuration has changed. Operation for rule set ." call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Firewall Status Changed" AND _raw_log ~= "Firewall\s+configuration\s+has\s+changed\.\s+Operation\s+\S+\s+for\s+rule\s+set\s+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), operation_name = arrayindex(regextract(msg, "Operation\s+\'(.+?)\'"),0), rule_set_name = arrayindex(regextract(msg,"rule\s+set\s+(\S+)\s+" ),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(Firewall.+)"),0) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = process_name, xdm.source.process.pid = to_integer(pid), xdm.observer.action = operation_name, xdm.network.rule = rule_set_name, xdm.event.outcome = if( msg ~= "rule\s+set\s+\S+\s+succeeded", XDM_CONST.OUTCOME_SUCCESS, msg ~= "rule\s+set\s+\S+\s+fail", XDM_CONST.OUTCOME_FAILED), xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_CONFIG_CHANGE, xdm.event.operation_sub_type = "firewall config change"; // Log format 2#: "Event \d+ : Firewall has been ." call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Firewall Status Changed" AND _raw_log ~= "Firewall\s+has\s+been\s+\w+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(Firewall.+)"),0) | alter // Map to XDM xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = process_name, xdm.source.process.pid = to_integer(pid), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.observer.action = if( msg ~= "disabled", "disabled", msg ~= "enabled", "enabled"), xdm.event.operation = XDM_CONST.OPERATION_TYPE_CONFIG_CHANGE, xdm.event.operation_sub_type = "firewall status change"; // ------------------------------------------ // Virtualization event type 6/7: Account Operations // ------------------------------------------ // Log format 1#: "Event \d+ : Password was changed for account on host " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Account operations" AND _raw_log ~= "Password\s+was\s+changed\s+for\s+account\s+\w+\s+on\s+host\s+\S+" | alter // Extract fields process_name1 = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), process_name2 = arrayindex(regextract(msg, "(\w+)\["),0), pid1 = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), pid2 = arrayindex(regextract(msg, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "changed\s+for\s+account\s+(\S+)"),0), target_esxi_host = arrayindex(regextract(msg, "on\s+host\s+(\S+)"),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(Password.+)"),0) | alter // Map to XDM xdm.source.host.hostname = coalesce(target_esxi_host,parsed_fields -> hostname), xdm.source.process.name = coalesce(process_name2, process_name1), xdm.source.process.pid = coalesce(to_integer(pid2), to_integer(pid1)), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_UPDATE, xdm.event.operation_sub_type = "password change"; // Log format 2#: "Event \d+ : Account was created on host " // Log format 3#: "Event \d+ : Account was removed on host " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Account operations" AND _raw_log ~= "Account\s+\w+\s+was\s+\w+\s+on\s+host\s+.+" | alter // Extract fields process_name1 = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), process_name2 = arrayindex(regextract(msg, "(\w+)\["),0), pid1 = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), pid2 = arrayindex(regextract(msg, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "Account\s+(\w+)"),0), target_esxi_host = arrayindex(regextract(msg, "on\s+host\s+(\S+)"),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(Account.+)"),0) | alter // Map to XDM xdm.source.host.hostname = coalesce(target_esxi_host, parsed_fields -> hostname), xdm.source.process.name = coalesce(process_name2, process_name1), xdm.source.process.pid = coalesce(to_integer(pid2), to_integer(pid1)), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = if( msg ~= "was\s+created", XDM_CONST.OPERATION_TYPE_CREATE, msg ~= "was\s+removed" , XDM_CONST.OPERATION_TYPE_DELETE), xdm.event.operation_sub_type = if( msg ~= "was\s+created", "account created", msg ~= "was\s+removed" , "account removed"); // ------------------------------------------ // Virtualization event type 8: File/Datastore // ------------------------------------------ // Log format 1#: "Event \d+ : Deletion of file or directory from was initiated from '@' and completed with status ''" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "File/Datastore Event" AND _raw_log ~= "Deletion\s+of\s+file\s+or\s+directory\s+\S+\s+from\s+\S+\s+was\s+initiated\s+from" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), file_path = arrayindex(regextract(msg, "file\s+or\s+directory\s+(\S+)"),0), location = arrayindex(regextract(msg, "Deletion\s+of\s+file\s+or\s+directory\s+\S+\s+from\s+(\S+)\s+"),0), user_agent = arrayindex(regextract(msg, "initiated\s+from\s+\'(.+?)\@"),0), source_ip = arrayindex(regextract(msg, "initiated\s+from\s+\'.+?\@(.+?)\'"),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(Deletion.+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.target.file.path = file_path, xdm.target.virtualization.data_store.name = location, xdm.source.user_agent = user_agent, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.event.outcome = if( msg ~= "completed\s+with\s+status\s+\'[Ss]uccess", XDM_CONST.OUTCOME_SUCCESS, msg ~= "completed\s+with\s+status\s+\'[Ff]ail", XDM_CONST.OUTCOME_FAILED), xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.is_completed = if(msg ~= "and\s+completed", TRUE), xdm.event.operation = XDM_CONST.OPERATION_TYPE_FILE_REMOVE, xdm.event.operation_sub_type = "file delete"; // Log format 2#: "Event \d+ : File upload to path '\[\]' was initiated from '@' and completed with status ''" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "File/Datastore Event" AND _raw_log ~= "File\s+upload\s+to\s+path\s+\'\[\S+\]\S+\'\s+was\s+initiated\s+from\s+\S+\s+and\s+completed" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), location = arrayindex(regextract(msg, "File\s+upload\s+to\s+path\s+\'\[(\S+)\]"),0), file_path = arrayindex(regextract(msg, "\'\[.+?](\S+)\'"),0), user_agent = arrayindex(regextract(msg, "initiated\s+from\s+\'(.+?)\@"),0), source_ip = arrayindex(regextract(msg, "initiated\s+from\s+\'.*\@(.*?)\'"),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(File.+)"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.target.virtualization.data_store.name = location, xdm.target.file.path = file_path, xdm.source.user_agent = user_agent, xdm.source.ipv4 = if(is_ipv4(source_ip) = TRUE, source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip) = TRUE, source_ip), xdm.source.host.ipv4_addresses = if(is_known_private_ipv4(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip) = TRUE, arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE,arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.event.outcome = if( msg ~= "completed\s+with\s+status\s+\'[Ss]uccess", XDM_CONST.OUTCOME_SUCCESS, msg ~= "completed\s+with\s+status\s+\'[Ff]ail", XDM_CONST.OUTCOME_FAILED), xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.is_completed = if(msg ~= "and\s+completed", TRUE), xdm.event.operation = XDM_CONST.OPERATION_TYPE_FILE_WRITE, xdm.event.operation_sub_type = "file upload"; // ------------------------------------------ // Virtualization event type 9: VM Operations // ------------------------------------------ // Log format 1#: Event \d+ : Created virtual machine on in call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "VM Operations" AND _raw_log ~= "Created\s+virtual\s+machine\s+\w+\s+on\s+\w+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user = arrayindex(regextract(msg, "user\=([^\]]+)"),0), vm_name = arrayindex(regextract(msg, "virtual\s+machine\s+(\S+)"),0), target_esxi_host = arrayindex(regextract(msg, "virtual\s+machine\s+\S+\s+on\s+([^,]+)"),0), data_center_name = arrayindex(regextract(msg, "virtual\s+machine\s+\S+\s+on\s+\S+\s+in\s+(\S+)"),0), outcome_reason = arrayindex(regextract(msg, "\:\s+(Created.+)"),0) | alter // Map to XDM xdm.target.host.hostname = coalesce(target_esxi_host, parsed_fields -> hostname), xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user, xdm.source.identity.username = user, xdm.target.virtualization.vm.hostname = vm_name, xdm.target.virtualization.data_center.name = data_center_name, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason,msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "VM Created", xdm.event.original_event_type = "VM Created"; // Log format 2#: "Event \d+ : on in has powered on" // Log format 3#: "Event \d+ : on in is powered off" call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "VM Operations" AND _raw_log ~= "\w+\s+on\s+\w+\s+in\s+\S+\s+(?:has|is)?\s+powered\s+(?:on|off)" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), vm_name = arrayindex(regextract(msg, "\:\s+(\S+)"),0), target_esxi_host = arrayindex(regextract(msg, "on\s+(\S+)"),0), data_center_name = arrayindex(regextract(msg, "on\s+\S+\s+in\s+(\S+)"),0), outcome_reason = arrayindex(regextract(msg, "Event\s+\d+\s+\:\s+(.+)"),0) | alter // Map to XDM xdm.target.host.hostname = coalesce(target_esxi_host, parsed_fields -> hostname), xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.target.virtualization.vm.hostname = vm_name, xdm.target.virtualization.data_center.name = data_center_name, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason,msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_STATUS_CHANGE, xdm.event.operation_sub_type = if( msg ~= "has\s+powered\s+on", "VM Power On", msg ~= "is\s+powered\s+off", "VM Power Off"), xdm.event.original_event_type = if( msg ~= "has\s+powered\s+on", "VM Power On", msg ~= "is\s+powered\s+off", "VM Power Off"); // Log format 4#: "Event \d+ : Guest OS reboot for on in " // Log format 5#: "Event \d+ : Guest OS shut down for on in " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "VM Operations" AND _raw_log ~= "Guest\s+OS\s+(?:reboot|shut down)?\s+for\s+\w+\s+on\s+\w+\s+in" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user = arrayindex(regextract(msg, "user\=([^\]]+)"),0), vm_name = arrayindex(regextract(msg, "Guest\s+OS\s+(?:reboot|shut down)?\s+for\s+(\w+)\s+"),0), target_esxi_host = arrayindex(regextract(msg, "Guest\s+OS\s+(?:reboot|shut down)?\s+for\s\w+\s+on\s+(\w+)\s+in"),0), data_center_name = arrayindex(regextract(msg, "Guest\s+OS\s+(?:reboot|shut down)?\s+for\s\w+\s+on\s+\w+\s+in\s+(\S+)"),0), outcome_reason = arrayindex(regextract(msg, "Guest\s+OS\s+.+"),0) | alter // Map to XDM xdm.target.host.hostname = coalesce(target_esxi_host, parsed_fields -> hostname), xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user, xdm.source.identity.username = user, xdm.target.virtualization.vm.hostname = vm_name, xdm.target.virtualization.data_center.name = data_center_name, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason,msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_STATUS_CHANGE, xdm.event.operation_sub_type = if( msg ~= "Guest\s+OS\s+reboot", "Guest OS VM Reboot", msg ~= "Guest\s+OS\s+shut down", "Guest OS VM Shutdown"), xdm.event.original_event_type = if( msg ~= "Guest\s+OS\s+reboot", "Guest OS VM Reboot", msg ~= "Guest\s+OS\s+shut down", "Guest OS VM Shutdown"); // Log format 6#: "Event \d+ : Removed on from " // Log format 7#: "Event \d+ : Registered on in " call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "VM Operations" AND _raw_log ~= "(?:Removed|Registered)\s+\w+\s+on\s+\S+\s+(?:in|from)\s+\S+" | alter // Extract fields target_esxi_host = arrayindex(regextract(msg, "(?:Removed|Registered)\s+\w+\s+on\s+(\S+)\s+"),0), process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user = arrayindex(regextract(msg, "user\=([^\]]+)"),0), vm_name = arrayindex(regextract(msg, "(?:Removed|Registered)\s+(\w+)\s+"),0), data_center_name = arrayindex(regextract(msg, "(?:Removed|Registered)\s+\w+\s+on\s+\S+\s+(?:in|from)\s+(\S+)"),0), outcome_reason = arrayindex(regextract(msg, "(?:Removed|Registered)\s+.+"),0) | alter // Map to XDM xdm.target.host.hostname = coalesce(target_esxi_host, parsed_fields -> hostname), xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user, xdm.source.identity.username = user, xdm.target.virtualization.vm.hostname = vm_name, xdm.target.virtualization.data_center.name = data_center_name, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS, xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = if( msg ~= "Removed\s+.+", XDM_CONST.OPERATION_TYPE_DELETE, msg ~= "Registered\s+.+", XDM_CONST.OPERATION_TYPE_CONFIG_CHANGE), xdm.event.operation_sub_type = if( msg ~= "Removed\s+.+", "VM Removed", msg ~= "Registered\s+.+","VM Registered"), xdm.event.original_event_type = if( msg ~= "Removed\s+.+", "VM Removed", msg ~= "Registered\s+.+","VM Registered"); // ------------------------------------------ // Virtualization event type 10: Task Events // ------------------------------------------ // Log format: Task Completed : - Status call esxi_event_classification | call esxi_general_fields_mapping | filter esxi_event_type = "Task Events" AND _raw_log ~= "Task\s+Completed\s+\:\s+\S+\-\d+\s+Status\s+\w+" | alter // Extract fields process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), user_name = arrayindex(regextract(msg, "user\=([^\]]+)"),0), vcenter_event = arrayindex(regextract(msg, "Task\s+Completed\s+\:\s+(\S+)\-\d+"),0), vcenter_event_unique_task_id = arrayindex(regextract(msg, "Task\s+Completed\s+\:\s+\S+\-(\d+)"),0), outcome_reason = arrayindex(regextract(msg, "Task\s+Completed.+"),0) | alter // Map to XDM xdm.target.host.hostname = parsed_fields -> hostname, xdm.target.process.name = process_name, xdm.target.process.pid = to_integer(pid), xdm.source.user.username = user_name, xdm.source.identity.username = user_name, xdm.target.virtualization.task.name = vcenter_event, xdm.target.virtualization.task.id = vcenter_event_unique_task_id, xdm.event.outcome = if( msg ~= "Status\s+[Ss]uccess", XDM_CONST.OUTCOME_SUCCESS, msg ~= "Status\s+[Fa]il", XDM_CONST.OUTCOME_FAILED), xdm.event.outcome_reason = coalesce(outcome_reason, msg), xdm.event.operation = XDM_CONST.OPERATION_TYPE_CREATE, xdm.event.operation_sub_type = "ESXi Task", xdm.event.is_completed = true; call esxi_event_classification | filter esxi_event_type = null // Extract the value from the syslog header | alter syslog_priority = to_integer(parsed_fields -> pri) // Extract the syslog facility from the priority value by dividing it by 8 | alter syslog_facility = floor(divide(syslog_priority, 8)) | alter syslog_severity = subtract(syslog_priority, multiply(syslog_facility, 8)), // Extract the severity remainder by subtracting (facility * 8) from the priority username_1 = arrayindex(regextract(_raw_log ,"User\s\'([a-zA-Z]+)\'"),0), username_2 = arrayindex(regextract(_raw_log ,"for\s+(\S+)\s+from"),0), username_3 = arrayindex(regextract(_raw_log , "[Uu]ser\s+(?:name\:\s+)*(\w+)"),0), command_line = arrayindex( regextract(_raw_log ,"command\s\'([^\']+)\'"),0), source_ip_1 = arrayindex( regextract(_raw_log ,"from\s(\d+\.\d+\.\d+\.\d+)\s"),0), source_ip_2 = arrayindex(regextract(_raw_log, "(\S+)\s+port"),0), source_port = arrayindex( regextract(_raw_log ,"port\s+(\d+)"),0), msg_1 = arrayindex( regextract(_raw_log ,"\:\s+(.*)$"),0), msg_2 = arrayindex( regextract(_raw_log ,"T\d+\:\d+\:\d+\.*\d*Z\|\s[a-zA-Z0-9\-\_]+\|\s\w+\:\s*(.*)"),0), msg_3 = arrayindex(regextract(_raw_log ,"line \d+\:(.*)$"),0), path_1 = arrayindex( regextract(_raw_log ,"path\:\s*(\S+)"),0), path_2 = arrayindex( regextract(_raw_log ,"on\s(\/\S+)"),0), mac_address = arrayindex( regextract(_raw_log , "MAC Address:\s([a-zA-Z0-9]+\:[a-zA-Z0-9]+\:[a-zA-Z0-9]+\:[a-zA-Z0-9]+\:[a-zA-Z0-9]+\:[a-zA-Z0-9]+)"),0) | alter msg = coalesce(msg_1, msg_2, msg_3, parsed_fields -> msg), path = coalesce(path_1, path_2), username = coalesce(username_1, username_2, username_3), source_ip = coalesce(source_ip_1, source_ip_2), process_name = arrayindex(regextract(parsed_fields -> process_pid, "(\w+)\["),0), pid = arrayindex(regextract(parsed_fields -> process_pid, "\[(\d+)"),0), severity = to_string(syslog_severity) // Convert the numeric severity result back to string for mapping compatibility | alter // XDM Mapping xdm.source.user.username = username, xdm.source.identity.username = username, xdm.source.host.hostname = parsed_fields -> hostname, xdm.source.process.name = process_name, xdm.source.process.pid = to_integer(pid), xdm.target.process.command_line = command_line, xdm.source.ipv4 = if(is_ipv4(source_ip), source_ip), xdm.source.ipv6 = if(is_ipv6(source_ip), source_ip), xdm.source.host.ipv4_addresses = if( is_known_private_ipv4(source_ip), arraycreate(source_ip)), xdm.source.host.ipv6_addresses = if(is_known_private_ipv6(source_ip), arraycreate(source_ip)), xdm.source.host.ipv4_public_addresses = if(is_known_private_ipv4(source_ip) = FALSE, arraycreate(source_ip)), xdm.source.host.ipv6_public_addresses = if(is_known_private_ipv6(source_ip) = FALSE, arraycreate(source_ip)), xdm.source.port = to_number(source_port), xdm.event.description = msg, xdm.event.format = if(_raw_log ~= "\<\d+\>1", "RFC-5424", _raw_log ~= "\<\d+\>", "RFC-3164"), xdm.event.log_level = if( severity = "0", XDM_CONST.LOG_LEVEL_EMERGENCY , severity = "1", XDM_CONST.LOG_LEVEL_ALERT , severity = "2", XDM_CONST.LOG_LEVEL_CRITICAL, severity = "3", XDM_CONST.LOG_LEVEL_ERROR, severity = "4", XDM_CONST.LOG_LEVEL_WARNING, severity = "5", XDM_CONST.LOG_LEVEL_NOTICE, severity = "6", XDM_CONST.LOG_LEVEL_INFORMATIONAL, severity = "7", XDM_CONST.LOG_LEVEL_DEBUG, severity), xdm.target.process.executable.path = path, xdm.source.host.mac_addresses = arraycreate(coalesce(mac_address ,""));