diff --git a/docs/sources/Cohesity/index.md b/docs/sources/Cohesity/index.md new file mode 100644 index 0000000000..779c40e9fc --- /dev/null +++ b/docs/sources/Cohesity/index.md @@ -0,0 +1,49 @@ +# Vendor - Cohesity + + +## Product - Switches + +| Ref | Link | +|----------------|---------------------------------------------------------------------------------------------------------| +| Splunk Add-on | None | +| Product Manual | unknown | + + +### Sourcetypes + +| sourcetype | notes | +|----------------|---------------------------------------------------------------------------------------------------------| +| cohesity:cluster:audit | None | +| cohesity:cluster:dataprotection | None | + +### Sourcetype and Index Configuration + +| key | sourcetype | index | notes | +|----------------|----------------|----------------|----------------| +| cohesity_cluster_audit | cohesity:cluster:audit | infraops | none | +| cohesity_cluster_dataprotection | cohesity:cluster:dataprotection | infraops | none | + +### Filter type + +MSG Parsing + +### Setup and Configuration + +Device setup unknown + +### Options + +| Variable | default | description | +|----------------|----------------|----------------| +| SC4S_LISTEN_COHESITY_CLUSTER_TCP_PORT | empty string | Enable a TCP port for this specific vendor product using a comma-separated list of port numbers | +| SC4S_LISTEN_COHESITY_CLUSTER_UDP_PORT | empty string | Enable a UDP port for this specific vendor product using a comma-separated list of port numbers | +| SC4S_ARCHIVE_COHESITY_CLUSTER | no | Enable archive to disk for this specific source | +| SC4S_DEST_COHESITY_CLUSTER_HEC | no | When Splunk HEC is disabled globally set to yes to enable this specific source | + +### Verification + +An active device will generate frequent events. Use the following search to validate events are present per source device + +``` +index= sourcetype=cohesity:cluster:* | stats count by host +``` diff --git a/mkdocs.yml b/mkdocs.yml index 5d90e3123f..d9cde15713 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -45,6 +45,7 @@ nav: - Checkpoint: sources/Checkpoint/index.md - Cisco: sources/Cisco/index.md - Citrix: sources/Citrix/index.md + - Cohesity: sources/Cohesity/index.md - "Common Event Format": sources/CommonEventFormat/index.md - CyberArk: sources/CyberArk/index.md - Cylance: sources/Cylance/index.md diff --git a/package/etc/conf.d/conflib/syslog/app-syslog-cohesity_cluster_audit.conf b/package/etc/conf.d/conflib/syslog/app-syslog-cohesity_cluster_audit.conf new file mode 100644 index 0000000000..981b615e2c --- /dev/null +++ b/package/etc/conf.d/conflib/syslog/app-syslog-cohesity_cluster_audit.conf @@ -0,0 +1,35 @@ +block parser app-syslog-cohesity_cluster_audit() { + channel { + parser { + json-parser( + prefix('.values.') + ); + date-parser-nofilter( + format( + '%Y-%m-%dT%T.%f%z', + '%Y-%m-%dT%T%z', + ) + template("${.values.Timestamp}") + ); + }; + filter { + "${.values.ClusterInfo}" ne ""; + }; + rewrite { + r_set_splunk_dest_default( + index('infraops') + sourcetype('cohesity:cluster:audit') + vendor_product("cohesity_cluster_audit") + template('t_msg_only') + ); + }; + + }; +}; +application app-syslog-cohesity_cluster_audit[sc4s-syslog] { + filter { + "${PROGRAM}" eq "cluster_audit"; + }; + parser { app-syslog-cohesity_cluster_audit(); }; +}; + diff --git a/package/etc/conf.d/conflib/syslog/app-syslog-cohesity_cluster_dataprotection.conf b/package/etc/conf.d/conflib/syslog/app-syslog-cohesity_cluster_dataprotection.conf new file mode 100644 index 0000000000..9cb5f1f2df --- /dev/null +++ b/package/etc/conf.d/conflib/syslog/app-syslog-cohesity_cluster_dataprotection.conf @@ -0,0 +1,35 @@ +block parser app-syslog-cohesity_cluster_dataprotection() { + channel { + parser { + json-parser( + prefix('.values.') + ); + date-parser-nofilter( + format( + '%Y-%m-%dT%T.%f%z', + '%Y-%m-%dT%T%z', + ) + template("${.values.Timestamp}") + ); + }; + filter { + "${.values.EventType}" ne ""; + }; + rewrite { + r_set_splunk_dest_default( + index('infraops') + sourcetype('cohesity:cluster:dataprotection') + vendor_product("cohesity_cluster_dataprotection") + template('t_msg_only') + ); + }; + + }; +}; +application app-syslog-cohesity_cluster_dataprotection[sc4s-syslog] { + filter { + "${PROGRAM}" eq "dataprotection_events"; + }; + parser { app-syslog-cohesity_cluster_dataprotection(); }; +}; + diff --git a/tests/test_cohesity.py b/tests/test_cohesity.py new file mode 100644 index 0000000000..6950a7f3ab --- /dev/null +++ b/tests/test_cohesity.py @@ -0,0 +1,89 @@ +# 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 + +from jinja2 import Environment + +from .sendmessage import * +from .splunkutils import * +from .timeutils import * + +import pytest + +env = Environment() + + +# <14>Jan 26 14:20:39 host cluster_audit: {"Timestamp" : "2022-01-26T14:19:27.512Z", "AttributeMap" : {}, "EntityType" : "Access Token", "EntityId" : "cohesitysnowdev", "EntityName" : "cohesitysnowdev", "User" : "", "Domain" : "local", "Action" : "Create", "Description" : "@local attempted to generate new access token for user cohesitysnowdev on domain local from 1.1.1.1 failed with error Invalid Username or Password specified.", "ClusterInfo" : "ClusterName: clustername, ClusterId: xxxxxx"} +testdata = [ + '{{ mark }}{{ bsd }} {{ host }} cluster_audit: {"Timestamp" : "{{ iso }}", "AttributeMap" : {}, "EntityType" : "Access Token", "EntityId" : "cohesitysnowdev", "EntityName" : "cohesitysnowdev", "User" : "", "Domain" : "local", "Action" : "Create", "Description" : "@local attempted to generate new access token for user cohesitysnowdev on domain local from 1.1.1.1 failed with error Invalid Username or Password specified.", "ClusterInfo" : "ClusterName: clustername, ClusterId: xxxxxx"}', +] + + +@pytest.mark.parametrize("event", testdata) +def test_cohesity_cluster_audit( + record_property, setup_wordlist, get_host_key, setup_splunk, setup_sc4s, event +): + host = get_host_key + + dt = datetime.datetime.now() + iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) + + # Tune time functions + epoch = epoch[:-3] + + mt = env.from_string(event + "\n") + message = mt.render(mark="<166>", bsd=bsd, host=host, iso=iso) + + sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) + + st = env.from_string( + 'search index=infraops _time={{ epoch }} sourcetype="cohesity:cluster:audit" (host="{{ host }}" OR "{{ host }}")' + ) + 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 + + +# <14>Jan 26 14:20:39 host cluster_audit: {"Timestamp" : "2022-01-26T14:19:27.512Z", "AttributeMap" : {}, "EntityType" : "Access Token", "EntityId" : "cohesitysnowdev", "EntityName" : "cohesitysnowdev", "User" : "", "Domain" : "local", "Action" : "Create", "Description" : "@local attempted to generate new access token for user cohesitysnowdev on domain local from 1.1.1.1 failed with error Invalid Username or Password specified.", "ClusterInfo" : "ClusterName: clustername, ClusterId: xxxxxx"} +testdata2 = [ + '{{ mark }}{{ bsd }} {{ host }} dataprotection_events: {"EventMessage" : "Expiring backup run", "Timestamp" : "{{ iso }}", "ClusterInfo" : {"ClusterId" : "1755240360407376", "ClusterName" : "cluster-name"}, "EventType" : "kBackup", "EnvironmentType" : "kVMware", "RegisteredSource" : {"EntityType" : "kVMware", "EntityId" : "1", "EntityName" : "ttllxapp-vc01"}, "BackupJobName" : "test1", "BackupJobId" : "582", "Entities" : [{"EntityType" : "kVMware", "EntityId" : "27", "EntityName" : "xxx-xxx"}, {"EntityType" : "kVMware", "EntityId" : "70", "EntityName" : "ttllxapp-joe01"}], "TaskId" : "509872", "AttributeMap" : {}}', +] + + +@pytest.mark.parametrize("event", testdata2) +def test_cohesity_dataprotection_events( + record_property, setup_wordlist, get_host_key, setup_splunk, setup_sc4s, event +): + host = get_host_key + + dt = datetime.datetime.now() + iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt) + + # Tune time functions + epoch = epoch[:-3] + + mt = env.from_string(event + "\n") + message = mt.render(mark="<166>", bsd=bsd, host=host, iso=iso) + + sendsingle(message, setup_sc4s[0], setup_sc4s[1][514]) + + st = env.from_string( + 'search index=infraops _time={{ epoch }} sourcetype="cohesity:cluster:dataprotection" (host="{{ host }}" OR "{{ host }}")' + ) + 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