mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
Writes audit log in parallel mode
First version still missing the index among other things
This commit is contained in:
parent
693238b235
commit
c9620ac50f
@ -126,7 +126,7 @@ class Assay {
|
||||
int processResponseBody();
|
||||
int appendResponseBody(const unsigned char *body, size_t size);
|
||||
|
||||
int processLogging();
|
||||
int processLogging(int status_code);
|
||||
|
||||
ModSecurityIntervention *intervention();
|
||||
|
||||
@ -149,12 +149,14 @@ class Assay {
|
||||
bool save_in_auditlog;
|
||||
bool do_not_save_in_auditlog;
|
||||
|
||||
int http_code_returned;
|
||||
int httpCodeReturned;
|
||||
|
||||
std::string to_json(int parts);
|
||||
|
||||
private:
|
||||
std::string id;
|
||||
time_t timeStamp;
|
||||
|
||||
private:
|
||||
std::ofstream myfile;
|
||||
Rules *m_rules;
|
||||
ModSecurity *m_ms;
|
||||
@ -166,7 +168,6 @@ class Assay {
|
||||
const char *m_uri;
|
||||
const char *m_protocol;
|
||||
const char *m_httpVersion;
|
||||
time_t m_timeStamp;
|
||||
|
||||
std::ostringstream m_requestBody;
|
||||
std::ostringstream m_responseBody;
|
||||
@ -236,7 +237,7 @@ void msc_assay_cleanup(Assay *assay);
|
||||
ModSecurityIntervention *msc_intervention(Assay *assay);
|
||||
|
||||
/** @ingroup ModSecurity_C_API */
|
||||
int msc_process_logging(Assay *assay);
|
||||
int msc_process_logging(Assay *assay, int code);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
18
src/assay.cc
18
src/assay.cc
@ -87,10 +87,10 @@ Assay::Assay(ModSecurity *ms, Rules *rules)
|
||||
m_rules(rules),
|
||||
save_in_auditlog(false),
|
||||
do_not_save_in_auditlog(false),
|
||||
m_timeStamp(std::time(NULL)),
|
||||
http_code_returned(200),
|
||||
timeStamp(std::time(NULL)),
|
||||
httpCodeReturned(200),
|
||||
m_ms(ms) {
|
||||
id = std::to_string(this->m_timeStamp) + \
|
||||
id = std::to_string(this->timeStamp) + \
|
||||
std::to_string(generate_assay_unique_id());
|
||||
m_rules->incrementReferenceCount();
|
||||
this->debug(4, "Initialising transaction");
|
||||
@ -617,8 +617,9 @@ int Assay::getResponseBodyLenth() {
|
||||
* @retval false Operation failed.
|
||||
*
|
||||
*/
|
||||
int Assay::processLogging() {
|
||||
int Assay::processLogging(int returned_code) {
|
||||
debug(4, "Starting phase LOGGING. (SecRules 5)");
|
||||
this->httpCodeReturned = returned_code;
|
||||
this->m_rules->evaluate(ModSecurity::LoggingPhase, this);
|
||||
|
||||
/* 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;
|
||||
size_t len;
|
||||
yajl_gen g = NULL;
|
||||
std::string ts = ascTime(&m_timeStamp).c_str();
|
||||
std::string ts = ascTime(&timeStamp).c_str();
|
||||
std::string uniqueId = UniqueId::uniqueId();
|
||||
|
||||
g = yajl_gen_alloc(NULL);
|
||||
@ -754,7 +755,7 @@ std::string Assay::to_json(int parts) {
|
||||
yajl_gen_map_open(g);
|
||||
|
||||
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 */
|
||||
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.
|
||||
*
|
||||
* @param assay ModSecurity assay.
|
||||
* @param code HTTP code returned to the user.
|
||||
*
|
||||
* @returns If the operation was successful or not.
|
||||
* @retval 1 Operation was successful.
|
||||
* @retval 0 Operation failed.
|
||||
*
|
||||
*/
|
||||
extern "C" int msc_process_logging(Assay *assay) {
|
||||
return assay->processLogging();
|
||||
extern "C" int msc_process_logging(Assay *assay, int code) {
|
||||
return assay->processLogging(code);
|
||||
}
|
||||
|
||||
} // namespace ModSecurity
|
||||
|
@ -102,11 +102,11 @@ bool AuditLog::setType(AuditLogType audit_type) {
|
||||
|
||||
bool AuditLog::init() {
|
||||
if (m_type == ParallelAuditLogType) {
|
||||
m_writer = new AuditLogWriterParallel();
|
||||
m_writer = new AuditLogWriterParallel(this);
|
||||
}
|
||||
|
||||
if (m_type == SerialAuditLogType) {
|
||||
m_writer = new AuditLogWriterSerial();
|
||||
m_writer = new AuditLogWriterSerial(this);
|
||||
}
|
||||
|
||||
if (m_writer == NULL || m_writer->init() == false) {
|
||||
@ -134,7 +134,7 @@ bool AuditLog::isRelevant(int status) {
|
||||
|
||||
|
||||
bool AuditLog::saveIfRelevant(Assay *assay) {
|
||||
if (this->isRelevant(assay->http_code_returned) == false &&
|
||||
if (this->isRelevant(assay->httpCodeReturned) == false &&
|
||||
assay->save_in_auditlog == false) {
|
||||
return true;
|
||||
}
|
||||
@ -148,9 +148,7 @@ bool AuditLog::saveIfRelevant(Assay *assay) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string log = assay->to_json(0);
|
||||
|
||||
m_writer->write(log);
|
||||
m_writer->write(assay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -162,12 +162,13 @@ class AuditLog {
|
||||
bool saveIfRelevant(Assay *assay);
|
||||
bool isRelevant(int status);
|
||||
|
||||
private:
|
||||
AuditLogStatus m_status;
|
||||
std::string m_path1;
|
||||
std::string m_path2;
|
||||
std::string m_storage_dir;
|
||||
|
||||
private:
|
||||
AuditLogStatus m_status;
|
||||
|
||||
int m_file_permissions;
|
||||
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.
|
||||
*
|
||||
*/
|
||||
bool AuditLogWriter::write(const std::string& log) {
|
||||
std::cout << log << std::endl;
|
||||
bool AuditLogWriter::write(Assay *assay) {
|
||||
std::cout << assay->to_json(0) << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -23,20 +23,28 @@
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
#include "modsecurity/assay.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace ModSecurity {
|
||||
class AuditLog;
|
||||
|
||||
/** @ingroup ModSecurity_CPP_API */
|
||||
class AuditLogWriter : public std::ofstream {
|
||||
public:
|
||||
AuditLogWriter() { }
|
||||
explicit AuditLogWriter(AuditLog *audit)
|
||||
: m_audit(audit) { }
|
||||
|
||||
virtual bool close() { 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);
|
||||
|
||||
protected:
|
||||
AuditLog *m_audit;
|
||||
};
|
||||
|
||||
} // namespace ModSecurity
|
||||
|
@ -15,9 +15,83 @@
|
||||
|
||||
#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 {
|
||||
|
||||
|
||||
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
|
||||
|
@ -13,10 +13,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef SRC_AUDIT_LOG_WRITER_PARALLEL_H_
|
||||
#define SRC_AUDIT_LOG_WRITER_PARALLEL_H_
|
||||
|
||||
#include "src/audit_log_writer.h"
|
||||
#include "modsecurity/assay.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -25,7 +28,36 @@ namespace ModSecurity {
|
||||
/** @ingroup ModSecurity_CPP_API */
|
||||
class AuditLogWriterParallel : public AuditLogWriter {
|
||||
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
|
||||
|
@ -30,7 +30,7 @@ bool AuditLogWriterSerial::close() {
|
||||
}
|
||||
|
||||
|
||||
bool AuditLogWriterSerial::write(const std::string& log) {
|
||||
bool AuditLogWriterSerial::write(Assay *assay) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define SRC_AUDIT_LOG_WRITER_SERIAL_H_
|
||||
|
||||
#include "src/audit_log_writer.h"
|
||||
#include "modsecurity/assay.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -31,11 +32,12 @@ namespace ModSecurity {
|
||||
/** @ingroup ModSecurity_CPP_API */
|
||||
class AuditLogWriterSerial : public AuditLogWriter {
|
||||
public:
|
||||
AuditLogWriterSerial() { }
|
||||
explicit AuditLogWriterSerial(AuditLog *audit)
|
||||
: AuditLogWriter(audit) { }
|
||||
|
||||
bool init() override;
|
||||
bool close() override;
|
||||
bool write(const std::string& log) override;
|
||||
bool write(Assay *assay) override;
|
||||
};
|
||||
|
||||
} // namespace ModSecurity
|
||||
|
15
src/utils.cc
15
src/utils.cc
@ -24,6 +24,13 @@
|
||||
#include <memory>
|
||||
#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"
|
||||
|
||||
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
|
||||
|
||||
|
@ -27,6 +27,7 @@ namespace ModSecurity {
|
||||
double random_number(const double from, const double to);
|
||||
double generate_assay_unique_id();
|
||||
std::string ascTime(time_t *t);
|
||||
void createDir(std::string dir);
|
||||
} // namespace ModSecurity
|
||||
|
||||
#define SRC_UTILS_H_
|
||||
|
@ -139,7 +139,7 @@ void perform_unit_test(std::vector<RegressionTest *> *tests,
|
||||
}
|
||||
|
||||
end:
|
||||
modsec_assay->processLogging();
|
||||
modsec_assay->processLogging(r.status);
|
||||
|
||||
CustomDebugLog *d = reinterpret_cast<CustomDebugLog *>
|
||||
(modsec_rules->debug_log);
|
||||
|
Loading…
x
Reference in New Issue
Block a user