diff --git a/docs/sources/Cisco/index.md b/docs/sources/Cisco/index.md index 95425f4..df106a3 100644 --- a/docs/sources/Cisco/index.md +++ b/docs/sources/Cisco/index.md @@ -120,6 +120,7 @@ Including Legacy FWSM and PIX | sourcetype | notes | |----------------|---------------------------------------------------------------------------------------------------------| | cisco:asa | cisco FTD Firepower will also use this source type except those noted below | +| cisco:ftd | cisco FTD Firepower will also use this source type except those noted below | | cisco:fwsm | Splunk has | | cisco:pix | cisco PIX will also use this source type except those noted below | | cisco:firepower:syslog | FTD Unified events see https://www.cisco.com/c/en/us/td/docs/security/firepower/Syslogs/b_fptd_syslog_guide.pdf | @@ -131,7 +132,8 @@ Including Legacy FWSM and PIX | cisco_asa | cisco:asa | netfw | none | | cisco_fwsm | cisco:fwsm | netfw | none | | cisco_pix | cisco:pix | netfw | none | -| cisco_ftd | cisco:firepower:syslog | netfw | none | +| cisco_firepower | cisco:firepower:syslog | netids | none | +| cisco_ftd | cisco:ftd | netfw | none | ### Filter type diff --git a/package/etc/conf.d/filters/cisco/firepower.conf b/package/etc/conf.d/filters/cisco/firepower.conf new file mode 100644 index 0000000..715ca5c --- /dev/null +++ b/package/etc/conf.d/filters/cisco/firepower.conf @@ -0,0 +1,3 @@ +filter f_cisco_firepower { + program('SFIMS'); +}; diff --git a/package/etc/conf.d/log_paths/lp-cisco_asa.conf.tmpl b/package/etc/conf.d/log_paths/lp-cisco_asa.conf.tmpl index 2668057..36ec3ee 100644 --- a/package/etc/conf.d/log_paths/lp-cisco_asa.conf.tmpl +++ b/package/etc/conf.d/log_paths/lp-cisco_asa.conf.tmpl @@ -24,7 +24,7 @@ log { filter(f_cisco_ftd); rewrite { set("cisco_ftd", value("fields.sc4s_vendor_product")); - r_set_splunk_dest_default(sourcetype("cisco:firepower:syslog")) + r_set_splunk_dest_default(sourcetype("cisco:ftd")) }; parser {p_add_context_splunk(key("cisco_ftd")); }; parser (compliance_meta_by_source); diff --git a/package/etc/conf.d/log_paths/lp-cisco_firepower.conf.tmpl b/package/etc/conf.d/log_paths/lp-cisco_firepower.conf.tmpl new file mode 100644 index 0000000..d820b03 --- /dev/null +++ b/package/etc/conf.d/log_paths/lp-cisco_firepower.conf.tmpl @@ -0,0 +1,63 @@ +# cisco_firepower +{{- /* The following provides a unique port source configuration if env var(s) are set */}} +{{- $context := dict "port_id" "CISCO_FIREPOWER" "parser" "rfc3164" }} +{{- tmpl.Exec "t/source_network.t" $context }} + +log { + junction { +{{- if or (or (getenv (print "SC4S_LISTEN_CISCO_FIREPOWER_TCP_PORT")) (getenv (print "SC4S_LISTEN_CISCO_FIREPOWER_UDP_PORT"))) (getenv (print "SC4S_LISTEN_CISCO_FIREPOWER_TLS_PORT")) }} + channel { + # Listen on the specified dedicated port(s) for CISCO_FIREPOWER traffic + source (s_CISCO_FIREPOWER); + flags (final); + }; +{{- end}} + channel { + # Listen on the default port (typically 514) for CISCO_FIREPOWER traffic + source (s_DEFAULT); + filter(f_cisco_firepower); + flags(final); + }; + }; + + if { + filter{program("SFIMS")}; + rewrite { + set("cisco_firepower", value("fields.sc4s_vendor_product")); + r_set_splunk_dest_default(sourcetype("cisco:firepower:syslog")) + }; + parser { p_add_context_splunk(key("cisco_firepower")); }; + parser (compliance_meta_by_source); + rewrite { set("$(template ${.splunk.sc4s_template} $(template t_hdr_msg))" value("MSG")); }; + } else { + rewrite { + set("cisco_firepower", value("fields.sc4s_vendor_product")); + subst("^[^\t]+\t", "", value("MESSAGE"), flags("global")); + set("${PROGRAM}", value(".PROGRAM")); + subst('^\/(?:[^\/]+\/)+', "" , value(".PROGRAM")); + r_set_splunk_dest_default(sourcetype("cisco_firepower:${.PROGRAM}"), source("program:${.PROGRAM}")) + }; + parser { p_add_context_splunk(key("cisco_firepower")); }; + parser (compliance_meta_by_source); + rewrite { set("$(template ${.splunk.sc4s_template} $(template t_legacy_hdr_msg))" value("MSG")); }; + }; + + +{{- if or (conv.ToBool (getenv "SC4S_DEST_SPLUNK_HEC_GLOBAL" "yes")) (conv.ToBool (getenv "SC4S_DEST_CISCO_FIREPOWER_HEC" "no")) }} + destination(d_hec); +{{- end}} + +{{- if or (conv.ToBool (getenv "SC4S_ARCHIVE_GLOBAL" "no")) (conv.ToBool (getenv "SC4S_ARCHIVE_CISCO_FIREPOWER" "no")) }} + destination(d_archive); +{{- end}} + +{{- if (print (getenv "SC4S_DEST_GLOBAL_ALTERNATES")) }} + {{ getenv "SC4S_DEST_GLOBAL_ALTERNATES" | regexp.ReplaceLiteral "^" "destination(" | regexp.ReplaceLiteral "[, ]+" ");\n destination(" }}); +{{- end }} + +{{- if (print (getenv "SC4S_DEST_CISCO_FIREPOWER_ALTERNATES")) }} + {{ getenv "SC4S_DEST_CISCO_FIREPOWER_ALTERNATES" | regexp.ReplaceLiteral "^" "destination(" | regexp.ReplaceLiteral "[, ]+" ");\n destination(" }}); +{{- end }} + + flags(flow-control,final); +}; diff --git a/package/etc/context_templates/splunk_metadata.csv.example b/package/etc/context_templates/splunk_metadata.csv.example index 5887ca9..5e7c7f1 100644 --- a/package/etc/context_templates/splunk_metadata.csv.example +++ b/package/etc/context_templates/splunk_metadata.csv.example @@ -23,6 +23,7 @@ Cisco_C100V Email Security Virtual Appliance_ESA_CONSOLIDATED_LOG_EVENT,sc4s_tem Cisco_C100V Email Security Virtual Appliance_ESA_CONSOLIDATED_LOG_EVENT,source,esa:consolidated Cisco_C100V Email Security Virtual Appliance_ESA_CONSOLIDATED_LOG_EVENT,sourcetype,cisco:esa:cef cisco_esa,index,email +cisco_firepower,index,netids cisco_ftd,index,netfw cisco_fwsm,index,netfw cisco_ios,index,netops diff --git a/tests/test_cisco_asa.py b/tests/test_cisco_asa.py index 6657876..6ec0170 100644 --- a/tests/test_cisco_asa.py +++ b/tests/test_cisco_asa.py @@ -17,7 +17,9 @@ # Apr 15 2017 00:21:14 192.168.12.1 : %ASA-5-111010: User 'john', running 'CLI' from IP 0.0.0.0, executed 'dir disk0:/dap.xml' # Apr 15 2017 00:22:27 192.168.12.1 : %ASA-4-313005: No matching connection for ICMP error message: icmp src outside:81.24.28.226 dst inside:72.142.17.10 (type 3, code 0) on outside interface. Original IP payload: udp src 72.142.17.10/40998 dst 194.153.237.66/53. # Apr 15 2017 00:22:42 192.168.12.1 : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/8949 to outside:72.142.18.38/23 -def test_cisco_asa_traditional(record_property, setup_wordlist, setup_splunk, setup_sc4s): +def test_cisco_asa_traditional( + record_property, setup_wordlist, setup_splunk, setup_sc4s +): host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) dt = datetime.datetime.now() @@ -27,12 +29,15 @@ def test_cisco_asa_traditional(record_property, setup_wordlist, setup_splunk, se epoch = epoch[:-7] mt = env.from_string( - "{{ mark }} {{ bsd }} {{ host }} : %ASA-3-003164: TCP access denied by ACL from 179.236.133.160/3624 to outside:72.142.18.38/23\n") + "{{ mark }} {{ bsd }} {{ host }} : %ASA-3-003164: TCP access denied by ACL from 179.236.133.160/3624 to outside:72.142.18.38/23\n" + ) message = mt.render(mark="<111>", bsd=bsd, host=host) sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) - st = env.from_string("search _time={{ epoch }} index=netfw host=\"{{ host }}\" sourcetype=\"cisco:asa\" \"%ASA-3-003164\"") + st = env.from_string( + 'search _time={{ epoch }} index=netfw host="{{ host }}" sourcetype="cisco:asa" "%ASA-3-003164"' + ) search = st.render(epoch=epoch, host=host) resultCount, eventCount = splunk_single(setup_splunk, search) @@ -43,8 +48,11 @@ def test_cisco_asa_traditional(record_property, setup_wordlist, setup_splunk, se assert resultCount == 1 + # <164>Jan 31 2020 17:24:03: %ASA-4-402119: IPSEC: Received an ESP packet (SPI= 0x0C190BF9, sequence number= 0x598243) from 192.0.0.1 (user= 192.0.0.1) to 192.0.0.2 that failed anti-replay checking. -def test_cisco_asa_traditional_nohost(record_property, setup_wordlist, setup_splunk, setup_sc4s): +def test_cisco_asa_traditional_nohost( + record_property, setup_wordlist, setup_splunk, setup_sc4s +): host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) dt = datetime.datetime.now() @@ -54,12 +62,15 @@ def test_cisco_asa_traditional_nohost(record_property, setup_wordlist, setup_spl epoch = epoch[:-7] mt = env.from_string( - "{{ mark }} {{ bsd }}: %ASA-4-402119: IPSEC: Received an ESP packet (SPI= 0x0C190BF9, sequence number= 0x598243) from {{host}} (user= 192.0.0.1) to 192.0.0.2 that failed anti-replay checking.\n") + "{{ mark }} {{ bsd }}: %ASA-4-402119: IPSEC: Received an ESP packet (SPI= 0x0C190BF9, sequence number= 0x598243) from {{host}} (user= 192.0.0.1) to 192.0.0.2 that failed anti-replay checking.\n" + ) message = mt.render(mark="<111>", bsd=bsd, host=host) sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) - st = env.from_string("search _time={{ epoch }} index=netfw sourcetype=\"cisco:asa\" \"%ASA-4-402119\" \"{{ host }}\"") + st = env.from_string( + 'search _time={{ epoch }} index=netfw sourcetype="cisco:asa" "%ASA-4-402119" "{{ host }}"' + ) search = st.render(epoch=epoch, host=host) resultCount, eventCount = splunk_single(setup_splunk, search) @@ -75,7 +86,7 @@ def test_cisco_asa_traditional_nohost(record_property, setup_wordlist, setup_spl def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_sc4s): host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) -# Get UTC-based 'dt' time structure + # Get UTC-based 'dt' time structure dt = datetime.datetime.now(datetime.timezone.utc) iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) @@ -85,12 +96,15 @@ def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_ epoch = epoch[:-7] mt = env.from_string( - "{{ mark }} {{ iso }}Z {{ host }} : %ASA-3-005424: TCP access denied by ACL from 179.236.133.160/5424 to outside:72.142.18.38/23 epoch={{ epoch }}\n") + "{{ mark }} {{ iso }}Z {{ host }} : %ASA-3-005424: TCP access denied by ACL from 179.236.133.160/5424 to outside:72.142.18.38/23 epoch={{ epoch }}\n" + ) message = mt.render(mark="<166>", iso=iso, epoch=epoch, host=host) sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) - st = env.from_string("search _time={{ epoch }} index=netfw host=\"{{ host }}\" sourcetype=\"cisco:asa\" \"%ASA-3-005424\"") + st = env.from_string( + 'search _time={{ epoch }} index=netfw host="{{ host }}" sourcetype="cisco:asa" "%ASA-3-005424"' + ) search = st.render(epoch=epoch, host=host) resultCount, eventCount = splunk_single(setup_splunk, search) @@ -101,11 +115,12 @@ def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_ assert resultCount == 1 -#<118>2020-02-04T11:00:54Z %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity + +# <118>2020-02-04T11:00:54Z %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity def test_cisco_ftd(record_property, setup_wordlist, setup_splunk, setup_sc4s): host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) -# Get UTC-based 'dt' time structure + # Get UTC-based 'dt' time structure dt = datetime.datetime.now(datetime.timezone.utc) iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) @@ -115,12 +130,15 @@ def test_cisco_ftd(record_property, setup_wordlist, setup_splunk, setup_sc4s): epoch = epoch[:-7] mt = env.from_string( - "{{ mark }} {{ iso }}Z {{ host }} : %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity\n") + "{{ mark }} {{ iso }}Z {{ host }} : %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity\n" + ) message = mt.render(mark="<166>", iso=iso, epoch=epoch, host=host) sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) - st = env.from_string("search _time={{ epoch }} index=netfw host=\"{{ host }}\" sourcetype=\"cisco:firepower:syslog\"") + st = env.from_string( + 'search _time={{ epoch }} index=netfw host="{{ host }}" sourcetype="cisco:ftd"' + ) search = st.render(epoch=epoch, host=host) resultCount, eventCount = splunk_single(setup_splunk, search) @@ -129,4 +147,4 @@ def test_cisco_ftd(record_property, setup_wordlist, setup_splunk, setup_sc4s): record_property("resultCount", resultCount) record_property("message", message) - assert resultCount == 1 \ No newline at end of file + assert resultCount == 1 diff --git a/tests/test_cisco_firepower.py b/tests/test_cisco_firepower.py new file mode 100644 index 0000000..c0a6b6b --- /dev/null +++ b/tests/test_cisco_firepower.py @@ -0,0 +1,44 @@ +# Copyright 2019 Splunk, Inc. +# +# Use of this source code is governed by a BSD-2-clause-style +# license that can be found in the LICENSE-BSD2 file or at +# https://opensource.org/licenses/BSD-2-Clause +import random + +from jinja2 import Environment + +from .sendmessage import * +from .splunkutils import * +from .timeutils import * + +env = Environment() + + +def test_cisco_firepower(record_property, setup_wordlist, setup_splunk, setup_sc4s): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + dt = datetime.datetime.now() + iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) + + # Tune time functions + epoch = epoch[:-7] + + mt = env.from_string( + "{{ mark }} {{ bsd }} {{ host }} SFIMS: Protocol: TCP, SrcIP: 1.1.1.1, OriginalClientIP: ::, DstIP: 2.2.2.2, SrcPort: 47097, DstPort: 33897, TCPFlags: 0x0, DE: Primary Detection Engine (asdf912a-ad91-d192-adsf-12aadf32910d), Policy: device-policy, ConnectType: Start, AccessControlRuleName: EU-NoLicense-Block-All, AccessControlRuleAction: Block with reset, Prefilter Policy: Default Prefilter Policy, InitiatorPackets: 1, ResponderPackets: 0, InitiatorBytes: 54, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity, DNSResponseType: No Error, Sinkhole: Unknown, URLCategory: Unknown, URLReputation: Risk unknown\n" + ) + message = mt.render(mark="<111>", bsd=bsd, host=host) + + sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) + + st = env.from_string( + 'search _time={{ epoch }} index=netids host="{{ host }}" sourcetype="cisco:firepower:syslog"' + ) + search = st.render(epoch=epoch, host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1