-
Notifications
You must be signed in to change notification settings - Fork 505
Conversation
|
Have you run this up in vagrant yet? |
|
FYI the PR for METRON-451 is failing at the same place. |
|
I've tested in a slimmed down single node vm (no sensors) but not in vagrant. I'm a bit limited in my resources at the moment so would appreciate if someone could validate in quick-dev as a sanity check. |
|
Currently my branch doesn't have build_utils. Going to rebase and see if that fixes the CI build. |
1bcfc5d to
04a936d
Compare
|
Testing It occurs to me I haven't outlined how to test or how I tested this code (apologies, this is my first PR). All my testing was performed on a single node vm (no sensors). This should mimic the quick-dev environment (unfortunately, I haven't had much luck with vagrant due to my primary OS being Windows). Test Steps
Future enhancements
|
nickwallen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff, Kyle! Very easy to read. Have some suggestions, but job well done.
| <166>Jan 5 08:52:35 10.22.8.216 %ASA-6-302014: Teardown TCP connection 212805593 for outside:10.22.8.223/59614(LOCAL\user.name) to inside:10.22.8.78/8102 duration 0:00:07 bytes 3433 TCP FINs (user.name) | ||
| <174>Jan 5 14:52:35 10.22.8.212 %ASA-6-302013: Built inbound TCP connection 76245503 for outside:10.22.8.233/54209 (10.22.8.233/54209) to inside:198.111.72.238/443 (198.111.72.238/443) (user.name) | ||
| <166>Jan 5 08:52:35 10.22.8.216 %ASA-6-302013: Built inbound TCP connection 212806031 for outside:10.22.8.17/58633 (10.22.8.17/58633)(LOCAL\user.name) to inside:10.22.8.12/389 (10.22.8.12/389) (user.name) | ||
| <142>Jan 5 08:52:35 10.22.8.201 %ASA-6-302014: Teardown TCP connection 488168292 for DMZ-Inside:10.22.8.51/51231 to Inside-Trunk:10.22.8.174/40004 duration 0:00:00 bytes 2103 TCP FINs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has this data been scrubbed? I just want to make sure that none of it is proprietary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took the existing test data found in .../sample/data/SampleInput/AsaOutput and added to it data from some of my test devices. The data I added has been scrubbed/anonymized.
|
|
||
| @Override | ||
| public void init() { | ||
| asaGrok = new Grok(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What features would we need to add to the GrokParser to implement ASA parsing with the GrokParser? Would be nice to learn from your experience to enhance the GrokParser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment, the GrokParser is limited to a single complied pattern that needs to match every incoming message. This works well for logs where the format is always the same (e.g. proxy logs, http access logs); however, falls short for devices with many different message types using different formats. ASAs are a good example of this as are standard Unix/Linux syslog messages.
I'm not sure what the best approach would be to solve this issue, but, ideally the GrokParser would be able to parse disparate message types based on an input pattern file (or files). I played around with the pattern discovery feature of Grok when developing this parser. It works pretty well and could be an option but seemed to slow down overall processing. That's why I ultimately landed on a static map of possible ASA message patterns.
I suppose another way would be to allow the user to specify as part of the configuration (1) a base message pattern (e.g. syslog) which should always match and then (2) an inner message pattern map which finds the best match and returns the results.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is a good idea. We can keep that in mind in enhancing the GrokParser.
| return false; | ||
| } | ||
|
|
||
| public static boolean isValidIpAddr(String ipAddress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does your isValidIpAddr function do something different than org.apache.commons.validator.routines.InetAddressValidator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, agreed. I'd just do InetAddressValidator.getInstance().isValidInet6Address(ip) || InetAddressValidator.getInstance().isValidInet4Address(ip) here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No my isValidIpAddr function is probably more rudimentary than org.apache.commons.validator.routines.InetAddressValidator. I actually switched to using the InetAddressValidator in the latest version of the code, so this is just an unused function that I will remove.
|
|
||
| String src_ip = (String) messageJson.get("src_ip"); | ||
| if (src_ip != null && ipValidator.isValid(src_ip)) | ||
| metronJson.put(Constants.Fields.SRC_ADDR.getName(), src_ip); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if there is not a valid source IP? Is that OK? Or should we blow-up in that scenario? Same goes for the other core fields; src_port, dst_addr, protocol, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been thinking about this one a bit. In the case where there is no source IP (or other core fields) in the original message, there shouldn't be an error as many message types may not contain all or any of these fields. However, in the case where the source IP (or other field) exists but is invalid, there is either a parsing issue (e.g. pattern is incorrect) or the original message is malformed. At that point, I think logging a warning would be appropriate for later followup. Are there other options to explore beyond logging? Is there a way to force that particular message into the parser_invalid or parser_error topics?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out the ipValidator function isn't adding any benefit here. The grok pattern being used on the raw message is already checking that it's a valid IP address (IPv4 or IPv6). Given that I'm going to simply remove that validation from the code as redundant.
| LOG.trace("[Metron] Final normalized message: " + metronJson.toString()); | ||
|
|
||
| } catch (Exception e) { | ||
| e.printStackTrace(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better to do a LOG.error and grab the e.getMessage() along with other contextual information. Need to make it easy to understand why it blew up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'll correct it.
| String syslogPattern = "%{CISCO_TAGGED_SYSLOG}"; | ||
| JSONObject metronJson = new JSONObject(); | ||
| List<JSONObject> messages = new ArrayList<>(); | ||
| try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make sense to break this logic up into two methods each with its own try-catch block. The first method parses the syslog portion. The second parses the syslog 'message' based on the given 'ciscotag'.
In each 'catch' we want to provide as much contextual information about what went wrong as we can. For example, if it throws an exception when parsing the syslog 'message' portion, then the error message should log the 'ciscotag' so we have more information to troubleshoot with.
Breaking this logic up into two methods each with its own try-catch block allows you to provide greater context in each failure scenario.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'll refactor.
| import java.time.ZonedDateTime; | ||
| import java.time.format.DateTimeFormatter; | ||
|
|
||
| public class SyslogUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have unit tests for these methods? Would be good to add specifically for the SyslogUtils methods.
|
|
||
| public static long parseTimestampToEpochMillis(String logTimestamp) { | ||
| if (logTimestamp.length() < 20) { | ||
| ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a Syslog timestamp always UTC? More importantly do ASAs follow the Syslog standard, if so? ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course you're right, the timestamp will not always be in UTC. ASA logs consumed via syslog (either raw off the wire or through another syslog server) will generally follow the syslog standard.
There are a number of possibilities to explore here. If we assume that we will be collecting the raw syslog from the ASAs off the wire, the timestamp will not include the timezone/offset. This code assumes the device is logging in UTC, which, to your point, is probably a bad assumption. I made this assumption because it seems to me we would want all of the timestamps indexed to be in the same timezone and the easiest way to accomplish that would be to normalize all of the telemetry data to UTC.
Question for the team. How are other parsers handling timezone? Are they passing through the device timezone?
The way I'm thinking of solving this is by adding a configuration option to the parser to specify the device timezone. (This would require that all ASAs put through the parser we configured to the same timezone though.) I would then convert the timestamp to UTC prior to writing it into the metron normalized JSON message.
Any feedback or other ideas on solving this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your idea will work just fine for now. Allow the user to configure the input timezone and the output timezone should be in UTC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As part of a future enhancement, maybe we can allow the user to define a map as part of the configuration. This maps the value of some indicator field to a timezone. For example, based on something like %ASA-6-302013 the parser will choose the appropriate input timezone.
| ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC); | ||
| int year = now.getYear(); | ||
| if (now.getDayOfYear() == 1 && !now.getMonth().toString().substring(0,3).equals(logTimestamp.substring(0,3).toUpperCase())) | ||
| year--; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic stands out to me as not totally obvious. Would be good to comment why you are doing this. Under what conditions do we need to year-- and why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I see how this is not entirely obvious. I'm trying to solve an edge case here where a message comes in for parsing without a year in the timestamp on January 1st but the message was actually generated on the device on December 31st. I'll add in some comments for clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha. So anything that comes in on the first day of the year, with a month that is not January, will be backdated.
If something comes in on the 2nd day of the year, with a month of December, it will NOT be backdated. The period of time that we are willing to backdate, is effectively 1 day currently.
Maybe that time period needs to be configurable. The user defines the period of time, 1 day, 2 days, 1 week, after the beginning of the year in which messages can possibly be backdated.
Are there certain conditions under which the logic should blow-up and error? What if we are going to backdate a message where the month is July? Should we just do that or should we error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late comment, but I perceive a small problem here.
- Using criteria "now == day#1 in UTC" has an unknown relationship to the incoming data, depending on the source time zone. You might be 24 hrs ahead of the source, or you might be one second ahead. So if there might be a delay in obtaining the logs, due perhaps to a half-day network failure at Metron's end, you will backdate logs from some sources but not from others, depending on their geographic location. This argument is not alleviated by changing from "day Initial code for a website #1" to "day Initial code for a website #1 or replace opensoc-streaming version 0.4BETA with 0.6BETA 8e7a6b4ad9febbc… #2", the specifics just change somewhat. Also, log ingest can be delayed for months rather than days, and we want to be able to accommodate replay or historical ingest. I would suggest instead of using the current criterion (now.getDayOfYear() < "configurable.number.of.days" && now.getMonth() != logTimeStamp.getMonth()) that we use the criterion that the logTimestamp calculated with "this year" is significantly in the future from "now". I suggest "more than 4 days in the future" is a good criterion; that leaves 1 day for NTP error on the logging side, 1 day for NTP error on the Metron side, 1 day for possible leap year artifacts, and 1 day for Murphy's Law. With this rule, year-less logs can be correctly ingested from up to one year (less 4 days) in the past.
- For the stated goal, that's sufficient. We don't need to make the "future limit" configurable. However, there is also the use case of ingesting year-less data more than a year old. The only way to enable that, that I can see, would be configuring the source with a year (or an age) along with a timezone. Doesn't work for on-going sources, but would work for a source that ingests a chunk of history of known age.
- BTW, is the ZonedDateTime.parse() method robust if we accidentally hand it a FEB 29 date from a non-leap year? Since we are trying to synthesize the "year" information, it could happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of checking how far the date in the current year would be in the future and basing the back date decision on that. Let me work on that.
cestella
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love it! Thanks for the contribution. Just a few comments, but great job.
| ,DST_PORT("ip_dst_port") | ||
| ,PROTOCOL("protocol") | ||
| ,TIMESTAMP("timestamp") | ||
| ,ORIGINAL("original_string") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I particularly like this one. We should refactor the GrokParser to use it as a follow-on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I think we've needed something like this for a while. it will help standardize our parsing. great job noticing this. I am definitely +1 on refactoring grok to look like this
| - { topic: "bro", num_partitions: 1, replication_factor: 1, retention_gb: 10 } | ||
| - { topic: "yaf", num_partitions: 1, replication_factor: 1, retention_gb: 10 } | ||
| - { topic: "snort", num_partitions: 1, replication_factor: 1, retention_gb: 10 } | ||
| - { topic: "asa", num_partitions: 1, replication_factor: 1, retention_gb: 10 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we create the kafka topic if we aren't starting the sensor as part of the default set of sensors? Shouldn't we handle this like squid, where we have the user create the topic if they set up the sensor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I was thinking about building out the monit scripts, etc to make this as easy as possible for the user to deploy out-of-the-box, but that's a future PR. Is that something that would be valuable to folks? Either way, I can remove this from the current PR.
| return false; | ||
| } | ||
|
|
||
| public static boolean isValidIpAddr(String ipAddress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, agreed. I'd just do InetAddressValidator.getInstance().isValidInet6Address(ip) || InetAddressValidator.getInstance().isValidInet4Address(ip) here.
| } | ||
|
|
||
| @Test | ||
| public void testCISCOFW106023() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have test-cases covering situations where:
- IP's are malformed
- IP's are IPv6
- Data is garbage
| List<JSONObject> messages = new ArrayList<>(); | ||
| try { | ||
| String logLine = new String(rawMessage, "UTF-8"); | ||
| LOG.trace("[Metron] Started parsing raw message: " + logLine); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure all the LOG.trace is necessary. At the very least you should use SLF4J's parameterized messages to avoid the cost of parameter construction. SLF4J FAQ
I thought I already commented on this, but Github seems to have lost it. Sorry if this ends up being a dup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to leave the additional logging in for assistance in debugging when adding new ASA message types to the parser in the future. I've updated the code to use the SLF4J parameterized messages as suggested.
|
@nickwallen @cestella Thanks very much for the feedback! Much appreciated. I'll get started on these changes and respond to your questions as soon as I can. |
|
Not entirely sure why the CI build failed. The error was: Slightly earlier in the log: I'm thinking this is similar to @ottobackwards issue on #303. Could it be anything else or should I just try a close and re-open? |
|
I would close and re-open. As our test suite has expanded and is more demanding, at certain times Travis will fail the build when there is not really a problem. We need to figure out how to fix this problem, but right now I'd try a reboot. |
|
Thanks. Looks like re-opening did the trick. I've done my best to incorporate everyone's feedback into this version. Re-tested in single node vm successfully. |
|
@kylerichardson When you say "tested in single node vm", what do you mean exactly? Do you not use the Vagrant deployment mechanism at |
| "parserClassName": "org.apache.metron.parsers.asa.BasicAsaParser", | ||
| "sensorTopic": "asa", | ||
| "parserConfig": { | ||
| "deviceTimeZone": "UTC-05:00" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make the default UTC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, absolutely. I'll remove it. I left this in as an example. If no deviceTimeZone is provided, the code will default to UTC.
|
@nickwallen Apologies, I should have been more specific. I tested using the same steps provided earlier in the PR. That said, my "single node vm" testing is not done with vagrant. Currently I'm not able to successfully use the quick dev environment based on my setup (e.g. Windows). I'm working to remedy that. For "single node vm" testing, I actually run two vms, one Fedora host which I do development on and use to run the ansible deployment and a second Centos 6 (base install from snapshot) host which I deploy Metron onto. For testing this PR, I deployed Metron without the sensors to by Centos 6 vm for testing and ran through the steps provided above. |
nickwallen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there. Looking really good. Just a few small issues with the tests, mainly.
| return convertToEpochMillis(logTimestamp, DateTimeFormatter.ISO_OFFSET_DATE_TIME); | ||
|
|
||
| else | ||
| throw new ParseException(String.format("Unsupported date format: '%s'", logTimestamp)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, any reason we're using a checked exception here? In other places we're just using run time exceptions. The ParseException that you created is used only for this, I believe.
Not a big deal either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thought here was that there may be some situations where we want to handle a parsing error without blowing up and sending the message to the error queue. It was a bit of "future proofing" on my part I suppose.
For consistency, would it be better to revert to using a RuntimeException?
| try { | ||
| JSONObject asaJson = asaParser.parse(rawMessage.getBytes()).get(0); | ||
| } catch (RuntimeException e) { | ||
| assertTrue(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this test will ever fail. You can get rid of the try/catch and just change the annotation. That way the test will fail if a RunTimeException is not thrown.
@Test (expected = RunTimeException.class)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, I'd prefer using JUnit's Rules to test this. RuntimeExceptions are fairly generic, and Rules would allow the specific exception message to be verified.
e.g.
TestThing testThing = new TestThing();
thrown.expect(NotFoundException.class);
thrown.expectMessage(startsWith("some Message"));
https://github.com/junit-team/junit4/wiki/exception-testing
|
|
||
| import static org.junit.Assert.*; | ||
|
|
||
| public class SyslogUtilsTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A tricky, but necessary, part of your timestamp logic is rolling the year backwards in certain cases. Are there specific tests that hit on that? Maybe I am missing them. We need to make sure we cover all the edges on those scenarios.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. There currently isn't test coverage for that logic.
I was trying to avoid having to add a dependency on a Clock object but it may be the only way to throughly test this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it suffice to Mock the ZonedDateTime.now() call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, in theory that is.
I tried doing just that with PowerMock and Mockito; unfortunately, it seems there is a bug in the underlying javassist library that doesn't play well with the new java.time classes.
The issue is reportedly fixed in Javassist 3.20.0-GA; however, it doesn't appear that PowerMock has updated to this version.
Reference: JASSIST-246 and powermock/powermock#557
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bummer. Sorry, I have no advice. Any Mockito experts out there?
| } | ||
|
|
||
| private long getParsedEpochMillis(String originalTimestamp) { | ||
| try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no need to try/catch here. Just have the method throw ParseException. Any of your test methods can also throw ParseException. This simplifies the logic and JUnit will fail the test if a ParseException is thrown.
| try { | ||
| asaGrok.addPatternFromReader(new InputStreamReader(patternStream)); | ||
| } catch (GrokException e) { | ||
| LOG.error("[Metron] Failed to load grok patterns from jar", e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would want to throw a runtime exception after the LOG. That is, if the GrokParser itself is a good guide for expected behavior.
| asaGrok = new Grok(); | ||
| InputStream patternStream = this.getClass().getClassLoader().getResourceAsStream("patterns/asa"); | ||
| try { | ||
| asaGrok.addPatternFromReader(new InputStreamReader(patternStream)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just calling this out for other's awareness, but this will only load the Grok pattern from the classpath. The GrokParser seems to work much harder looking for a pattern.
Maybe that is what we want in this case, since changing the Grok pattern might not play well with the rest of the Java code involved with Kyle's parser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My two cents...
In this case, the parser code is tightly coupled to the pattern file, which is why I chose to load it from the classpath.
I could see a couple of other options:
(1) Add a parser config option to the full path of the pattern file
(2) Wait for #308 to be merged and add the patterns as config options
The problem I see with option 2 is that the pattern file used for the ASAs has a lot of lines and might be a bit ugly in the parser config.
With either of these options, another parser config option would need to be added to hold the CISCOTAG to pattern name mapping.
nickwallen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking very good. Almost there. Just a few changes with the tests.
|
Thanks for bearing with me. I really appreciate the feedback and direction. I should be able to get these changes in later tonight after I finish up my "day job" :). |
|
I added a comment above, to SyslogUtils.java line 36, which the system did not email to the list, probably because I immediately edited it to fix a format error. @kylerichardson please consider it. Thanks. |
|
Whew, got the CI build to finally pass. All integration and unit tests are passing. I've also re-testing in the single node vm environment I described above. |
|
Any other feedback or suggestions for me? |
|
Testing this in production this week on production hardware. Will have feedback in the next few days |
| LOGLEVEL ([A|a]lert|ALERT|[T|t]race|TRACE|[D|d]ebug|DEBUG|[N|n]otice|NOTICE|[I|i]nfo|INFO|[W|w]arn?(?:ing)?|WARN?(?:ING)?|[E|e]rr?(?:or)?|ERR?(?:OR)?|[C|c]rit?(?:ical)?|CRIT?(?:ICAL)?|[F|f]atal|FATAL|[S|s]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?) | ||
|
|
||
| #== Cisco ASA == | ||
| CISCO_TAGGED_SYSLOG ^<%{POSINT:syslog_pri}>%{CISCOTIMESTAMP:timestamp}( %{SYSLOGHOST:sysloghost})? ?:? %%{CISCOTAG:ciscotag}: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to put the entire logstash patterns file here? i think we can just put the ASA-specific lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ASA patterns build off of several of the more generic patterns referenced earlier in the file; however, I should be able to reduce it down to just the ones being used.
|
Still testing...bare with me |
|
@james-sirota No worries. Thanks for testing! |
|
+1. Great job. Any more revisions you want to make to this? Or are we good to commit? |
Summary of changes: - Complete rewrite of ASA parser including new test suite - ZK configurations for ease of topology deployment (parser and enrichment) - Add field constant for original_string in metron-common - Minor changes to ASA patterns file for (1) Syslog severity/facility capture (2) Interface capture on CISCOFW106006_106007_106010 - Updates to various POMs to allow easier validation of logging during unit testing (1) Exclusions for slf4j-log4j12 on various dependencies for metron-parsers and metron-integration-test (2) Explicit dependency on slf4j-api for metron-parsers (3) Test dependency on slf4j-simple for metron-parsers
Includes the following: - Static map for ASA message patterns (vs pattern discovery) - Minor changes to ASA patterns file - Broke out common syslog parsing elements - Broke out reusable field validations
Includes the following: - Extend BasicParser - Handle both types of syslog timestamps (with and without year) - Include integration test and supporting sample data
Changes include: (1) New/additional unit tests (2) Reworked Syslog Timestamp (no year) logic (3) Enhanced error checking and logging (introduced new ParseException)
db86866 to
12cd31e
Compare
|
Rebased against master to incorporate the global junit version change. Should be good to go now pending Travis. Thanks again to everyone for all of the suggestions, feedback, and testing. |
|
Ok, need some helping figuring out why the CI build keeps failing... I get several of these at the end of the log: and prior to that I see: This occurred for both of the CI builds since I rebased to the latest master. Any ideas? |
|
A big thank you to @ottobackwards for helping to troubleshoot the CI build fails. This should be good to go now. |
|
+1 Great contribution |
I've rewritten the ASA parser which can be extended, as needed, to new ASA message types by editing the bundled asa patterns file and the static map used for grok patterns in the code. I've also tried to make it easier to deploy the asa topology by including zookeeper config files and creating the kafka topic during metron install. Sample data is also included for integration testing.