Skip to content

Commit

Permalink
Merge branch 'develop' into feature/nx-os-soup
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Faircloth authored and GitHub committed May 18, 2020
2 parents 75c4bb5 + 53027d8 commit a546ac8
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 46 deletions.
9 changes: 6 additions & 3 deletions docs/sources/Cisco/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,27 +95,30 @@ Use the following search to validate events are present
index=<asconfigured> sourcetype=cisco:apic:*
```

Verify timestamp, and host values match as expected
Verify timestamp, and host values match as expected

## Product - ASA AND FTD (Firepower)

| Ref | Link |
|----------------|---------------------------------------------------------------------------------------------------------|
| Splunk Add-on | https://splunkbase.splunk.com/app/1620/ |
| Splunk Add-on for ASA | https://splunkbase.splunk.com/app/1620/ |
| Cisco eStreamer for Splunk | https://splunkbase.splunk.com/app/1629/ |
| Product Manual | https://www.cisco.com/c/en/us/td/docs/security/asa/asa82/configuration/guide/config/monitor_syslog.html |


### Sourcetypes

| sourcetype | notes |
|----------------|---------------------------------------------------------------------------------------------------------|
| cisco:asa | cisco FTD Firepower will also use this source type |
| cisco:asa | cisco FTD Firepower 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 |

### Sourcetype and Index Configuration

| key | sourcetype | index | notes |
|----------------|----------------|----------------|----------------|
| cisco_asa | cisco:asa | netfw | none |
| cisco_ftd | cisco:firepower:syslog | netfw | none |


### Filter type
Expand Down
4 changes: 2 additions & 2 deletions package/etc/conf.d/filters/cisco/apic.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

filter f_cisco_apic {
program('^%LOG_LOCAL\d-\d-');
or
program('^%ACLLOG-\d-ACLLOG_PKTLOG');
or program('^%LOG_-\d-');
or program('^%ACLLOG-\d-ACLLOG_PKTLOG');
};
93 changes: 61 additions & 32 deletions package/etc/conf.d/filters/cisco/cisco_syslog.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,68 @@ filter f_is_cisco_syslog{

parser cisco-parser-ex{
channel {
filter {
message('^<\d*> ?(?:(\d+)\: )?(?:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]): )?(?:(\d+): )?(?:(\d\d:\d\d:\d\d|\d{1,6} \d{1,2}))?(?:(\*)?((?:\w\w\w {1,2}\d{1,2} (?:\d{2,4} )?\d\d:\d\d:\d\d)(?:\.\d{3,6})?( [AP]M)?)( [A-Z]{3,3})?)? ?(?:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))? ?: ((\%[^\: ]+)\:? ?.*)' flags(store-matches));
};
if {
#Cisco IOS-XR devices with node-id format
filter {
message('^<\d*>(?:(\d+)\: )?(RP\/\d*\/RSP\d*\/CPU\d*:)?(?:([^\: ]+):)(?:(\*)?(\w\w\w {1,2}\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}\.\d+))? : ?([^\[]{1,30}\[\d*\]: ?\%[^\: ]+\:? ?.*)' flags(store-matches));
};

parser { date-parser-nofilter(format(
'%b %d %H:%M:%S.%f',
'%b %d %H:%M:%S',
'%b %d %I:%M:%S %p.%f',
'%b %d %I:%M:%S %p',
'%b %d %Y %H:%M:%S.%f',
'%b %d %Y %H:%M:%S')
template("$8"));
};
parser { date-parser-nofilter(format(
'%b %d %H:%M:%S.%f',
'%b %d %H:%M:%S',
'%b %d %I:%M:%S %p.%f',
'%b %d %I:%M:%S %p',
'%b %d %Y %H:%M:%S.%f',
'%b %d %Y %H:%M:%S')
template("$5"));
};

rewrite {
set(
"${4}",
value("HOST")
condition(not match('^\d+$', value('4')) and match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' value('4')))
);
set(
"${13}",
value("HOST")
condition(not match('^\d+$', value('13')) and match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' value('13')))
);
set(
"${15}",
value("PROGRAM")
);
set(
"${14}",
value("MESSAGE")
);
rewrite {
set(
"${3}",
value("HOST")
condition(not match('^\d+$', value('3')) and match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' value('3')))
);
set(
"${6}",
value("MESSAGE")
);
};
} else {
# All other cisco syslog
filter {
message('^<\d*> ?(?:(\d+)\: )?(?:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]): )?(?:(\d+): )?(?:(\d\d:\d\d:\d\d|\d{1,6} \d{1,2}))?(?:(\*)?((?:\w\w\w {1,2}\d{1,2} (?:\d{2,4} )?\d\d:\d\d:\d\d)(?:\.\d{3,6})?( [AP]M)?)( [A-Z]{3,3})?)? ?(?:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))? ?: ((\%[^\: ]+)\:? ?.*)' flags(store-matches));
};

rewrite {
set(
"${4}",
value("HOST")
condition(not match('^\d+$', value('4')) and match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' value('4')))
);
set(
"${13}",
value("HOST")
condition(not match('^\d+$', value('13')) and match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' value('13')))
);
set(
"${15}",
value("PROGRAM")
);
set(
"${14}",
value("MESSAGE")
);
};
parser { date-parser-nofilter(format(
'%b %d %H:%M:%S.%f',
'%b %d %H:%M:%S',
'%b %d %I:%M:%S %p.%f',
'%b %d %I:%M:%S %p',
'%b %d %Y %H:%M:%S.%f',
'%b %d %Y %H:%M:%S')
template("$8"));
};
};
};
};
};
28 changes: 22 additions & 6 deletions package/etc/conf.d/log_paths/lp-cisco_asa.conf.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,29 @@ log {
};
};

rewrite {
set("cisco_asa", value("fields.sc4s_vendor_product"));
r_set_splunk_dest_default(sourcetype("cisco:asa"), index("netfw"))
if {
filter {
message('^%FTD-\d+-43000\d: ') or
match('^%FTD-\d+-43000\d:', value("LEGACY_MSGHDR"));
};
rewrite {
set("cisco_ftd", value("fields.sc4s_vendor_product"));
r_set_splunk_dest_default(sourcetype("cisco:firepower:syslog"), index("netfw"))
};
parser {p_add_context_splunk(key("cisco_ftd")); };
parser (compliance_meta_by_source);
rewrite { set("$(template ${.splunk.sc4s_template} $(template t_msg_only))" value("MSG")); };

} else {
rewrite {
set("cisco_asa", value("fields.sc4s_vendor_product"));
r_set_splunk_dest_default(sourcetype("cisco:asa"), index("netfw"))
};
parser {p_add_context_splunk(key("cisco_asa")); };
parser (compliance_meta_by_source);
rewrite { set("$(template ${.splunk.sc4s_template} $(template t_msg_only))" value("MSG")); };

};
parser {p_add_context_splunk(key("cisco_asa")); };
parser (compliance_meta_by_source);
rewrite { set("$(template ${.splunk.sc4s_template} $(template t_msg_only))" value("MSG")); };

{{- if or (conv.ToBool (getenv "SC4S_DEST_SPLUNK_HEC_GLOBAL" "yes")) (conv.ToBool (getenv "SC4S_DEST_CISCO_ASA_HEC" "no")) }}
destination(d_hec);
Expand Down
2 changes: 1 addition & 1 deletion package/etc/conf.d/log_paths/lp-cisco_z_ios.conf.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ log {
{{- end }}

flags(flow-control,final);
};
};
27 changes: 26 additions & 1 deletion tests/test_cisco_apic.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
env = Environment()

#<11>July 22 22:45:28 apic1 %LOG_LOCAL0-2-SYSTEM_MSG [F0110][soaking][node-failed][critical][topology/pod-1/node-102/fault-F0110] Node 102 not reachable. unknown
def test_cisco_aci(record_property, setup_wordlist, setup_splunk, setup_sc4s):
def test_cisco_aci_loglocal(record_property, setup_wordlist, setup_splunk, setup_sc4s):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))

dt = datetime.datetime.now()
Expand All @@ -39,6 +39,31 @@ def test_cisco_aci(record_property, setup_wordlist, setup_splunk, setup_sc4s):

assert resultCount == 1

def test_cisco_aci_log(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 for Cisco APIC
epoch = epoch[:-7]

mt = env.from_string(
"{{ mark }} {{ bsd }} {{ host }} %LOG_-2-SYSTEM_MSG [F0110][soaking][node-failed][critical][topology/pod-1/node-102/fault-F0110]\n")
message = mt.render(mark="<165>", bsd=bsd, host=host, date=date, time=time, tzoffset=tzoffset)
sendsingle(message, setup_sc4s[0], setup_sc4s[1][514])

st = env.from_string("search _time={{ epoch }} index=netops host=\"{{ host }}\" sourcetype=\"cisco:apic:events\"")
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

#%ACLLOG-5-ACLLOG_PKTLOG
def test_cisco_aci_acl(record_property, setup_wordlist, setup_splunk, setup_sc4s):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))
Expand Down
30 changes: 30 additions & 0 deletions tests/test_cisco_asa.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,33 @@ def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_
record_property("message", message)

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
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
dt = datetime.datetime.now(datetime.timezone.utc)
iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt)

# Tune time functions
# iso from included timeutils is from local timezone; need to keep iso as UTC
iso = dt.isoformat()[0:19]
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")
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\"")
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
2 changes: 1 addition & 1 deletion tests/test_cisco_ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ def test_cisco_ios_uptime(record_property, setup_wordlist, get_host_key, setup_s
record_property("resultCount", resultCount)
record_property("message", message)

assert resultCount == 1
assert resultCount == 1

0 comments on commit a546ac8

Please sign in to comment.