diff --git a/docs/sources/Cisco/index.md b/docs/sources/Cisco/index.md index 9467fa2..9fccf8d 100644 --- a/docs/sources/Cisco/index.md +++ b/docs/sources/Cisco/index.md @@ -375,4 +375,57 @@ Use the following search to validate events are present index= sourcetype=cisco:ucm ``` -Verify timestamp, and host values match as expected \ No newline at end of file +Verify timestamp, and host values match as expected + +## Product - WSA + +| Ref | Link | +|----------------|---------------------------------------------------------------------------------------------------------| +| Splunk Add-on | https://splunkbase.splunk.com/app/1747/ | +| Product Manual | https://www.cisco.com/c/en/us/td/docs/security/wsa/wsa11-7/user_guide/b_WSA_UserGuide_11_7.html | + +* Update ``vi /opt/sc4s/local/context/vendor_product_by_source.conf `` update the host or ip mask for ``f_cisco_wsa`` to identiy the wsa events prior to WSA v11.7 and ``f_cisco_wsa11_7`` to identify the events since WSA v11.7. + + +### Sourcetypes + +| cisco:wsa:l4tm | The L4TM logs of Cisco IronPort WSA record sites added to the L4TM block and allow lists. | +| cisco:wsa:squid | The access logs of Cisco IronPort WSA version prior to 11.7 record Web Proxy client history in squid. | +| cisco:wsa:squid:new | The access logs of Cisco IronPort WSA version since 11.7 record Web Proxy client history in squid. | + +### Sourcetype and Index Configuration + +| key | sourcetype | index | notes | +|----------------|----------------|----------------|----------------| +| cisco_wsa_l4tm | cisco:wsa:l4tm | netops | None | +| cisco_wsa_squid | cisco:wsa:squid | netops | None | +| cisco_wsa_squid_new | cisco:wsa:squid:new | netops | None | + +### Filter type + +IP, Netmask or Host + +### Setup and Configuration + +* Install the Splunk Add-on on the search head(s) for the user communities interested in this data source. If SC4S is exclusively used the addon is not required on the indexer. +* WSA Follow vendor configuration steps per Product Manual. +* Ensure host and timestamp are included. + +### Options + +| Variable | default | description | +|----------------|----------------|----------------| +| SC4S_LISTEN_CISCO_WSA_TCP_PORT | empty string | Enable a TCP port for this specific vendor product using the number defined | +| SC4S_LISTEN_CISCO_WSA_UDP_PORT | empty string | Enable a UDP port for this specific vendor product using the number defined | +| SC4S_ARCHIVE_CISCO_WSA | no | Enable archive to disk for this specific source | +| SC4S_DEST_CISCO_WSA_HEC | no | When Splunk HEC is disabled globally set to yes to enable this specific source | + +### Verification + +Use the following search to validate events are present + +``` +index=netops sourcetype=cisco:wsa:* +``` + +Verify timestamp, and host values match as expected \ No newline at end of file diff --git a/package/etc/conf.d/filters/cisco/wsa.conf b/package/etc/conf.d/filters/cisco/wsa.conf new file mode 100644 index 0000000..6f86606 --- /dev/null +++ b/package/etc/conf.d/filters/cisco/wsa.conf @@ -0,0 +1,7 @@ +filter f_cisco_wsa11_7{ + match("cisco_wsa11_7", value("fields.sc4s_vendor_product") type(glob)); +}; + +filter f_cisco_wsa{ + match('cisco_wsa*', value("fields.sc4s_vendor_product") type(glob)); +}; \ No newline at end of file diff --git a/package/etc/conf.d/log_paths/lp-cisco_wsa.conf.tmpl b/package/etc/conf.d/log_paths/lp-cisco_wsa.conf.tmpl new file mode 100644 index 0000000..9403f7d --- /dev/null +++ b/package/etc/conf.d/log_paths/lp-cisco_wsa.conf.tmpl @@ -0,0 +1,102 @@ +# Cisco WSA +{{- /* The following provides a unique port source configuration if env var(s) are set */}} +{{- $context := dict "port_id" "CISCO_WSA" "parser" "rfc3164" }} +{{- tmpl.Exec "t/source_network.t" $context }} + +log{ + junction { +{{- if or (or (getenv (print "SC4S_LISTEN_CISCO_WSA_TCP_PORT")) (getenv (print "SC4S_LISTEN_CISCO_WSA_UDP_PORT"))) (getenv (print "SC4S_LISTEN_CISCO_WSA_TLS_PORT")) }} + channel { + # Listen on the specified dedicated port(s) for CISCO_WSA traffic + source (s_CISCO_WSA); + flags (final); + }; +{{- end}} + channel { + # Listen on the default port (typically 514) for CISCO_WSA traffic + source (s_DEFAULT); + filter(f_cisco_wsa); + flags(final); + }; + }; + + if{ + filter{ + message('(\d*|\s+|\w+|\(|\)|\+|\:|\-)*(Info|Warning|Alert|Debug):.*') + }; + rewrite { + set("cisco_wsa", value("fields.sc4s_vendor_product")); + r_set_splunk_dest_default(sourcetype("cisco:wsa:l4tm"), index("netops")) + }; + parser { p_add_context_splunk(key("cisco_wsa")); }; + parser (compliance_meta_by_source); + rewrite { set("$(template ${.splunk.sc4s_template} $(template t_legacy_hdr_msg))" value("MSG")); }; + + } elif { + filter(f_cisco_wsa11_7); + parser { + channel { + filter { + program( + '(?:(?\d{10})(?:.(?\d{1,9}))?)' + flags(store-matches) + ); + }; + parser { + date-parser-nofilter(format('%s.%f') + template("${EPOCH}.${TIMESECFRAC}") + ); + }; + }; + }; + rewrite { + set("cisco_wsa11_7", value("fields.sc4s_vendor_product")); + r_set_splunk_dest_default(sourcetype("cisco:wsa:squid:new"), index("netops"),source("wsa_11.7")) + }; + parser { p_add_context_splunk(key("cisco_wsa")); }; + parser (compliance_meta_by_source); + rewrite { set("$(template ${.splunk.sc4s_template} $(template t_legacy_hdr_msg))" value("MSG")); }; + + } else { + parser { + channel { + filter { + program( + '(?:(?\d{10})(?:.(?\d{1,9}))?)' + flags(store-matches) + ); + }; + parser { + date-parser-nofilter(format('%s.%f') + template("${EPOCH}.${TIMESECFRAC}") + ); + }; + }; + }; + rewrite { + set("cisco_wsa", value("fields.sc4s_vendor_product")); + r_set_splunk_dest_default(sourcetype("cisco:wsa:squid"), index("netops")) + }; + parser { p_add_context_splunk(key("cisco_wsa")); }; + 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_WSA_HEC" "no")) }} + destination(d_hec); +{{- end}} + +{{- if or (conv.ToBool (getenv "SC4S_ARCHIVE_GLOBAL" "no")) (conv.ToBool (getenv "SC4S_ARCHIVE_CISCO_WSA" "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_WSA_ALTERNATES")) }} + {{ getenv "SC4S_DEST_CISCO_WSA_ALTERNATES" | regexp.ReplaceLiteral "^" "destination(" | regexp.ReplaceLiteral "[, ]+" ");\n destination(" }}); +{{- end }} + + flags(flow-control,final); +}; \ No newline at end of file diff --git a/package/etc/context_templates/vendor_product_by_source.conf.example b/package/etc/context_templates/vendor_product_by_source.conf.example index 1eb20df..8e27762 100644 --- a/package/etc/context_templates/vendor_product_by_source.conf.example +++ b/package/etc/context_templates/vendor_product_by_source.conf.example @@ -39,6 +39,12 @@ filter f_cisco_meraki { host("testcm-*" type(glob)) #or netmask(xxx.xxx.xxx.xxx/xx) }; +filter f_cisco_wsa{ + host("cisco_wsa" type(glob)) +}; +filter f_cisco_wsa11_7{ + host("cisco_wsa11_7" type(glob)) +}; filter f_cisco_nx_os { host("csconx-*" type(glob)) #or netmask(xxx.xxx.xxx.xxx/xx) diff --git a/package/etc/context_templates/vendor_product_by_source.csv.example b/package/etc/context_templates/vendor_product_by_source.csv.example index 86ece07..d1e29bd 100644 --- a/package/etc/context_templates/vendor_product_by_source.csv.example +++ b/package/etc/context_templates/vendor_product_by_source.csv.example @@ -2,6 +2,8 @@ f_test_test,sc4s_vendor_product,"test_test" f_brocade_syslog,sc4s_vendor_product,"brocade_syslog" f_null_queue,sc4s_vendor_product,"null_queue" f_cisco_meraki,sc4s_vendor_product,"cisco_meraki" +f_cisco_wsa,sc4s_vendor_product,"cisco_wsa" +f_cisco_wsa11_7,sc4s_vendor_product,"cisco_wsa11_7" f_citrix_netscaler,sc4s_vendor_product,"citrix_netscaler" f_dell_rsa_secureid,sc4s_vendor_product,"dell_rsa_secureid" f_f5_bigip,sc4s_vendor_product,"f5_bigip" diff --git a/tests/test_cisco_wsa.py b/tests/test_cisco_wsa.py new file mode 100644 index 0000000..a69273f --- /dev/null +++ b/tests/test_cisco_wsa.py @@ -0,0 +1,118 @@ +import random + +from jinja2 import Environment + +from .sendmessage import * +from .splunkutils import * +from .timeutils import * +import pytest +env = Environment() + + +testdata_squid_11_7 = [ +'{{ mark }}{{ bsd }} {{ host }} 1588851315.000 382 10.0.0.13 TCP_CLIENT_REFRESH_MISS_SSL/201 4646 GET http://test_web.com/page2/b.txt Conner_Fitzerald DEFAULT_PARENT/www.xxxxxxx14.com application/x-javascript OTHER_382-NONE-CyberRange_Inside_NoAuth-OMSPolicy-random_policy-random_policy-DIRECT "Anonymous_Suspect_Vendor" "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52" - -', +'{{ mark }}{{ bsd }} {{ host }} 1588850982.000 331 10.0.0.12 TCP_DENIED/403 3197 POST http://test_web.net/contents/content5.jpg Tom_Lawrence DIRECT/www.xxxxxxx7.com application/x-javascript DEFAULT_CASE_331-Auth-APJC_Cisco_Corporate-OMSPolicy-DefaultGroup-NONE-DefaultRouting "Anonymous_Suspect_Vendor" "Mozilla/5.0 (X11; U; Linux arm7tdmi; rv:1.8.1.11) Gecko/20071130 Minimo/0.025" - -', +'{{ mark }}{{ bsd }} {{ host }} 1588851529.000 252 10.0.0.2 NONE/504 3040 GET http://test_web.net/users/user5.jpg Tom_Lawrence DIRECT/www.xxxxxxx5.com application/pkix-crl PASSTHRU_ADMIN_252-Decrypt_VFS-WebxOnly-RFS_Transparent_Proxy_Test-random_policy-NONE-DefaultRouting "abcd" "Mozilla/5.0 (X11; U; Linux arm7tdmi; rv:1.8.1.11) Gecko/20071130 Minimo/0.025" - -' +] + +testdata_l4tm = [ +'{{ mark }}{{ bsd }} {{ host }} Mon May 04 12:59:59 2020 Info: Firewall noted TCP data from 10.0.0.15 to 61.79.37.205(www.xxxxxxx7.com):1283.', +'{{ mark }}{{ bsd }} {{ host }} 04 May 2020 12:59:57 (GMT-1:00) Info: Address 143.164.34.50 discovered for www.xxxxxxx4.com (www.xxxxxxx4.com) added to firewall greylist.', +'{{ mark }}{{ bsd }} {{ host }} Mon May 04 12:59:54 2020 Info: Begin Logfile', +'{{ mark }}{{ bsd }} {{ host }} Mon May 04 12:59:49 2020 Info: Version: 9.0.0-485 SN: 848F69E6010F-JYFZWQ1', +'{{ mark }}{{ bsd }} {{ host }} 04 May 2020 12:59:59 (GMT+5:00) Info: Firewall blocked TCP data from 10.0.0.3:1148 to 96.246.56.182.', +'{{ mark }}{{ bsd }} {{ host }} Mon May 04 12:59:58 2020 Info: Time offset from UTC: 113 seconds', +'{{ mark }}{{ bsd }} {{ host }} Mon May 04 12:59:59 2020 Info: Firewall noted TCP data from 10.0.0.15 to 61.79.37.205(www.xxxxxxx7.com):1283.' +] +testdata_squid = [ +'{{ mark }}{{ bsd }} {{ host }} 1588851279.000 184 10.0.0.6 TCP_CLIENT_REFRESH_MISS/404 461 POST http://test_web.net/users/user2.jpg - DEFAULT_PARENT/www.xxxxxxx15.com application/javascript DEFAULT_CASE_184-NONE-CyberRange_DC_NoAuth-RFS_Transparent_Proxy_Test-random_policy-DefaultGroup-RoutingPolicy "abcd" 486', +'{{ mark }}{{ bsd }} {{ host }} 1588851133.000 258 10.0.0.12 TCP_MISS/200 4687 GET http://test_web.net/users/user2.jpg Tom_Lawrence DIRECT/www.xxxxxxx15.com image/gif BLOCK_AMW_RESP_URL_258-Allow_All_iDevices-APJC_Cisco_Corporate-RFS_Transparent_Proxy_Test-NONE-random_policy-random_policy "random_name"', +'{{ mark }}{{ bsd }} {{ host }} 1588851234.000 17 10.0.0.5 TCP_CLIENT_REFRESH_MISS_SSL/200 1939 HEAD http://test_web.net/contents/content4.jpg - NONE/www.xxxxxxx15.com application/javascript ALLOW_WBRS_17-AccessPolicy-CyberRange_Inside_NoAuth-RFS_Transparent_Proxy_Test-DefaultGroup-random_policy-RoutingPolicy - 486', +'{{ mark }}{{ bsd }} {{ host }} 1588850961.000 245 2001:b8f9:c5c2:f730::2 TCP_DENIED/403 0 GET http://test_web.net/users/user1.jpg Alexei_Romanov NONE/www.xxxxxxx6.com application/x-javascript BLOCK_WEBCAT_245-Allow_All_iDevices-CyberRange_Inside_NoAuth-OMSPolicy-DataSecurityPolicy-DefaultGroup-DIRECT -', +'{{ mark }}{{ bsd }} {{ host }} 1588850940.000 26 2001:44c4:cf35:1b78::6 TCP_MISS/204 4525 POST http://test_web.com/page1/a.txt Andy_Lloyd DIRECT/www.xxxxxxx3.com image/jpeg DEFAULT_CASE_26-NONE-CyberRange_Inside_NoAuth-OMSPolicy-DataSecurityPolicy-ExternalDLPolicy-RoutingPolicy "Anonymous_Suspect_Vendor" 100', +'{{ mark }}{{ bsd }} {{ host }} 1588851442.000 6 10.0.0.7 TCP_CLIENT_REFRESH_MISS/404 1932 GET http://test_web.com/page2/b.txt - DEFAULT_PARENT/www.xxxxxxx8.com - DEFAULT_CASE_6-AP_Subnet_2-NONE-RFS_Transparent_Proxy_Test-NONE-ExternalDLPolicy-RoutingPolicy <nc,5.0,-,"-",-,-,-,-,"-",-,-,-,"-",-,-,"-","-",-,-,nc,-,"-","-","Unknown","Unknown","-","-",0.63,0,-,"-","-",-,"-",-,-,"-","-"> - "03/Jan/2015:07:09:50 +1100" NONE -', +'{{ mark }}{{ bsd }} {{ host }} 1588850950.000 262 10.0.0.7 TCP_MISS_SSL/204 953 POST http://test_web.net/contents/content3.jpg Alexei_Romanov NONE/www.xxxxxxx10.com application/x-javascript DEFAULT_CASE_262-Internet_Access_with_Streaming-ID.ACMETECHISE-NONE-DefaultGroup-random_policy-RoutingPolicy "Anonymous_Suspect_Vendor" 123 "07/052020:11:29:10 +1332" NONE "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.15"' + +] + +@pytest.mark.parametrize("event", testdata_squid_11_7) +def test_cisco_wsa_squid_11_7(record_property, setup_wordlist, get_host_key, setup_splunk, setup_sc4s, event): + host = "cisco_wsa11_7" + + dt = datetime.datetime.now() + iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) + + # Tune time functions + epoch = epoch[:-7] + + mt = env.from_string(event + "\n") + message = mt.render(mark="<13>", bsd=bsd ,host=host ) + + sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) + + st = env.from_string( + "search index=netops sourcetype=\"cisco:wsa:squid:new\" _raw=\"{{ message }}\"") + message1 = mt.render(mark="", bsd="", host="") + search = st.render(host=host, message=message1.lstrip().replace('"','\\"')) + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +@pytest.mark.parametrize("event", testdata_squid) +def test_cisco_wsa_squid(record_property, setup_wordlist, get_host_key, setup_splunk, setup_sc4s, event): + host = "cisco_wsa" + + dt = datetime.datetime.now() + iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) + + # Tune time functions + epoch = epoch[:-7] + + mt = env.from_string(event + "\n") + message = mt.render(mark="<13>", bsd=bsd ,host=host ) + + sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) + + st = env.from_string( + "search index=netops sourcetype=\"cisco:wsa:squid\" _raw=\"{{ message }}\"") + message1 = mt.render(mark="", bsd="", host="") + search = st.render(host=host, message=message1.lstrip().replace('"','\\"')) + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +@pytest.mark.parametrize("event", testdata_l4tm) +def test_cisco_wsa_l4tm(record_property, setup_wordlist, get_host_key, setup_splunk, setup_sc4s, event): + host = "cisco_wsa" + + dt = datetime.datetime.now() + iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) + + # Tune time functions + epoch = epoch[:-7] + + mt = env.from_string(event + "\n") + message = mt.render(mark="<13>", bsd=bsd, host=host) + sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) + + st = env.from_string( + "search index=netops _time={{ epoch }} sourcetype=\"cisco:wsa:l4tm\" _raw=\"{{ message }}\"") + + message1 = mt.render(mark="", bsd="", host="") + search = st.render(epoch=epoch, host=host, message=message1.lstrip()) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 \ No newline at end of file