/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.nifi.processors.standard; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; import org.junit.Assert; import org.junit.Test; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; public class TestParseCEF { private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); private final static String sample1 = "CEF:0|TestVendor|TestProduct|TestVersion|TestEventClassID|TestName|Low|" + // TimeStamp, String and Long "rt=Feb 09 2015 00:27:43 UTC cn3Label=Test Long cn3=9223372036854775807 " + // FloatPoint and MacAddress "cfp1=1.234 cfp1Label=Test FP Number smac=00:00:0c:07:ac:00 " + // IPv6 and String "c6a3=2001:cdba::3257:9652 c6a3Label=Test IPv6 cs1Label=Test String cs1=test test test chocolate " + // IPv4 "destinationTranslatedAddress=123.123.123.123 " + // Date without TZ "deviceCustomDate1=Feb 06 2015 13:27:43 " + // Integer and IP Address (from v4) "dpt=1234 agt=123.123.0.124 dlat=40.366633"; private final static String sample2 = "CEF:0|TestVendor|TestProduct|TestVersion|TestEventClassID|TestName|Low|" + // TimeStamp, String and Long "rt=Feb 09 2015 00:27:43 UTC cn3Label=Test Long cn3=9223372036854775807 " + // FloatPoint and MacAddress "cfp1=1.234 cfp1Label=Test FP Number smac=00:00:0c:07:ac:00 " + // IPv6 and String "c6a3=2001:cdba::3257:9652 c6a3Label=Test IPv6 cs1Label=Test String cs1=test test test chocolate " + // IPv4 "destinationTranslatedAddress=123.123.123.123 " + // Date without TZ "deviceCustomDate1=Feb 06 2015 13:27:43 " + // Integer and IP Address (from v4) "dpt=1234 agt=123.123.0.124 dlat=40.366633 " + // A JSON object inside one of CEF's custom Strings "cs2Label=JSON payload " + "cs2={\"test_test_test\": \"chocolate!\", \"what?!?\": \"Simple! test test test chocolate!\"}"; @Test public void testInvalidMessage() { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.enqueue("test test test chocolate\n".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_FAILURE, 1); } @Test public void testSuccessfulParseToAttributes() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_ATTRIBUTES); runner.enqueue(sample1.getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 1); final MockFlowFile mff = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); mff.assertAttributeEquals("cef.extension.rt", sdf.format(new Date(1423441663000L))); mff.assertAttributeEquals("cef.extension.cn3Label", "Test Long"); mff.assertAttributeEquals("cef.extension.cn3", "9223372036854775807"); mff.assertAttributeEquals("cef.extension.cfp1", "1.234"); mff.assertAttributeEquals("cef.extension.cfp1Label", "Test FP Number"); mff.assertAttributeEquals("cef.extension.smac", "00:00:0c:07:ac:00"); mff.assertAttributeEquals("cef.extension.c6a3", "2001:cdba:0:0:0:0:3257:9652"); mff.assertAttributeEquals("cef.extension.c6a3Label", "Test IPv6"); mff.assertAttributeEquals("cef.extension.cs1Label", "Test String"); mff.assertAttributeEquals("cef.extension.cs1", "test test test chocolate"); mff.assertAttributeEquals("cef.extension.destinationTranslatedAddress", "123.123.123.123"); mff.assertContentEquals(sample1.getBytes()); // Converting a field without timezone will always result on render time being dependent // on locale of the machine running this test. long eventTime = 1423229263000L; int offset = TimeZone.getDefault().getOffset(eventTime); sdf.setTimeZone(TimeZone.getDefault()); String prettyEvent = sdf.format(new Date(eventTime - offset)); mff.assertAttributeEquals("cef.extension.deviceCustomDate1",prettyEvent); mff.assertAttributeEquals("cef.extension.dpt", "1234"); mff.assertAttributeEquals("cef.extension.agt", "123.123.0.124"); mff.assertAttributeEquals("cef.extension.dlat", "40.366633"); } @Test public void testSuccessfulParseToAttributesWithUTC() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_ATTRIBUTES); runner.setProperty(ParseCEF.TIME_REPRESENTATION, ParseCEF.UTC); runner.enqueue(sample1.getBytes()); runner.run(); sdf.setTimeZone(TimeZone.getTimeZone(ParseCEF.UTC)); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 1); final MockFlowFile mff = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); mff.assertAttributeEquals("cef.extension.rt", sdf.format(new Date(1423441663000L))); // Converting a field without timezone will always result on render time being dependent // on locale of the machine running this test. long eventTime = 1423229263000L; int offset = TimeZone.getDefault().getOffset(eventTime); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String prettyEvent = sdf.format(new Date(eventTime - offset)); mff.assertAttributeEquals("cef.extension.deviceCustomDate1",prettyEvent); mff.assertContentEquals(sample1.getBytes()); } @Test public void testSuccessfulParseToContent() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_CONTENT); runner.enqueue(sample1.getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 1); final MockFlowFile mff = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); byte [] rawJson = mff.toByteArray(); JsonNode results = new ObjectMapper().readTree(rawJson); JsonNode header = results.get("header"); JsonNode extension = results.get("extension"); Assert.assertEquals("TestVendor", header.get("deviceVendor").asText()); Assert.assertEquals(sdf.format(new Date(1423441663000L)), extension.get("rt").asText()); Assert.assertEquals("Test Long", extension.get("cn3Label").asText()); Assert.assertEquals( 9223372036854775807L, extension.get("cn3").asLong()); Assert.assertTrue(extension.get("cfp1").floatValue() == 1.234F); Assert.assertEquals("Test FP Number", extension.get("cfp1Label").asText()); Assert.assertEquals("00:00:0c:07:ac:00", extension.get("smac").asText()); Assert.assertEquals("2001:cdba:0:0:0:0:3257:9652", extension.get("c6a3").asText()); Assert.assertEquals("Test IPv6", extension.get("c6a3Label").asText()); Assert.assertEquals("123.123.123.123", extension.get("destinationTranslatedAddress").asText()); Assert.assertEquals("Test String", extension.get("cs1Label").asText()); Assert.assertEquals("test test test chocolate", extension.get("cs1").asText()); } @Test public void testSuccessfulParseToContentWhenCEFContainsJSON() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_CONTENT); runner.enqueue(sample2.getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 1); final MockFlowFile mff = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); byte [] rawJson = mff.toByteArray(); JsonNode results = new ObjectMapper().readTree(rawJson); JsonNode header = results.get("header"); JsonNode extension = results.get("extension"); Assert.assertEquals("TestVendor", header.get("deviceVendor").asText()); Assert.assertEquals(sdf.format(new Date(1423441663000L)), extension.get("rt").asText()); Assert.assertEquals("Test Long", extension.get("cn3Label").asText()); Assert.assertEquals( 9223372036854775807L, extension.get("cn3").asLong()); Assert.assertTrue(extension.get("cfp1").floatValue() == 1.234F); Assert.assertEquals("Test FP Number", extension.get("cfp1Label").asText()); Assert.assertEquals("00:00:0c:07:ac:00", extension.get("smac").asText()); Assert.assertEquals("2001:cdba:0:0:0:0:3257:9652", extension.get("c6a3").asText()); Assert.assertEquals("Test IPv6", extension.get("c6a3Label").asText()); Assert.assertEquals("Test String", extension.get("cs1Label").asText()); Assert.assertEquals("test test test chocolate", extension.get("cs1").asText()); Assert.assertEquals("123.123.123.123", extension.get("destinationTranslatedAddress").asText()); JsonNode inner = new ObjectMapper().readTree(extension.get("cs2").asText()); Assert.assertEquals("chocolate!", inner.get("test_test_test").asText()); } @Test public void testSuccessfulParseToContentUTC() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_CONTENT); runner.setProperty(ParseCEF.TIME_REPRESENTATION, ParseCEF.UTC); runner.enqueue(sample1.getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 1); final MockFlowFile mff = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); byte [] rawJson = mff.toByteArray(); JsonNode results = new ObjectMapper().readTree(rawJson); JsonNode extension = results.get("extension"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); Assert.assertEquals(sdf.format(new Date(1423441663000L)), extension.get("rt").asText()); // Converting a field without timezone will always result on render time being dependent // on locale of the machine running this test. long eventTime = 1423229263000L; int offset = TimeZone.getDefault().getOffset(eventTime); // Set TZ to UTC sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String prettyEvent = sdf.format(new Date(eventTime - offset)); Assert.assertEquals(prettyEvent, extension.get("deviceCustomDate1").asText()); } @Test public void testNonEnglishDate() { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_ATTRIBUTES); runner.setProperty(ParseCEF.DATETIME_REPRESENTATION, "fr-FR"); runner.assertValid(); String sample = sample1.replace("Feb", "févr."); runner.enqueue(sample); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 1); MockFlowFile mff1 = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); mff1.assertAttributeEquals("cef.extension.rt", sdf.format(new Date(1423441663000L))); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_ATTRIBUTES); runner.setProperty(ParseCEF.DATETIME_REPRESENTATION, "et-EE"); runner.assertValid(); sample = sample1.replace("Feb", "veebr"); runner.enqueue(sample); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 2); MockFlowFile mff2 = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); mff2.assertAttributeEquals("cef.extension.rt", sdf.format(new Date(1423441663000L))); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_ATTRIBUTES); runner.setProperty(ParseCEF.DATETIME_REPRESENTATION, "ja-JP"); runner.assertValid(); SimpleDateFormat dateFormat = new SimpleDateFormat("LLLL", Locale.forLanguageTag("ja-JP") ); String jpFeb = dateFormat.format(1423441663000L); sample = sample1.replace("Feb", jpFeb ); runner.enqueue(sample); runner.run(); runner.assertAllFlowFilesTransferred(ParseCEF.REL_SUCCESS, 3); MockFlowFile mff3 = runner.getFlowFilesForRelationship(ParseCEF.REL_SUCCESS).get(0); mff3.assertAttributeEquals("cef.extension.rt", sdf.format(new Date(1423441663000L))); } @Test public void testCustomValidator() { final TestRunner runner = TestRunners.newTestRunner(new ParseCEF()); runner.setProperty(ParseCEF.FIELDS_DESTINATION, ParseCEF.DESTINATION_CONTENT); runner.setProperty(ParseCEF.TIME_REPRESENTATION, ParseCEF.UTC); runner.setProperty(ParseCEF.DATETIME_REPRESENTATION, "SPANGLISH"); runner.assertNotValid(); runner.setProperty(ParseCEF.DATETIME_REPRESENTATION, "en-US"); runner.assertValid(); Locale availableLocales[] = Locale.getAvailableLocales(); for (Locale listedLocale : availableLocales ) { if (!listedLocale.toString().isEmpty()) { String input = listedLocale.toLanguageTag(); runner.setProperty(ParseCEF.DATETIME_REPRESENTATION, input ); runner.assertValid(); } } } }