diff --git a/docs/sources.md b/docs/sources.md index 7919645..12f4f3c 100644 --- a/docs/sources.md +++ b/docs/sources.md @@ -1,3 +1,68 @@ +# Vendor - Checkpoint + +## Product - Log Exporter (Splunk) + +| Ref | Link | +|----------------|---------------------------------------------------------------------------------------------------------| +| Splunk Add-on | https://splunkbase.splunk.com/app/4293/ | +| Product Manual | https://sc1.checkpoint.com/documents/App_for_Splunk/html_frameset.htm | + + +### Sourcetypes + +| sourcetype | notes | +|----------------|---------------------------------------------------------------------------------------------------------| +| cp_log | None | + +### Sourcetype and Index Configuration + +| key | sourcetype | index | notes | +|----------------|----------------|----------------|----------------| +| checkpoint_splunk | cp_log | netfw | none | + +### Source and Index Configuration + +Checkpoint Software blades with CIM mapping have been sub-grouped into sources +to allow routing to appropriate indexes. All other source meta data is left at default + +| key | source | index | notes | +|----------------|----------------|----------------|----------------| +| checkpoint_splunk_dlp | dlp | netdlp | none | +| checkpoint_splunk_email | email | email | none | +| checkpoint_splunk_firewall | firewall | netfw | none | +| checkpoint_splunk_sessions | sessions | netops | none | +| checkpoint_splunk_web | web | netproxy | none | + +### Filter type + +MSG Parse: This filter parses message content + +### 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. +* Review and update the splunk_index.csv file and set the index and sourcetype as required for the data source. +* Follow vendor configuration steps per Product Manual above ensure: + * Log Level is 6 "Informational" + * Protocol is TCP/IP + * permit-hostdown is on + * device-id is hostname and included + * timestamp is included + +### Options + +| Variable | default | description | +|----------------|----------------|----------------| +| SC4S_LISTEN_CHECKPOINT_SPLUNK_TCP_PORT | empty string | Enable a TCP port for this specific vendor product using the port number defined | + +### Verification + +Use the following search to validate events are present + +``` +index= sourcetype=cisco:asa +``` + +Verify timestamp, and host values match as expected # Vendor - Cisco ## Product - ASA (Pre Firepower) diff --git a/package/etc/conf.d/conflib/_splunk/splunkfields.conf b/package/etc/conf.d/conflib/_splunk/splunkfields.conf index b535d3b..c195deb 100644 --- a/package/etc/conf.d/conflib/_splunk/splunkfields.conf +++ b/package/etc/conf.d/conflib/_splunk/splunkfields.conf @@ -10,10 +10,12 @@ rewrite r_set_splunk_default { #overridden by user defined values block rewrite r_set_splunk_dest_default( index() + source("${.splunk.source}") sourcetype() template(`splunk-template`) ) { set("`index`", value(".splunk.index")); + set("`source`", value(".splunk.source")); set("`sourcetype`", value(".splunk.sourcetype")); set("`template`", value("fields.sc4s_template")); }; diff --git a/package/etc/conf.d/filters/checkpoint/splunk.conf b/package/etc/conf.d/filters/checkpoint/splunk.conf new file mode 100644 index 0000000..701ebc2 --- /dev/null +++ b/package/etc/conf.d/filters/checkpoint/splunk.conf @@ -0,0 +1,57 @@ +filter f_checkpoint_splunk { + match('\|(?:origin_sic_name|originsicname)\=[cC][nN]|\|product\=SmartConsole\|' value("RAWMSG") type("pcre")); +}; + +filter f_checkpoint_splunk_alerts { + match('*IOS Profile*' value('.kv.product') type('glob')) + or match('*Device*' value('.kv.product') type('glob')) +}; + +filter f_checkpoint_splunk_Change { + match('*Application Control*' value('.kv.product') type('glob')) +}; + +filter f_checkpoint_splunk_DLP { + match('*DLP*' value('.kv.product') type('glob')) +}; + +filter f_checkpoint_splunk_email { + match('*MTA*' value('.kv.product') type('glob')) + or match('*Anti-Spam*' value('.kv.product') type('glob')) + or match('*Anti Spam*' value('.kv.product') type('glob')) +}; + +filter f_checkpoint_splunk_IDS { + match('*IPS*' value('.kv.product') type('glob')) + or match('*WIFI*' value('.kv.product') type('glob')) + or match('*Cellular*' value('.kv.product') type('glob')) +}; + +filter f_checkpoint_splunk_IDS_Malware { + match('*Threat Emulation*' value('.kv.product') type('glob')) + or match('*Anti-Virus*' value('.kv.product') type('glob')) + or match('*Anti-Bot*' value('.kv.product') type('glob')) + or match('*Threat Extraction*' value('.kv.product') type('glob')) + or match('*Anti-Ransomware*' value('.kv.product') type('glob')) + or match('*Anti-Exploit**' value('.kv.product') type('glob')) + or match('*Forensics*' value('.kv.product') type('glob')) + or match('*OS Exploit*' value('.kv.product') type('glob')) + or (match('*Application*' value('.kv.product') type('glob')) and not match('*Application Control*' value('.kv.product') type('glob'))) + or match('*Text Message*' value('.kv.product') type('glob')) + or match('*Network Access*' value('.kv.product') type('glob')) + or match('*Zero Phishing*' value('.kv.product') type('glob')) +}; + +filter f_checkpoint_splunk_NetworkSessions { + match('*VPN*' value('.kv.product') type('glob')) + or match('*Mobile*' value('.kv.product') type('glob')) + or match('*VPN*' value('.kv.fw_subproduct') type('glob')) +}; + +filter f_checkpoint_splunk_NetworkTraffic { + match('*Firewall*' value('.kv.product') type('glob')) + and not match('*VPN*' value('.kv.fw_subproduct') type('glob')) +}; +filter f_checkpoint_splunk_Web { + match('*Url Filtering*' value('.kv.product') type('glob')) +}; \ No newline at end of file diff --git a/package/etc/conf.d/log_paths/p_rfc3164-checkpoint_splunk.conf.tmpl b/package/etc/conf.d/log_paths/p_rfc3164-checkpoint_splunk.conf.tmpl new file mode 100644 index 0000000..0ad2806 --- /dev/null +++ b/package/etc/conf.d/log_paths/p_rfc3164-checkpoint_splunk.conf.tmpl @@ -0,0 +1,72 @@ +# Checkpoint Splunk format +{{- if (ne (getenv (print "SC4S_LISTEN_CHECKPOINT_SPLUNK_TCP_PORT") "no") "no") or (ne (getenv (print "SC4S_LISTEN_CHECKPOINT_SPLUNK_UDP_PORT") "no") "no") or (ne (getenv (print "SC4S_LISTEN_CHECKPOINT_SPLUNK_TLS_PORT") "no") "no") }} +{{ $context := dict "port_id" "CHECKPOINT_SPLUNK" "parser" "common" }} +{{ tmpl.Exec "t/source_network.t" $context }} +{{- end -}} +{{ define "log_path" }} +log { +{{- if eq (.) "yes"}} + source(s_default-ports); + filter(f_is_rfc3164); + filter(f_checkpoint_splunk); +{{- end}} +{{- if eq (.) "no"}} + source (s_dedicated_port_CHECKPOINT_SPLUNK); +{{- end}} + + parser { + kv-parser(prefix(".kv.") pair-separator("|") template("${MSGHDR} ${MSG}")); + date-parser(format("%s") template("${.kv.time}") time-zone({{- getenv "SC4S_DEFAULT_TIMEZONE" "GMT"}})); + + }; + + rewrite { set("${.kv.hostname}", value("HOST")); }; + + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), index("netops"), template("t_hdr_msg"))}; + parser {p_add_context_splunk(key("checkpoint_splunk")); }; + + if { + filter(f_checkpoint_splunk_NetworkTraffic); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("firewall"), index("netfw"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_firewall")); }; + } elif { + filter(f_checkpoint_splunk_Web); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("web"), index("netproxy"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_web")); }; + } elif { + filter(f_checkpoint_splunk_NetworkSessions); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("sessions"), index("netops"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_sessions")); }; + } elif { + filter(f_checkpoint_splunk_IDS_Malware); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("ids_malware"), index("netids"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_ids")); }; + } elif { + filter(f_checkpoint_splunk_IDS); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("ids"), index("netids"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_ids")); }; + } elif { + filter(f_checkpoint_splunk_email); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("email"), index("email"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_email")); }; + } elif { + filter(f_checkpoint_splunk_DLP); + rewrite { r_set_splunk_dest_default(sourcetype("cp_log"), source("firewall"), index("netdlp"), template("t_standard"))}; + parser {p_add_context_splunk(key("checkpoint_splunk_dlp")); }; + }; + + + parser (compliance_meta_by_source); + + destination(d_hec); #--HEC-- + + flags(flow-control); +}; +{{- end}} +{{- if (ne (getenv (print "SC4S_LISTEN_CHECKPOINT_SPLUNK_TCP_PORT") "no") "no") or (ne (getenv (print "SC4S_LISTEN_CHECKPOINT_SPLUNK_UDP_PORT") "no") "no") or (ne (getenv (print "SC4S_LISTEN_CHECKPOINT_SPLUNK_TLS_PORT") "no") "no") }} +# Listen on the specified dedicated port(s) for CHECKPOINT_SPLUNK traffic + {{ tmpl.Exec "log_path" "no" }} +{{- end}} + +# Listen on the default port (typically 514) for CHECKPOINT_SPLUNK traffic +{{ tmpl.Exec "log_path" "yes" }} diff --git a/package/etc/context_templates/splunk_index.csv b/package/etc/context_templates/splunk_index.csv index e93911a..ec4f02c 100644 --- a/package/etc/context_templates/splunk_index.csv +++ b/package/etc/context_templates/splunk_index.csv @@ -3,6 +3,14 @@ #cef_Incapsula_SIEMintegration,index,netwaf #cef_Microsoft_Microsoft Windows,index,oswinsec #cef_Microsoft_System or Application Event,index,oswin +#checkpoint_splunk,index,netops +#checkpoint_splunk_dlp,index,netdlp +#checkpoint_splunk_email,index,email +#checkpoint_splunk_firewall,index,netfw +#checkpoint_splunk_sessions,index,netops +#checkpoint_splunk_web,index,netproxy +#checkpoint_splunk,index,netops +#checkpoint_splunk,index,netops #cisco_asa,index,netfw #cisco_ios,index,netops #cisco_nx_os,index,netops diff --git a/splunk/etc/apps/SA-syslog-ng/default/indexes.conf b/splunk/etc/apps/SA-syslog-ng/default/indexes.conf index 09e86e5..612fe0b 100644 --- a/splunk/etc/apps/SA-syslog-ng/default/indexes.conf +++ b/splunk/etc/apps/SA-syslog-ng/default/indexes.conf @@ -30,6 +30,11 @@ homePath = $SPLUNK_DB/oswinsec/db coldPath = $SPLUNK_DB/oswinsec/colddb thawedPath = $SPLUNK_DB/oswinsec/thaweddb +[netdlp] +homePath = $SPLUNK_DB/netdlp/db +coldPath = $SPLUNK_DB/netdlp/colddb +thawedPath = $SPLUNK_DB/netdlp/thaweddb + [netfw] homePath = $SPLUNK_DB/netfw/db coldPath = $SPLUNK_DB/netfw/colddb diff --git a/tests/test_checkpoint.py b/tests/test_checkpoint.py new file mode 100644 index 0000000..92d1717 --- /dev/null +++ b/tests/test_checkpoint.py @@ -0,0 +1,140 @@ +# 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 * + +env = Environment(extensions=['jinja2_time.TimeExtension']) + +# +#Oct 8 15:00:25 DEVICENAME time=1570561225|hostname=devicename|severity=Informational|confidence_level=Unknown|product=IPS|action=Drop|ifdir=inbound|ifname=bond2|loguid={0x5d9cdcc9,0x8d159f,0x5f19f392,0x1897a828}|origin=1.1.1.1|time=1570561225|version=1|attack=Streaming Engine: TCP Segment Limit Enforcement|attack_info=TCP segment out of maximum allowed sequence. Packet dropped.|chassis_bladed_system=[ 1_3 ]|dst=10.10.10.10|origin_sic_name=CN=something_03_local,O=devicename.domain.com.p7fdbt|performance_impact=0|protection_id=tcp_segment_limit|protection_name=TCP Segment Limit Enforcement|protection_type=settings_tcp|proto=6|rule=393|rule_name=10.384_..|rule_uid={9F77F944-8DD5-4ADF-803A-785D03B3A2E8}|s_port=46455|service=443|smartdefense_profile=Recommended_Protection_ded9e8d8ee89d|src=1.1.1.2| +def test_checkpoint_splunk_ips(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} time={% now 'utc', '%s' %}|hostname={{ host }}|severity=Informational|confidence_level=Unknown|product=IPS|action=Drop|ifdir=inbound|ifname=bond2|loguid={0x5d9cdcc9,0x8d159f,0x5f19f392,0x1897a828}|origin=1.1.1.1|time={% now 'utc', '%s' %}|version=1|attack=Streaming Engine: TCP Segment Limit Enforcement|attack_info=TCP segment out of maximum allowed sequence. Packet dropped.|chassis_bladed_system=[ 1_3 ]|dst=10.10.10.10|origin_sic_name=CN=something_03_local,O=devicename.domain.com.p7fdbt|performance_impact=0|protection_id=tcp_segment_limit|protection_name=TCP Segment Limit Enforcement|protection_type=settings_tcp|proto=6|rule=393|rule_name=10.384_..|rule_uid={9F77F944-8DD5-4ADF-803A-785D03B3A2E8}|s_port=46455|service=443|smartdefense_profile=Recommended_Protection_ded9e8d8ee89d|src=1.1.1.2|\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=netids host=\"{{ host }}\" sourcetype=\"cp_log\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +#$Oct 8 15:48:31 DEVICENAME time=1570564111|hostname=devicename|product=Firewall|action=Drop|ifdir=inbound|ifname=bond1|loguid={0x5d9ce80f,0x8d0555,0x5f19f392,0x18982828}|origin=1.1.1.1|time=1570564111|version=1|chassis_bladed_system=[ 1_1 ]|dst=10.10.10.10|inzone=External|origin_sic_name=CN=something_03_local,O=devicename.domain.com.p7fdbt|outzone=Internal|proto=6|rule=402|rule_name=11_..|rule_uid={C8CD796E-7BD5-47B6-90CA-B250D062D5E5}|s_port=33687|service=23|src=1.1.1.2| +def test_checkpoint_splunk_firewall(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} time={% now 'utc', '%s' %}|hostname={{ host }}|product=Firewall|action=Drop|ifdir=inbound|ifname=bond1|loguid={0x5d9ce80f,0x8d0555,0x5f19f392,0x18982828}|origin=1.1.1.1|time={% now 'utc', '%s' %}|version=1|chassis_bladed_system=[ 1_1 ]|dst=10.10.10.10|inzone=External|origin_sic_name=CN=something_03_local,O=devicename.domain.com.p7fdbt|outzone=Internal|proto=6|rule=402|rule_name=11_..|rule_uid={C8CD796E-7BD5-47B6-90CA-B250D062D5E5}|s_port=33687|service=23|src=1.1.1.2|\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=netfw host=\"{{ host }}\" sourcetype=\"cp_log\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +#Oct 9 12:01:16 DEVICENAME |hostname=DEVICENAME|product=mds-query-tool|action=Accept|ifdir=outbound|origin=1.1.1.1|2.2.2.2|originsicname=cn\=cp_mgmt,o\=DEVICENAME.domain.com.p7fdbt|sequencenum=1|time=1570641309|version=5|administrator=localhost|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log Out|operation_number=12|subject=Administrator Login| +def test_checkpoint_splunk_mds(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} |hostname={{ host }}|time={% now 'utc', '%s' %}|product=mds-query-tool|action=Accept|ifdir=outbound|origin=1.1.1.1|2.2.2.2|originsicname=cn\=cp_mgmt,o\=DEVICENAME.domain.com.p7fdbt|sequencenum=1|time={% now 'utc', '%s' %}|version=5|administrator=localhost|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log Out|operation_number=12|subject=Administrator Login|\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=netops host=\"{{ host }}\" sourcetype=\"cp_log\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +#Oct 9 12:01:16 DEVICENAME|hostname=DEVICENAME|product=CPMI Client|action=Accept|ifdir=outbound|origin=1.1.1.1|2.2.2.2|originsicname=cn\=cp_mgmt,o\=DEVICENAME.domain.com.p7fdbt|sequencenum=1|time=1570641173|version=5|administrator=localhost|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log Out|operation_number=12|subject=Administrator Login +def test_checkpoint_splunk_cpmi(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} |hostname={{ host }}|product=CPMI Client|action=Accept|ifdir=outbound|origin=1.1.1.1|2.2.2.2|originsicname=cn\=cp_mgmt,o\=DEVICENAME.domain.com.p7fdbt|sequencenum=1|time={% now 'utc', '%s' %}|version=5|administrator=localhost|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log Out|operation_number=12|subject=Administrator Login\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=netops host=\"{{ host }}\" sourcetype=\"cp_log\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +#Oct 9 12:01:16 DEVICENAME |hostname=DEVICENAME|product=WEB_API|action=Accept|ifdir=outbound|origin=1.1.1.1|2.2.2.2|originsicname=cn\=cp_mgmt,o\=DEVICENAME.domain.com.p7fdbt|sequencenum=1|time=1570640578|version=5|administrator=tufinapi|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log Out|operation_number=12|subject=Administrator Login +def test_checkpoint_splunk_web_api(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} |hostname={{ host }}|product=WEB_API|action=Accept|ifdir=outbound|origin=1.1.1.1|2.2.2.2|originsicname=cn\=cp_mgmt,o\=DEVICENAME.domain.com.p7fdbt|sequencenum=1|time={% now 'utc', '%s' %}|version=5|administrator=tufinapi|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log Out|operation_number=12|subject=Administrator Login\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=netops host=\"{{ host }}\" sourcetype=\"cp_log\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +#Oct 9 11:05:15 DEVICENAME time=1570633513|hostname=DEVICENAME|product=SmartConsole|action=Accept|ifdir=outbound|origin=1.1.1.1|4.4.4.4|sequencenum=1|time=1570633513|version=5|additional_info=Authentication method: Password based application token|administrator=psanadhya|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log In|operation_number=10|subject=Administrator Login| +def test_checkpoint_splunk_smartconsole(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} time={% now 'utc', '%s' %}|hostname={{ host }}|product=SmartConsole|action=Accept|ifdir=outbound|origin=1.1.1.1|4.4.4.4|sequencenum=1|time={% now 'utc', '%s' %}|version=5|additional_info=Authentication method: Password based application token|administrator=psanadhya|client_ip=3.3.3.3|machine=DEVICENAME|operation=Log In|operation_number=10|subject=Administrator Login|\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=netops host=\"{{ host }}\" sourcetype=\"cp_log\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1