aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandrew stalin <andrew.stalin@gmail.com>2024-12-12 13:54:21 +0700
committerGitHub <noreply@github.com>2024-12-12 13:54:21 +0700
commit95f10723e8c1c5538f2ccc33372450f4ddc0e5df (patch)
tree3f2a534b2804414bef44b8b4fd088aeeb1443588
parent0c6385657910a0bfa392c62d49a78d8f73482ff2 (diff)
downloadydb-95f10723e8c1c5538f2ccc33372450f4ddc0e5df.tar.gz
Register a custom audit log item builder (#12268)
-rw-r--r--ydb/core/audit/audit_log.h4
-rw-r--r--ydb/core/audit/audit_log_impl.cpp70
-rw-r--r--ydb/core/audit/audit_log_item_builder.h14
-rw-r--r--ydb/core/audit/ya.make1
-rw-r--r--ydb/core/protos/config.proto3
5 files changed, 59 insertions, 33 deletions
diff --git a/ydb/core/audit/audit_log.h b/ydb/core/audit/audit_log.h
index 97ecc6e78a..1696e0f7b9 100644
--- a/ydb/core/audit/audit_log.h
+++ b/ydb/core/audit/audit_log.h
@@ -37,8 +37,10 @@ namespace NActors {
namespace NKikimr::NAudit {
+using TAuditLogParts = TVector<std::pair<TString, TString>>;
+
extern std::atomic<bool> AUDIT_LOG_ENABLED;
-void SendAuditLog(const NActors::TActorSystem* sys, TVector<std::pair<TString, TString>>&& parts);
+void SendAuditLog(const NActors::TActorSystem* sys, TAuditLogParts&& parts);
} // namespace NKikimr::NAudit
diff --git a/ydb/core/audit/audit_log_impl.cpp b/ydb/core/audit/audit_log_impl.cpp
index 538e267d5e..bfab6d72be 100644
--- a/ydb/core/audit/audit_log_impl.cpp
+++ b/ydb/core/audit/audit_log_impl.cpp
@@ -3,14 +3,14 @@
#include <library/cpp/logger/record.h>
#include <library/cpp/logger/backend.h>
+#include <ydb/core/base/events.h>
#include <ydb/library/actors/core/log.h>
#include <ydb/library/actors/core/actor.h>
#include <ydb/library/actors/core/events.h>
#include <ydb/library/actors/core/hfunc.h>
#include <ydb/library/services/services.pb.h>
-#include <ydb/core/base/events.h>
-
+#include "audit_log_item_builder.h"
#include "audit_log_service.h"
#include "audit_log.h"
@@ -55,9 +55,9 @@ struct TEvAuditLog {
struct TEvWriteAuditLog : public NActors::TEventLocal<TEvWriteAuditLog, EvWriteAuditLog> {
TInstant Time;
- TVector<std::pair<TString, TString>> Parts;
+ TAuditLogParts Parts;
- TEvWriteAuditLog(TInstant time, TVector<std::pair<TString, TString>>&& parts)
+ TEvWriteAuditLog(TInstant time, TAuditLogParts&& parts)
: Time(time)
, Parts(std::move(parts))
{}
@@ -78,12 +78,11 @@ void WriteLog(const TString& log, const TVector<THolder<TLogBackend>>& logBacken
}
}
-TString GetJsonLog(const TEvAuditLog::TEvWriteAuditLog::TPtr& ev) {
- const auto* msg = ev->Get();
+TString GetJsonLog(TInstant time, const TAuditLogParts& parts) {
TStringStream ss;
- ss << msg->Time << ": ";
+ ss << time << ": ";
NJson::TJsonMap m;
- for (auto& [k, v] : msg->Parts) {
+ for (auto& [k, v] : parts) {
m[k] = v;
}
NJson::WriteJson(&ss, &m, false, false);
@@ -91,19 +90,18 @@ TString GetJsonLog(const TEvAuditLog::TEvWriteAuditLog::TPtr& ev) {
return ss.Str();
}
-TString GetJsonLogCompatibleLog(const TEvAuditLog::TEvWriteAuditLog::TPtr& ev) {
- const auto* msg = ev->Get();
+TString GetJsonLogCompatibleLog(TInstant time, const TAuditLogParts& parts) {
TStringStream ss;
NJsonWriter::TBuf json(NJsonWriter::HEM_DONT_ESCAPE_HTML, &ss);
{
auto obj = json.BeginObject();
obj
.WriteKey("@timestamp")
- .WriteString(msg->Time.ToString().data())
+ .WriteString(time.ToString().data())
.WriteKey("@log_type")
.WriteString("audit");
- for (auto& [k, v] : msg->Parts) {
+ for (auto& [k, v] : parts) {
obj.WriteKey(k).WriteString(v);
}
json.EndObject();
@@ -112,12 +110,11 @@ TString GetJsonLogCompatibleLog(const TEvAuditLog::TEvWriteAuditLog::TPtr& ev) {
return ss.Str();
}
-TString GetTxtLog(const TEvAuditLog::TEvWriteAuditLog::TPtr& ev) {
- const auto* msg = ev->Get();
+TString GetTxtLog(TInstant time, const TAuditLogParts& parts) {
TStringStream ss;
- ss << msg->Time << ": ";
- for (auto it = msg->Parts.begin(); it != msg->Parts.end(); it++) {
- if (it != msg->Parts.begin())
+ ss << time << ": ";
+ for (auto it = parts.begin(); it != parts.end(); it++) {
+ if (it != parts.begin())
ss << ", ";
ss << it->first << "=" << it->second;
}
@@ -125,6 +122,23 @@ TString GetTxtLog(const TEvAuditLog::TEvWriteAuditLog::TPtr& ev) {
return ss.Str();
}
+// Array of functions for converting a audit event parameters to a string.
+// Indexing in the array occurs by the value of the NKikimrConfig::TAuditConfig::EFormat enumeration.
+// For each new format, we need to register the audit event conversion function.
+// The size of AuditLogItemBuilders must be larger by one of the maximum value of the NKikimrConfig::TAuditConfig::EFormat enumeration.
+// The first value of AuditLogItemBuilders is a stub for the convenience of indexing by enumeration value.
+static std::vector<TAuditLogItemBuilder> AuditLogItemBuilders = { nullptr, GetJsonLog, GetTxtLog, GetJsonLogCompatibleLog, nullptr };
+
+// numbering enumeration starts from one
+static constexpr size_t DefaultAuditLogItemBuilder = static_cast<size_t>(NKikimrConfig::TAuditConfig::JSON);
+
+void RegisterAuditLogItemBuilder(NKikimrConfig::TAuditConfig::EFormat format, TAuditLogItemBuilder builder) {
+ size_t index = static_cast<size_t>(format);
+ if (index < AuditLogItemBuilders.size()) {
+ AuditLogItemBuilders[index] = builder;
+ }
+}
+
class TAuditLogActor final : public TActor<TAuditLogActor> {
private:
const TAuditLogBackends LogBackends;
@@ -160,20 +174,12 @@ private:
Y_UNUSED(ctx);
for (auto& logBackends : LogBackends) {
- switch (logBackends.first) {
- case NKikimrConfig::TAuditConfig::JSON:
- WriteLog(GetJsonLog(ev), logBackends.second);
- break;
- case NKikimrConfig::TAuditConfig::TXT:
- WriteLog(GetTxtLog(ev), logBackends.second);
- break;
- case NKikimrConfig::TAuditConfig::JSON_LOG_COMPATIBLE:
- WriteLog(GetJsonLogCompatibleLog(ev), logBackends.second);
- break;
- default:
- WriteLog(GetJsonLog(ev), logBackends.second);
- break;
- }
+ const auto builderIndex = static_cast<size_t>(logBackends.first);
+ const auto builder = builderIndex < AuditLogItemBuilders.size() && AuditLogItemBuilders[builderIndex] != nullptr
+ ? AuditLogItemBuilders[builderIndex] : AuditLogItemBuilders[DefaultAuditLogItemBuilder];
+ const auto msg = ev->Get();
+ const auto auditLogItem = builder(msg->Time, msg->Parts);
+ WriteLog(auditLogItem, logBackends.second);
}
}
@@ -190,7 +196,7 @@ private:
std::atomic<bool> AUDIT_LOG_ENABLED = false;
-void SendAuditLog(const NActors::TActorSystem* sys, TVector<std::pair<TString, TString>>&& parts)
+void SendAuditLog(const NActors::TActorSystem* sys, TAuditLogParts&& parts)
{
auto request = MakeHolder<TEvAuditLog::TEvWriteAuditLog>(Now(), std::move(parts));
sys->Send(MakeAuditServiceID(), request.Release());
diff --git a/ydb/core/audit/audit_log_item_builder.h b/ydb/core/audit/audit_log_item_builder.h
new file mode 100644
index 0000000000..609d80afb9
--- /dev/null
+++ b/ydb/core/audit/audit_log_item_builder.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <ydb/core/audit/audit_log.h>
+#include <ydb/core/protos/config.pb.h>
+
+
+namespace NKikimr::NAudit {
+
+using TAuditLogItemBuilder = TString(*)(TInstant, const TAuditLogParts&);
+
+// Registration of a function for converting audit events to a string in a specified format
+void RegisterAuditLogItemBuilder(NKikimrConfig::TAuditConfig::EFormat format, TAuditLogItemBuilder builder);
+
+}
diff --git a/ydb/core/audit/ya.make b/ydb/core/audit/ya.make
index 3c2272d2d8..127eacc2a6 100644
--- a/ydb/core/audit/ya.make
+++ b/ydb/core/audit/ya.make
@@ -1,6 +1,7 @@
LIBRARY()
SRCS(
+ audit_log_item_builder.h
audit_log.h
audit_log_service.h
audit_log_impl.cpp
diff --git a/ydb/core/protos/config.proto b/ydb/core/protos/config.proto
index 968db47fb0..315749c259 100644
--- a/ydb/core/protos/config.proto
+++ b/ydb/core/protos/config.proto
@@ -1493,10 +1493,13 @@ message TMeteringConfig {
};
message TAuditConfig {
+ // For each new format, we need to register the audit event conversion function
+ // See ydb/core/audit/audit_log_impl.cpp for details
enum EFormat {
JSON = 1; // Outputs audit log in format: "<time>: {"k1": "v1", "k2": "v2", ...}" where <time> is ISO 8601 format time string, k1, k2, ..., kn - fields of audit log message and v1, v2, ..., vn are their values
TXT = 2; // Outputs audit log in format: "<time>: k1=v1, k2=v2, ..." where <time> is ISO 8601 format time string, k1, k2, ..., kn - fields of audit log message and v1, v2, ..., vn are their values
JSON_LOG_COMPATIBLE = 3; // Outputs audit log in format: "{"@timestamp": "<ISO 8601 time>", "@log_type": "audit", "k1": "v1", "k2": "v2", ...}" where @timestamp is ISO 8601 format time string, k1, k2, ..., kn - fields of audit log message and v1, v2, ..., vn are their values // Suitable for output both debug log and audit log to the same destination (stderr)
+ FORMAT_4 = 4; // Reserved
}
message TStderrBackend {