Implement text syslog record parsing

This commit is contained in:
Marko Zivanovic
2015-09-02 16:00:19 +02:00
parent eb6448f859
commit 13d5266c37
11 changed files with 606 additions and 2 deletions
+2
View File
@@ -1,8 +1,10 @@
cmake_minimum_required(VERSION 2.8)
project(syslog-bulk-uploader)
set(CMAKE_CXX_FLAGS "-g -Wall")
add_definitions(-std=c++11)
add_subdirectory(src)
add_subdirectory(test)
enable_testing()
add_test(NAME SyslogBulkUploaderTests COMMAND SyslogBulkUploaderTests)
add_test(NAME SyslogMessageTests COMMAND SyslogMessageTests)
+13 -1
View File
@@ -1,5 +1,17 @@
find_package(Boost COMPONENTS date_time REQUIRED)
include_directories(
${Boost_INLUDE_DIRS}
)
add_library(slbu-lib
SyslogBulkUploader.cpp
Facility.cpp
Severity.cpp
SyslogMessage.cpp
)
add_executable(syslog-bulk-uploader main.cpp)
target_link_libraries(syslog-bulk-uploader slbu-lib)
target_link_libraries(syslog-bulk-uploader
slbu-lib
${Boost_DATE_TIME_LIBRARY}
)
+99
View File
@@ -0,0 +1,99 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the std::string("Software")), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED std::string("AS IS"), WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <boost/algorithm/string.hpp>
#include "Facility.h"
const std::string Facility::readFromStream(std::istream& src) {
std::string ret;
while (src) {
std::istream::char_type c = src.get();
if (c == '.') {
break;
} else {
if (c != ' ' && c != '\t') {
ret.push_back(c);
}
}
}
return ret;
}
const Facility::Value Facility::readFromString(const std::string& src) {
Facility::Value ret;
if (boost::iequals(src, std::string("Kern"))) {
ret = Facility::Value::Kern;
} else if (boost::iequals(src, std::string("User"))) {
ret = Facility::Value::User;
} else if (boost::iequals(src, std::string("Mail"))) {
ret = Facility::Value::Mail;
} else if (boost::iequals(src, std::string("Daemon"))) {
ret = Facility::Value::Daemon;
} else if (boost::iequals(src, std::string("Auth"))) {
ret = Facility::Value::Auth;
} else if (boost::iequals(src, std::string("Syslog"))) {
ret = Facility::Value::Syslog;
} else if (boost::iequals(src, std::string("Lpr"))) {
ret = Facility::Value::Lpr;
} else if (boost::iequals(src, std::string("News"))) {
ret = Facility::Value::News;
} else if (boost::iequals(src, std::string("Uucp"))) {
ret = Facility::Value::Uucp;
} else if (boost::iequals(src, std::string("Clock"))) {
ret = Facility::Value::Clock;
} else if (boost::iequals(src, std::string("Authpriv"))) {
ret = Facility::Value::Authpriv;
} else if (boost::iequals(src, std::string("Ftp"))) {
ret = Facility::Value::Ftp;
} else if (boost::iequals(src, std::string("Ntp"))) {
ret = Facility::Value::Ntp;
} else if (boost::iequals(src, std::string("LogAudit"))) {
ret = Facility::Value::LogAudit;
} else if (boost::iequals(src, std::string("LogAlert"))) {
ret = Facility::Value::LogAlert;
} else if (boost::iequals(src, std::string("Cron"))) {
ret = Facility::Value::Cron;
} else if (boost::iequals(src, std::string("Local0"))) {
ret = Facility::Value::Local0;
} else if (boost::iequals(src, std::string("Local1"))) {
ret = Facility::Value::Local1;
} else if (boost::iequals(src, std::string("Local2"))) {
ret = Facility::Value::Local2;
} else if (boost::iequals(src, std::string("Local3"))) {
ret = Facility::Value::Local3;
} else if (boost::iequals(src, std::string("Local4"))) {
ret = Facility::Value::Local4;
} else if (boost::iequals(src, std::string("Local5"))) {
ret = Facility::Value::Local5;
} else if (boost::iequals(src, std::string("Local6"))) {
ret = Facility::Value::Local6;
} else if (boost::iequals(src, std::string("Local7"))) {
ret = Facility::Value::Local7;
} else {
throw "Illegal facility value: " + src;
};
return ret;
}
+73
View File
@@ -0,0 +1,73 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef FACILITY_H
#define FACILITY_H
#include <istream>
class Facility {
public:
Facility(const char* src) : Facility(std::string(src)) {
};
Facility(const std::string& source) : _value(readFromString(source)) {
};
Facility(std::istream& source) : Facility(readFromStream(source)) {
};
Facility(const Facility & orig) : _value(orig._value) {
};
bool operator!=(const Facility & right) const {
bool result = !(*this == right); // Reuse equals operator
return result;
}
bool operator==(const Facility & right) const {
return _value == right._value;
}
friend std::ostream& operator<<(std::ostream& os, const Facility& obj) {
os << obj._value;
return os;
}
virtual ~Facility() {
};
private:
enum Value {
Kern = 0, User = 1, Mail = 2, Daemon = 3, Auth = 4, Syslog = 5, Lpr = 6, News = 7, Uucp = 8, Clock = 9,
Authpriv = 10, Ftp = 11, Ntp = 12, LogAudit = 13, LogAlert = 14, Cron = 15, Local0 = 16, Local1 = 17,
Local2 = 18, Local3 = 19, Local4 = 20, Local5 = 21, Local6 = 22, Local7 = 23
};
const Value _value;
const std::string readFromStream(std::istream&);
const Value readFromString(const std::string&);
};
#endif /* FACILITY_H */
+44
View File
@@ -0,0 +1,44 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef READER_H
#define READER_H
#include <memory>
#include <boost/noncopyable.hpp>
class Reader : boost::noncopyable {
public:
virtual ~Reader() {
};
virtual std::shared_ptr<SyslogMessage> nextMessage() = 0;
private:
};
#endif /* READER_H */
+65
View File
@@ -0,0 +1,65 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <boost/algorithm/string.hpp>
#include "Severity.h"
const std::string Severity::readFromStream(std::istream& src) {
std::string ret;
while (src) {
std::istream::char_type c = src.get();
if (c == ' ' || c == '\t') {
break;
} else {
ret.push_back(c);
}
}
return ret;
}
const Severity::Value Severity::readFromString(const std::string& src) {
Severity::Value ret;
if (boost::iequals(src, std::string("Emergency"))) {
ret = Severity::Value::Emergency;
} else if (boost::iequals(src, std::string("Alert"))) {
ret = Severity::Value::Alert;
} else if (boost::iequals(src, std::string("Critical"))) {
ret = Severity::Value::Critical;
} else if (boost::iequals(src, std::string("Error"))) {
ret = Severity::Value::Error;
} else if (boost::iequals(src, std::string("Warning"))) {
ret = Severity::Value::Warning;
} else if (boost::iequals(src, std::string("Notice"))) {
ret = Severity::Value::Notice;
} else if (boost::iequals(src, std::string("Informational"))) {
ret = Severity::Value::Informational;
} else if (boost::iequals(src, std::string("Debug"))) {
ret = Severity::Value::Debug;
} else {
throw "Illegal severity value: " + src;
};
return ret;
}
+73
View File
@@ -0,0 +1,73 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef SEVERITY_H
#define SEVERITY_H
#include <istream>
class Severity {
public:
Severity(const char* src) : Severity(std::string(src)) {
};
Severity(const std::string& src) : _value(readFromString(src)) {
};
Severity(std::istream& source) : Severity(readFromStream(source)) {
};
Severity(const Severity& orig) : _value(orig._value) {
};
bool operator!=(const Severity& right) const {
bool result = !(*this == right); // Reuse equals operator
return result;
}
bool operator==(const Severity& right) const {
return _value == right._value;
}
virtual ~Severity() {
};
friend std::ostream& operator<<(std::ostream& os, const Severity& obj) {
os << obj._value;
return os;
}
private:
enum Value {
Emergency = 0, Alert = 1, Critical = 2, Error = 3, Warning = 4, Notice = 5, Informational = 6, Debug = 7
};
const Value _value;
const std::string readFromStream(std::istream& source);
const Value readFromString(const std::string& src);
};
#endif /* SEVERITY_H */
+89
View File
@@ -0,0 +1,89 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "SyslogMessage.h"
void skipWhitespace(std::istream& src) {
bool whitespace = true;
while (src && whitespace) {
std::istream::char_type c = src.peek();
if (c == ' ' || c == '\t') {
src.get();
continue;
} else {
whitespace = false;
}
}
}
const boost::posix_time::ptime SyslogMessage::readTimestamp(std::istream& src) {
int ws = 0;
std::string ts;
while (src) {
std::istream::char_type c = src.get();
if (c == ' ' || c == '\t') {
ws++;
}
if (ws == 2) {
break;
} else {
ts.push_back(c);
}
}
return boost::posix_time::time_from_string(ts);
};
const Facility SyslogMessage::readFacility(std::istream& src) {
return Facility(src);
};
const Severity SyslogMessage::readSeverity(std::istream& src) {
return Severity(src);
};
const std::string SyslogMessage::readSource(std::istream& src) {
std::string ret;
skipWhitespace(src);
while (src) {
std::istream::char_type c = src.get();
if (c == ' ' || c == '\t') {
break;
} else {
ret.push_back(c);
}
}
return ret;
};
const std::string SyslogMessage::readMessage(std::istream & src) {
std::string ret;
skipWhitespace(src);
while (src) {
std::istream::char_type c = src.get();
if (!src.eof()) {
ret.push_back(c);
}
}
return ret;
};
+93
View File
@@ -0,0 +1,93 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef SYSLOGMESSAGE_H
#define SYSLOGMESSAGE_H
#include <boost/date_time/posix_time/posix_time.hpp>
#include "Facility.h"
#include "Severity.h"
class SyslogMessage {
public:
SyslogMessage(std::istream& src) : _timestamp(readTimestamp(src)), _facility(readFacility(src)),
_severity(readSeverity(src)), _source(readSource(src)), _message(readMessage(src)) {
};
SyslogMessage(const SyslogMessage& orig) : _timestamp(orig._timestamp), _facility(orig._facility),
_severity(orig._severity), _source(orig._source), _message(orig._message) {
};
virtual ~SyslogMessage() {
};
const Facility facility() const {
return _facility;
}
const std::string message() const {
return _message;
}
const Severity severity() const {
return _severity;
}
const std::string source() const {
return _source;
}
const boost::posix_time::ptime timestamp() const {
return _timestamp;
}
friend std::ostream& operator<<(std::ostream& os, const SyslogMessage& obj) {
os << "SyslogMessage{timestamp:" << obj._timestamp << ", facility:" << obj._facility <<
", severity:" << obj._severity << ",source:" << obj._source << ",message:" << obj._message << "}";
return os;
}
private:
const boost::posix_time::ptime _timestamp;
const Facility _facility;
const Severity _severity;
const std::string _source;
const std::string _message;
const boost::posix_time::ptime readTimestamp(std::istream&);
const Facility readFacility(std::istream&);
const Severity readSeverity(std::istream&);
const std::string readSource(std::istream&);
const std::string readMessage(std::istream&);
};
#endif /* SYSLOGMESSAGE_H */
+9 -1
View File
@@ -1,12 +1,20 @@
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
find_package(Boost COMPONENTS unit_test_framework date_time REQUIRED)
include_directories(
${TEST_SOURCE_DIR/src}
${Boost_INLUDE_DIRS}
)
add_definitions(-DBOOST_TEST_DYN_LINK)
add_executable(SyslogBulkUploaderTests SyslogBulkUploaderTests.cpp)
target_link_libraries(SyslogBulkUploaderTests
slbu-lib
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
)
add_executable(SyslogMessageTests SyslogMessageTests.cpp)
target_link_libraries(SyslogMessageTests
slbu-lib
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
${Boost_DATE_TIME_LIBRARY}
)
+46
View File
@@ -0,0 +1,46 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Živanović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "../src/SyslogMessage.h"
#define BOOST_TEST_MODULE SyslogMessageTests
#include <boost/test/unit_test.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
BOOST_AUTO_TEST_CASE(constructor_and_getters) {
std::stringstream source("2015-09-02 13:33:11 Local4.Critical 192.168.0.1 Kiwi_Syslog_Server %ASA-2-106007: Deny inbound UDP from 138.28.4.18/22084 to 9.28.3.28/53 due to DNS Query");
boost::posix_time::ptime timestamp(boost::posix_time::time_from_string("2015-09-02 13:33:11"));
SyslogMessage m(source);
BOOST_CHECK_EQUAL(m.timestamp(), timestamp);
BOOST_CHECK_EQUAL(m.facility(), Facility("Local4"));
BOOST_CHECK_EQUAL(m.severity(), Severity("Critical"));
BOOST_CHECK_EQUAL(m.source(), "192.168.0.1");
BOOST_CHECK_EQUAL(m.message(), "Kiwi_Syslog_Server %ASA-2-106007: Deny inbound UDP from 138.28.4.18/22084 to 9.28.3.28/53 due to DNS Query");
}
BOOST_AUTO_TEST_CASE(invalid_params) {
BOOST_CHECK_THROW(Facility("invalid"), std::string);
BOOST_CHECK_THROW(Severity("invalid"), std::string);
BOOST_CHECK_NO_THROW(Facility("Local0"));
BOOST_CHECK_NO_THROW(Severity("Critical"));
}