From b0e4095cae10dfca6e536a0d110492ee5bd2a2ae Mon Sep 17 00:00:00 2001 From: byrsapty Date: Fri, 28 Aug 2026 13:22:41 +0300 Subject: [PATCH] Add A10 ACOS (LSN/CGNAT + BGP) pipeline rules from real captured syslog 8 new rules (vendor=a10) wired into Network Equipment Parsing: LSN TCP/Session/ICMP per-user quota exceeded (critical - real service impact, drops new connections for that subscriber), BGP-4-MAXPFX prefix-limit warning, and admin session open/close/timeout/auth-success (aXAPI and CLI both covered by one pattern each). Unlike the CSV-report-derived rules, these are built directly from real captured A10 log output the user provided, so confidence is higher - closer to the accel-ppp rules' provenance. Multi-entry LSN lines (several 'ip(count)' pairs in one quota-exceeded message) only have their first pair extracted into fields; the full list stays in the raw message. Not live-verified - the user is bringing the target system up themselves this time rather than through the test container used earlier in this branch of work. --- pipelines/pipeline1_network.json | 4 ++-- rules/rule85_a10_lsn_tcp_quota_exceeded.json | 5 +++++ rules/rule86_a10_lsn_session_quota_exceeded.json | 5 +++++ rules/rule87_a10_lsn_icmp_quota_exceeded.json | 5 +++++ rules/rule88_a10_bgp_maxpfx_warning.json | 5 +++++ rules/rule89_a10_session_opened.json | 5 +++++ rules/rule90_a10_session_closed.json | 5 +++++ rules/rule91_a10_session_timeout.json | 5 +++++ rules/rule92_a10_auth_success.json | 5 +++++ 9 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 rules/rule85_a10_lsn_tcp_quota_exceeded.json create mode 100644 rules/rule86_a10_lsn_session_quota_exceeded.json create mode 100644 rules/rule87_a10_lsn_icmp_quota_exceeded.json create mode 100644 rules/rule88_a10_bgp_maxpfx_warning.json create mode 100644 rules/rule89_a10_session_opened.json create mode 100644 rules/rule90_a10_session_closed.json create mode 100644 rules/rule91_a10_session_timeout.json create mode 100644 rules/rule92_a10_auth_success.json diff --git a/pipelines/pipeline1_network.json b/pipelines/pipeline1_network.json index 63e592d..3a96e4b 100644 --- a/pipelines/pipeline1_network.json +++ b/pipelines/pipeline1_network.json @@ -1,5 +1,5 @@ { "title": "Network Equipment Parsing", - "description": "Parses Juniper, BDCOM EPON/GPON OLT, ZTE OLT, and D-Link syslog, plus a universal critical-severity fallback", - "source": "pipeline \"Network Equipment Parsing\"\nstage 0 match either\n rule \"juniper_ntp_unreachable\";\n rule \"juniper_ssh_login_success\";\n rule \"juniper_ssh_login_failed_tagged\";\n rule \"juniper_ssh_failed_password\";\n rule \"juniper_ui_configuration_error\";\n rule \"juniper_chassis_alarm\";\n rule \"olt_privilege_mode\";\n rule \"olt_cli_logout\";\n rule \"olt_ip_arp_moved\";\n rule \"olt_config_write\";\n rule \"bdcom_epon_dying_gasp\";\n rule \"bdcom_epon_onu_config_error\";\n rule \"bdcom_epon_hal_driver_error\";\n rule \"bdcom_epon_onu_info_failed\";\n rule \"bdcom_epon_onu_authenticated\";\n rule \"bdcom_epon_onu_registered\";\n rule \"bdcom_epon_onu_deregistered\";\n rule \"bdcom_epon_oam_status\";\n rule \"bdcom_olt_cli_login\";\n rule \"bdcom_epon_config_saved\";\n rule \"bdcom_epon_interface_link_state\";\n rule \"bdcom_gpon_config_saved\";\n rule \"bdcom_gpon_dying_gasp\";\n rule \"bdcom_gpon_onu_offline\";\n rule \"bdcom_gpon_onu_activate_failed\";\n rule \"bdcom_gpon_onu_disabled\";\n rule \"bdcom_gpon_onu_discovered\";\n rule \"bdcom_gpon_onu_activated\";\n rule \"bdcom_gpon_onu_deactivated\";\n rule \"zte_gpon_dying_gasp\";\n rule \"zte_gpon_onu_signal_degraded\";\n rule \"zte_gpon_onu_lan_los\";\n rule \"zte_epon_dying_gasp\";\n rule \"zte_epon_onu_offline\";\n rule \"zte_gpon_olt_pon_los\";\n rule \"zte_optical_low_power\";\n rule \"zte_power_over_voltage\";\n rule \"zte_alarm_cleared\";\n rule \"zte_cli_login\";\n rule \"zte_cli_logout\";\n rule \"juniper_ddos_violation_set\";\n rule \"juniper_ddos_violation_clear\";\n rule \"juniper_psu_failure\";\n rule \"juniper_memory_parity_error\";\n rule \"juniper_optical_low_power\";\n rule \"juniper_qsfp_eeprom_failed\";\n rule \"juniper_lacp_timeout\";\n rule \"juniper_link_down\";\n rule \"juniper_lag_state_change\";\n rule \"juniper_snmp_auth_violation\";\n rule \"juniper_asic_error\";\n rule \"juniper_bgp_session_reset\";\n rule \"juniper_bgp_addr_not_found\";\n rule \"juniper_ntpd_resource_error\";\n rule \"juniper_ssh_too_many_failures\";\n rule \"juniper_config_commit\";\n rule \"juniper_mgmt_login\";\n rule \"dlink_system_reboot\";\n rule \"dlink_optical_alarm\";\n rule \"dlink_optical_recovered\";\n rule \"dlink_interface_link_state\";\n rule \"dlink_lag_state_change\";\n rule \"dlink_gbic_detected\";\n rule \"dlink_ntp_sync\";\n rule \"dlink_management_ip_changed\";\n rule \"dlink_telnet_login\";\n rule \"dlink_telnet_logout\";\n rule \"dlink_config_saved\";\n rule \"generic_critical_severity\";\nend" + "description": "Parses Juniper, BDCOM EPON/GPON OLT, ZTE OLT, D-Link, and A10 ACOS syslog, plus a universal critical-severity fallback", + "source": "pipeline \"Network Equipment Parsing\"\nstage 0 match either\n rule \"juniper_ntp_unreachable\";\n rule \"juniper_ssh_login_success\";\n rule \"juniper_ssh_login_failed_tagged\";\n rule \"juniper_ssh_failed_password\";\n rule \"juniper_ui_configuration_error\";\n rule \"juniper_chassis_alarm\";\n rule \"olt_privilege_mode\";\n rule \"olt_cli_logout\";\n rule \"olt_ip_arp_moved\";\n rule \"olt_config_write\";\n rule \"bdcom_epon_dying_gasp\";\n rule \"bdcom_epon_onu_config_error\";\n rule \"bdcom_epon_hal_driver_error\";\n rule \"bdcom_epon_onu_info_failed\";\n rule \"bdcom_epon_onu_authenticated\";\n rule \"bdcom_epon_onu_registered\";\n rule \"bdcom_epon_onu_deregistered\";\n rule \"bdcom_epon_oam_status\";\n rule \"bdcom_olt_cli_login\";\n rule \"bdcom_epon_config_saved\";\n rule \"bdcom_epon_interface_link_state\";\n rule \"bdcom_gpon_config_saved\";\n rule \"bdcom_gpon_dying_gasp\";\n rule \"bdcom_gpon_onu_offline\";\n rule \"bdcom_gpon_onu_activate_failed\";\n rule \"bdcom_gpon_onu_disabled\";\n rule \"bdcom_gpon_onu_discovered\";\n rule \"bdcom_gpon_onu_activated\";\n rule \"bdcom_gpon_onu_deactivated\";\n rule \"zte_gpon_dying_gasp\";\n rule \"zte_gpon_onu_signal_degraded\";\n rule \"zte_gpon_onu_lan_los\";\n rule \"zte_epon_dying_gasp\";\n rule \"zte_epon_onu_offline\";\n rule \"zte_gpon_olt_pon_los\";\n rule \"zte_optical_low_power\";\n rule \"zte_power_over_voltage\";\n rule \"zte_alarm_cleared\";\n rule \"zte_cli_login\";\n rule \"zte_cli_logout\";\n rule \"juniper_ddos_violation_set\";\n rule \"juniper_ddos_violation_clear\";\n rule \"juniper_psu_failure\";\n rule \"juniper_memory_parity_error\";\n rule \"juniper_optical_low_power\";\n rule \"juniper_qsfp_eeprom_failed\";\n rule \"juniper_lacp_timeout\";\n rule \"juniper_link_down\";\n rule \"juniper_lag_state_change\";\n rule \"juniper_snmp_auth_violation\";\n rule \"juniper_asic_error\";\n rule \"juniper_bgp_session_reset\";\n rule \"juniper_bgp_addr_not_found\";\n rule \"juniper_ntpd_resource_error\";\n rule \"juniper_ssh_too_many_failures\";\n rule \"juniper_config_commit\";\n rule \"juniper_mgmt_login\";\n rule \"dlink_system_reboot\";\n rule \"dlink_optical_alarm\";\n rule \"dlink_optical_recovered\";\n rule \"dlink_interface_link_state\";\n rule \"dlink_lag_state_change\";\n rule \"dlink_gbic_detected\";\n rule \"dlink_ntp_sync\";\n rule \"dlink_management_ip_changed\";\n rule \"dlink_telnet_login\";\n rule \"dlink_telnet_logout\";\n rule \"dlink_config_saved\";\n rule \"a10_lsn_tcp_quota_exceeded\";\n rule \"a10_lsn_session_quota_exceeded\";\n rule \"a10_lsn_icmp_quota_exceeded\";\n rule \"a10_bgp_maxpfx_warning\";\n rule \"a10_session_opened\";\n rule \"a10_session_closed\";\n rule \"a10_session_timeout\";\n rule \"a10_auth_success\";\n rule \"generic_critical_severity\";\nend" } diff --git a/rules/rule85_a10_lsn_tcp_quota_exceeded.json b/rules/rule85_a10_lsn_tcp_quota_exceeded.json new file mode 100644 index 0000000..9438fd5 --- /dev/null +++ b/rules/rule85_a10_lsn_tcp_quota_exceeded.json @@ -0,0 +1,5 @@ +{ + "title": "a10_lsn_tcp_quota_exceeded", + "description": "A10 ACOS LSN (Large Scale NAT/CGNAT): a subscriber hit their per-user TCP session quota - real service impact (new TCP connections for that user get dropped until it frees up). Built from real captured A10 syslog output. Note: a line can list multiple 'ip(count)' pairs (one per affected user in that batch) - this rule captures only the first for triage; the full list stays in the raw message.", + "source": "rule \"a10_lsn_tcp_quota_exceeded\"\nwhen\n contains(to_string($message.message), \"LSN: TCP user-quota exceeded\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"lsn_tcp_quota_exceeded\");\n set_field(\"severity_tag\", \"critical\");\n let m = regex(\"User\\\\(Count\\\\) (\\\\S+)\\\\((\\\\d+)\\\\)\", to_string($message.message), [\"ip\",\"count\"]);\n set_field(\"lsn_user_ip\", m[\"ip\"]);\n set_field(\"lsn_user_count\", to_long(m[\"count\"]));\nend" +} diff --git a/rules/rule86_a10_lsn_session_quota_exceeded.json b/rules/rule86_a10_lsn_session_quota_exceeded.json new file mode 100644 index 0000000..d28f650 --- /dev/null +++ b/rules/rule86_a10_lsn_session_quota_exceeded.json @@ -0,0 +1,5 @@ +{ + "title": "a10_lsn_session_quota_exceeded", + "description": "A10 ACOS LSN: a subscriber hit their per-user total session quota (all protocols) - real service impact. Built from real captured A10 syslog output. Same first-entry-only extraction caveat as a10_lsn_tcp_quota_exceeded for multi-user lines.", + "source": "rule \"a10_lsn_session_quota_exceeded\"\nwhen\n contains(to_string($message.message), \"LSN: Session user-quota exceeded\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"lsn_session_quota_exceeded\");\n set_field(\"severity_tag\", \"critical\");\n let m = regex(\"User\\\\(Count\\\\) (\\\\S+)\\\\((\\\\d+)\\\\)\", to_string($message.message), [\"ip\",\"count\"]);\n set_field(\"lsn_user_ip\", m[\"ip\"]);\n set_field(\"lsn_user_count\", to_long(m[\"count\"]));\nend" +} diff --git a/rules/rule87_a10_lsn_icmp_quota_exceeded.json b/rules/rule87_a10_lsn_icmp_quota_exceeded.json new file mode 100644 index 0000000..d0cb451 --- /dev/null +++ b/rules/rule87_a10_lsn_icmp_quota_exceeded.json @@ -0,0 +1,5 @@ +{ + "title": "a10_lsn_icmp_quota_exceeded", + "description": "A10 ACOS LSN: a subscriber hit their per-user ICMP quota - rarer than TCP/Session quota hits but same real service impact. Built from real captured A10 syslog output.", + "source": "rule \"a10_lsn_icmp_quota_exceeded\"\nwhen\n contains(to_string($message.message), \"LSN: ICMP user-quota exceeded\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"lsn_icmp_quota_exceeded\");\n set_field(\"severity_tag\", \"critical\");\n let m = regex(\"User\\\\(Count\\\\) (\\\\S+)\\\\((\\\\d+)\\\\)\", to_string($message.message), [\"ip\",\"count\"]);\n set_field(\"lsn_user_ip\", m[\"ip\"]);\n set_field(\"lsn_user_count\", to_long(m[\"count\"]));\nend" +} diff --git a/rules/rule88_a10_bgp_maxpfx_warning.json b/rules/rule88_a10_bgp_maxpfx_warning.json new file mode 100644 index 0000000..7839c68 --- /dev/null +++ b/rules/rule88_a10_bgp_maxpfx_warning.json @@ -0,0 +1,5 @@ +{ + "title": "a10_bgp_maxpfx_warning", + "description": "A10 Router process: BGP peer approaching its configured max-prefix limit (IPv4 Unicast) - early warning before the session would be reset for exceeding it. Built from real captured A10 syslog output.", + "source": "rule \"a10_bgp_maxpfx_warning\"\nwhen\n contains(to_string($message.message), \"BGP-4-MAXPFX\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"bgp_maxpfx_warning\");\n set_field(\"severity_tag\", \"warning\");\n let m = regex(\"from (\\\\S+) \\\\(IPv4 Unicast\\\\): reaches (\\\\d+), max (\\\\d+)\", to_string($message.message), [\"peer\",\"count\",\"max\"]);\n set_field(\"bgp_peer\", m[\"peer\"]);\n set_field(\"bgp_prefix_count\", to_long(m[\"count\"]));\n set_field(\"bgp_prefix_max\", to_long(m[\"max\"]));\nend" +} diff --git a/rules/rule89_a10_session_opened.json b/rules/rule89_a10_session_opened.json new file mode 100644 index 0000000..2ade244 --- /dev/null +++ b/rules/rule89_a10_session_opened.json @@ -0,0 +1,5 @@ +{ + "title": "a10_session_opened", + "description": "A10: admin session opened (covers both 'aXAPI session' and 'cli session' wording - same event, different access method). Built from real captured A10 syslog output.", + "source": "rule \"a10_session_opened\"\nwhen\n contains(to_string($message.message), \"session for user\") && contains(to_string($message.message), \"has been opened\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"session_opened\");\n let m = regex(\"session for user \\\\\"(\\\\S+)\\\\\" from (\\\\S+) has been opened\\\\. Session ID assigned is (\\\\d+)\", to_string($message.message), [\"user\",\"src_ip\",\"session_id\"]);\n set_field(\"a10_user\", m[\"user\"]);\n set_field(\"src_ip\", m[\"src_ip\"]);\n set_field(\"a10_session_id\", m[\"session_id\"]);\nend" +} diff --git a/rules/rule90_a10_session_closed.json b/rules/rule90_a10_session_closed.json new file mode 100644 index 0000000..0a9302d --- /dev/null +++ b/rules/rule90_a10_session_closed.json @@ -0,0 +1,5 @@ +{ + "title": "a10_session_closed", + "description": "A10: admin session closed normally. Built from real captured A10 syslog output.", + "source": "rule \"a10_session_closed\"\nwhen\n contains(to_string($message.message), \"Session ID\") && contains(to_string($message.message), \"is now closed\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"session_closed\");\n let m = regex(\"Session ID (\\\\d+) is now closed\", to_string($message.message), [\"session_id\"]);\n set_field(\"a10_session_id\", m[\"session_id\"]);\nend" +} diff --git a/rules/rule91_a10_session_timeout.json b/rules/rule91_a10_session_timeout.json new file mode 100644 index 0000000..49a5295 --- /dev/null +++ b/rules/rule91_a10_session_timeout.json @@ -0,0 +1,5 @@ +{ + "title": "a10_session_timeout", + "description": "A10: admin session timed out from inactivity (the detailed line naming session id/user/src_ip - the generic preceding 'Session timed out' line is a duplicate summary of the same event and is deliberately left unclassified). Built from real captured A10 syslog output.", + "source": "rule \"a10_session_timeout\"\nwhen\n contains(to_string($message.message), \"has timed out\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"session_timeout\");\n let m = regex(\"Session ID (\\\\d+) for user \\\\\"(\\\\S+)\\\\\" from (\\\\S+) has timed out\", to_string($message.message), [\"session_id\",\"user\",\"src_ip\"]);\n set_field(\"a10_session_id\", m[\"session_id\"]);\n set_field(\"a10_user\", m[\"user\"]);\n set_field(\"src_ip\", m[\"src_ip\"]);\nend" +} diff --git a/rules/rule92_a10_auth_success.json b/rules/rule92_a10_auth_success.json new file mode 100644 index 0000000..b9c490e --- /dev/null +++ b/rules/rule92_a10_auth_success.json @@ -0,0 +1,5 @@ +{ + "title": "a10_auth_success", + "description": "A10: local authentication succeeded (fires alongside a10_session_opened for the same login - kept separate since it's a distinct audit line). Built from real captured A10 syslog output.", + "source": "rule \"a10_auth_success\"\nwhen\n contains(to_string($message.message), \"Local authentication successful\")\nthen\n set_field(\"vendor\", \"a10\");\n set_field(\"event_type\", \"auth_success\");\n let m = regex(\"Local authentication successful \\\\(user: (\\\\S+)\\\\)\", to_string($message.message), [\"user\"]);\n set_field(\"a10_user\", m[\"user\"]);\nend" +}