mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-30 11:44:32 +03:00
Writes audit log in parallel mode
First version still missing the index among other things
This commit is contained in:
@@ -126,7 +126,7 @@ class Assay {
|
|||||||
int processResponseBody();
|
int processResponseBody();
|
||||||
int appendResponseBody(const unsigned char *body, size_t size);
|
int appendResponseBody(const unsigned char *body, size_t size);
|
||||||
|
|
||||||
int processLogging();
|
int processLogging(int status_code);
|
||||||
|
|
||||||
ModSecurityIntervention *intervention();
|
ModSecurityIntervention *intervention();
|
||||||
|
|
||||||
@@ -149,12 +149,14 @@ class Assay {
|
|||||||
bool save_in_auditlog;
|
bool save_in_auditlog;
|
||||||
bool do_not_save_in_auditlog;
|
bool do_not_save_in_auditlog;
|
||||||
|
|
||||||
int http_code_returned;
|
int httpCodeReturned;
|
||||||
|
|
||||||
std::string to_json(int parts);
|
std::string to_json(int parts);
|
||||||
|
|
||||||
private:
|
|
||||||
std::string id;
|
std::string id;
|
||||||
|
time_t timeStamp;
|
||||||
|
|
||||||
|
private:
|
||||||
std::ofstream myfile;
|
std::ofstream myfile;
|
||||||
Rules *m_rules;
|
Rules *m_rules;
|
||||||
ModSecurity *m_ms;
|
ModSecurity *m_ms;
|
||||||
@@ -166,7 +168,6 @@ class Assay {
|
|||||||
const char *m_uri;
|
const char *m_uri;
|
||||||
const char *m_protocol;
|
const char *m_protocol;
|
||||||
const char *m_httpVersion;
|
const char *m_httpVersion;
|
||||||
time_t m_timeStamp;
|
|
||||||
|
|
||||||
std::ostringstream m_requestBody;
|
std::ostringstream m_requestBody;
|
||||||
std::ostringstream m_responseBody;
|
std::ostringstream m_responseBody;
|
||||||
@@ -236,7 +237,7 @@ void msc_assay_cleanup(Assay *assay);
|
|||||||
ModSecurityIntervention *msc_intervention(Assay *assay);
|
ModSecurityIntervention *msc_intervention(Assay *assay);
|
||||||
|
|
||||||
/** @ingroup ModSecurity_C_API */
|
/** @ingroup ModSecurity_C_API */
|
||||||
int msc_process_logging(Assay *assay);
|
int msc_process_logging(Assay *assay, int code);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
18
src/assay.cc
18
src/assay.cc
@@ -87,10 +87,10 @@ Assay::Assay(ModSecurity *ms, Rules *rules)
|
|||||||
m_rules(rules),
|
m_rules(rules),
|
||||||
save_in_auditlog(false),
|
save_in_auditlog(false),
|
||||||
do_not_save_in_auditlog(false),
|
do_not_save_in_auditlog(false),
|
||||||
m_timeStamp(std::time(NULL)),
|
timeStamp(std::time(NULL)),
|
||||||
http_code_returned(200),
|
httpCodeReturned(200),
|
||||||
m_ms(ms) {
|
m_ms(ms) {
|
||||||
id = std::to_string(this->m_timeStamp) + \
|
id = std::to_string(this->timeStamp) + \
|
||||||
std::to_string(generate_assay_unique_id());
|
std::to_string(generate_assay_unique_id());
|
||||||
m_rules->incrementReferenceCount();
|
m_rules->incrementReferenceCount();
|
||||||
this->debug(4, "Initialising transaction");
|
this->debug(4, "Initialising transaction");
|
||||||
@@ -617,8 +617,9 @@ int Assay::getResponseBodyLenth() {
|
|||||||
* @retval false Operation failed.
|
* @retval false Operation failed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int Assay::processLogging() {
|
int Assay::processLogging(int returned_code) {
|
||||||
debug(4, "Starting phase LOGGING. (SecRules 5)");
|
debug(4, "Starting phase LOGGING. (SecRules 5)");
|
||||||
|
this->httpCodeReturned = returned_code;
|
||||||
this->m_rules->evaluate(ModSecurity::LoggingPhase, this);
|
this->m_rules->evaluate(ModSecurity::LoggingPhase, this);
|
||||||
|
|
||||||
/* If relevant, save this assay information at the audit_logs */
|
/* If relevant, save this assay information at the audit_logs */
|
||||||
@@ -691,7 +692,7 @@ std::string Assay::to_json(int parts) {
|
|||||||
const unsigned char *buf;
|
const unsigned char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
yajl_gen g = NULL;
|
yajl_gen g = NULL;
|
||||||
std::string ts = ascTime(&m_timeStamp).c_str();
|
std::string ts = ascTime(&timeStamp).c_str();
|
||||||
std::string uniqueId = UniqueId::uniqueId();
|
std::string uniqueId = UniqueId::uniqueId();
|
||||||
|
|
||||||
g = yajl_gen_alloc(NULL);
|
g = yajl_gen_alloc(NULL);
|
||||||
@@ -754,7 +755,7 @@ std::string Assay::to_json(int parts) {
|
|||||||
yajl_gen_map_open(g);
|
yajl_gen_map_open(g);
|
||||||
|
|
||||||
LOGFY_ADD("body", this->m_responseBody.str().c_str());
|
LOGFY_ADD("body", this->m_responseBody.str().c_str());
|
||||||
LOGFY_ADD_NUM("http_code", http_code_returned);
|
LOGFY_ADD_NUM("http_code", httpCodeReturned);
|
||||||
|
|
||||||
/* response headers */
|
/* response headers */
|
||||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>("headers"),
|
yajl_gen_string(g, reinterpret_cast<const unsigned char*>("headers"),
|
||||||
@@ -1251,14 +1252,15 @@ extern "C" int msc_get_response_body_length(Assay *assay) {
|
|||||||
* delivered prior to the execution of this function.
|
* delivered prior to the execution of this function.
|
||||||
*
|
*
|
||||||
* @param assay ModSecurity assay.
|
* @param assay ModSecurity assay.
|
||||||
|
* @param code HTTP code returned to the user.
|
||||||
*
|
*
|
||||||
* @returns If the operation was successful or not.
|
* @returns If the operation was successful or not.
|
||||||
* @retval 1 Operation was successful.
|
* @retval 1 Operation was successful.
|
||||||
* @retval 0 Operation failed.
|
* @retval 0 Operation failed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
extern "C" int msc_process_logging(Assay *assay) {
|
extern "C" int msc_process_logging(Assay *assay, int code) {
|
||||||
return assay->processLogging();
|
return assay->processLogging(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@@ -102,11 +102,11 @@ bool AuditLog::setType(AuditLogType audit_type) {
|
|||||||
|
|
||||||
bool AuditLog::init() {
|
bool AuditLog::init() {
|
||||||
if (m_type == ParallelAuditLogType) {
|
if (m_type == ParallelAuditLogType) {
|
||||||
m_writer = new AuditLogWriterParallel();
|
m_writer = new AuditLogWriterParallel(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type == SerialAuditLogType) {
|
if (m_type == SerialAuditLogType) {
|
||||||
m_writer = new AuditLogWriterSerial();
|
m_writer = new AuditLogWriterSerial(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_writer == NULL || m_writer->init() == false) {
|
if (m_writer == NULL || m_writer->init() == false) {
|
||||||
@@ -134,7 +134,7 @@ bool AuditLog::isRelevant(int status) {
|
|||||||
|
|
||||||
|
|
||||||
bool AuditLog::saveIfRelevant(Assay *assay) {
|
bool AuditLog::saveIfRelevant(Assay *assay) {
|
||||||
if (this->isRelevant(assay->http_code_returned) == false &&
|
if (this->isRelevant(assay->httpCodeReturned) == false &&
|
||||||
assay->save_in_auditlog == false) {
|
assay->save_in_auditlog == false) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -148,9 +148,7 @@ bool AuditLog::saveIfRelevant(Assay *assay) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string log = assay->to_json(0);
|
m_writer->write(assay);
|
||||||
|
|
||||||
m_writer->write(log);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -162,12 +162,13 @@ class AuditLog {
|
|||||||
bool saveIfRelevant(Assay *assay);
|
bool saveIfRelevant(Assay *assay);
|
||||||
bool isRelevant(int status);
|
bool isRelevant(int status);
|
||||||
|
|
||||||
private:
|
|
||||||
AuditLogStatus m_status;
|
|
||||||
std::string m_path1;
|
std::string m_path1;
|
||||||
std::string m_path2;
|
std::string m_path2;
|
||||||
std::string m_storage_dir;
|
std::string m_storage_dir;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AuditLogStatus m_status;
|
||||||
|
|
||||||
int m_file_permissions;
|
int m_file_permissions;
|
||||||
int m_storage_permission;
|
int m_storage_permission;
|
||||||
|
|
||||||
|
@@ -33,8 +33,8 @@ std::string AuditLogWriter::file_name(const std::string& unique_id) {
|
|||||||
* Temporary print the log into the std::cout to debug purposes.
|
* Temporary print the log into the std::cout to debug purposes.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool AuditLogWriter::write(const std::string& log) {
|
bool AuditLogWriter::write(Assay *assay) {
|
||||||
std::cout << log << std::endl;
|
std::cout << assay->to_json(0) << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,20 +23,28 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "modsecurity/assay.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
|
class AuditLog;
|
||||||
|
|
||||||
/** @ingroup ModSecurity_CPP_API */
|
/** @ingroup ModSecurity_CPP_API */
|
||||||
class AuditLogWriter : public std::ofstream {
|
class AuditLogWriter : public std::ofstream {
|
||||||
public:
|
public:
|
||||||
AuditLogWriter() { }
|
explicit AuditLogWriter(AuditLog *audit)
|
||||||
|
: m_audit(audit) { }
|
||||||
|
|
||||||
virtual bool close() { return true; }
|
virtual bool close() { return true; }
|
||||||
virtual bool init() { return true; }
|
virtual bool init() { return true; }
|
||||||
virtual bool write(const std::string& log);
|
virtual bool write(Assay *assay);
|
||||||
|
|
||||||
std::string file_name(const std::string& unique_id);
|
std::string file_name(const std::string& unique_id);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AuditLog *m_audit;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@@ -15,9 +15,83 @@
|
|||||||
|
|
||||||
#include "src/audit_log_writer_parallel.h"
|
#include "src/audit_log_writer_parallel.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "src/audit_log.h"
|
||||||
|
#include "modsecurity/assay.h"
|
||||||
|
#include "src/utils.h"
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
|
|
||||||
|
|
||||||
|
inline std::string AuditLogWriterParallel::logFilePath(time_t *t,
|
||||||
|
int part) {
|
||||||
|
struct tm timeinfo;
|
||||||
|
char tstr[300];
|
||||||
|
size_t len;
|
||||||
|
std::string name("");
|
||||||
|
|
||||||
|
localtime_r(t, &timeinfo);
|
||||||
|
|
||||||
|
if (part & YearMonthDayDirectory) {
|
||||||
|
memset(tstr, '\0', 300);
|
||||||
|
strftime(tstr, 299, "/%Y%m%d", &timeinfo);
|
||||||
|
name = tstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part & YearMonthDayAndTimeDirectory) {
|
||||||
|
memset(tstr, '\0', 300);
|
||||||
|
strftime(tstr, 299, "/%Y%m%d-%H%M", &timeinfo);
|
||||||
|
name = name + tstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part & YearMonthDayAndTimeFileName) {
|
||||||
|
memset(tstr, '\0', 300);
|
||||||
|
strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo);
|
||||||
|
name = name + tstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AuditLogWriterParallel::init() {
|
||||||
|
/** TODO:: Check if the directory exists. */
|
||||||
|
/** TODO:: Checking if we have permission to write in the target dir */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AuditLogWriterParallel::close() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AuditLogWriterParallel::write(Assay *assay) {
|
||||||
|
std::string log = assay->to_json(0);
|
||||||
|
std::string fileName = logFilePath(&assay->timeStamp,
|
||||||
|
YearMonthDayDirectory | YearMonthDayAndTimeDirectory
|
||||||
|
| YearMonthDayAndTimeFileName);
|
||||||
|
fileName = fileName + "-" + assay->id;
|
||||||
|
|
||||||
|
std::string logPath = m_audit->m_storage_dir;
|
||||||
|
|
||||||
|
createDir((logPath +
|
||||||
|
logFilePath(&assay->timeStamp, YearMonthDayDirectory)).c_str());
|
||||||
|
createDir((logPath +
|
||||||
|
logFilePath(&assay->timeStamp, YearMonthDayDirectory
|
||||||
|
| YearMonthDayAndTimeDirectory)).c_str());
|
||||||
|
|
||||||
|
std::ofstream f;
|
||||||
|
f.open(logPath + fileName, std::fstream::out | std::fstream::app);
|
||||||
|
f << log;
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@@ -13,10 +13,13 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifndef SRC_AUDIT_LOG_WRITER_PARALLEL_H_
|
#ifndef SRC_AUDIT_LOG_WRITER_PARALLEL_H_
|
||||||
#define SRC_AUDIT_LOG_WRITER_PARALLEL_H_
|
#define SRC_AUDIT_LOG_WRITER_PARALLEL_H_
|
||||||
|
|
||||||
#include "src/audit_log_writer.h"
|
#include "src/audit_log_writer.h"
|
||||||
|
#include "modsecurity/assay.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
@@ -25,7 +28,36 @@ namespace ModSecurity {
|
|||||||
/** @ingroup ModSecurity_CPP_API */
|
/** @ingroup ModSecurity_CPP_API */
|
||||||
class AuditLogWriterParallel : public AuditLogWriter {
|
class AuditLogWriterParallel : public AuditLogWriter {
|
||||||
public:
|
public:
|
||||||
AuditLogWriterParallel() { }
|
explicit AuditLogWriterParallel(AuditLog *audit)
|
||||||
|
: AuditLogWriter(audit) { }
|
||||||
|
|
||||||
|
bool init() override;
|
||||||
|
bool close() override;
|
||||||
|
bool write(Assay *assay) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Audit log file is saved into a directory structure. This directory
|
||||||
|
* structure is based on the timestamp of the assay creation, at the exact
|
||||||
|
* moment that ModSecurity be aware of a particular request/transaction.
|
||||||
|
* The expect fromat is:
|
||||||
|
*
|
||||||
|
* [...]/YearMonthDay/YearMonthDayAndTime/YearMonthDayAndTime-RequestId
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* /20150710/20150710-1353/20150710-135353-143654723362.584244
|
||||||
|
*
|
||||||
|
* This enumeration describes the subpaths of this structure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum AuditLogFilePath {
|
||||||
|
YearMonthDayDirectory = 2,
|
||||||
|
YearMonthDayAndTimeDirectory = 4,
|
||||||
|
YearMonthDayAndTimeFileName = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::string logFilePath(time_t *t, int part);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@@ -30,7 +30,7 @@ bool AuditLogWriterSerial::close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AuditLogWriterSerial::write(const std::string& log) {
|
bool AuditLogWriterSerial::write(Assay *assay) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#define SRC_AUDIT_LOG_WRITER_SERIAL_H_
|
#define SRC_AUDIT_LOG_WRITER_SERIAL_H_
|
||||||
|
|
||||||
#include "src/audit_log_writer.h"
|
#include "src/audit_log_writer.h"
|
||||||
|
#include "modsecurity/assay.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
@@ -31,11 +32,12 @@ namespace ModSecurity {
|
|||||||
/** @ingroup ModSecurity_CPP_API */
|
/** @ingroup ModSecurity_CPP_API */
|
||||||
class AuditLogWriterSerial : public AuditLogWriter {
|
class AuditLogWriterSerial : public AuditLogWriter {
|
||||||
public:
|
public:
|
||||||
AuditLogWriterSerial() { }
|
explicit AuditLogWriterSerial(AuditLog *audit)
|
||||||
|
: AuditLogWriter(audit) { }
|
||||||
|
|
||||||
bool init() override;
|
bool init() override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
bool write(const std::string& log) override;
|
bool write(Assay *assay) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
15
src/utils.cc
15
src/utils.cc
@@ -24,6 +24,13 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#if defined _MSC_VER
|
||||||
|
#include <direct.h>
|
||||||
|
#elif defined __GNUC__
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "modsecurity/modsecurity.h"
|
#include "modsecurity/modsecurity.h"
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
@@ -62,5 +69,13 @@ std::string ascTime(time_t *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void createDir(std::string dir) {
|
||||||
|
#if defined _MSC_VER
|
||||||
|
_mkdir(dir.data());
|
||||||
|
#elif defined __GNUC__
|
||||||
|
mkdir(dir.data(), 0777);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@ namespace ModSecurity {
|
|||||||
double random_number(const double from, const double to);
|
double random_number(const double from, const double to);
|
||||||
double generate_assay_unique_id();
|
double generate_assay_unique_id();
|
||||||
std::string ascTime(time_t *t);
|
std::string ascTime(time_t *t);
|
||||||
|
void createDir(std::string dir);
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
|
||||||
#define SRC_UTILS_H_
|
#define SRC_UTILS_H_
|
||||||
|
@@ -139,7 +139,7 @@ void perform_unit_test(std::vector<RegressionTest *> *tests,
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
modsec_assay->processLogging();
|
modsec_assay->processLogging(r.status);
|
||||||
|
|
||||||
CustomDebugLog *d = reinterpret_cast<CustomDebugLog *>
|
CustomDebugLog *d = reinterpret_cast<CustomDebugLog *>
|
||||||
(modsec_rules->debug_log);
|
(modsec_rules->debug_log);
|
||||||
|
Reference in New Issue
Block a user