[PATCH (3.4)] tfuuid: New template function to generate UUIDs.
This patch adds a new template function: $(UUID) (also available as $(uuid)), which can be used to generate Universally Unique IDentifiers. The use case for this is to add an UUID to each message as soon as they're received, so that they can be identified later, accross destinations. This allows me to pre-generate an ID for messages going into mongodb, and send those messages to a different destination too, with the same ID included. Use it like this: rewrite r_add_uuid { set("$(UUID)" value("UUID")); }; log default { source(s_network); rewrite(r_add_uuid); destination(d_mongo); destination(d_program); }; The module uses the widely available libuuid library to generate the UUIDs. Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- configure.in | 16 ++++++++++- modules/Makefile.am | 2 +- modules/tfuuid/Makefile.am | 11 ++++++++ modules/tfuuid/tfuuid.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 modules/tfuuid/Makefile.am create mode 100644 modules/tfuuid/tfuuid.c diff --git a/configure.in b/configure.in index 734d703..83b81ac 100644 --- a/configure.in +++ b/configure.in @@ -182,6 +182,10 @@ AC_ARG_ENABLE(systemd, [ --enable-systemd Enable systemd support (default: auto)] ,,enable_systemd="auto") +AC_ARG_ENABLE(uuid, + [ --enable-uuid Enable UUID support (default: auto)] + ,,enable_uuid="auto") + AC_ARG_WITH(compile-date, [ --without-compile-date Do not include the compile date in the binary] ,wcmp_date="${withval}", wcmp_date="yes") @@ -930,6 +934,14 @@ if test "x$enable_systemd" = "xyes"; then fi fi +if test "x$enable_uuid" = "xyes" || test "x$enable_uuid" = "xauto"; then + PKG_CHECK_MODULES(UUID, uuid, with_uuid="yes", with_uuid="no") + if test "x$with_uuid" = "xno" && test "x$enable_uuid" = "xyes"; then + AC_MSG_ERROR([Could not find libuuid, and uuid support was explicitly enabled.]) + fi + enable_uuid="$with_uuid" +fi + dnl *************************************************************************** dnl default modules to be loaded dnl *************************************************************************** @@ -1087,6 +1099,7 @@ AM_CONDITIONAL(ENABLE_PACCT, [test "$enable_pacct" = "yes"]) AM_CONDITIONAL(ENABLE_MONGODB, [test "$enable_mongodb" = "yes"]) AM_CONDITIONAL(ENABLE_JSON_FORMAT, [test "$enable_json_format" = "yes"]) AM_CONDITIONAL(ENABLE_JSON_PARSE, [test "$enable_json_parse" = "yes"]) +AM_CONDITIONAL(ENABLE_UUID, [test "$enable_uuid" = "yes"]) AM_CONDITIONAL(WITH_LIBSYSTEMD, [test "$with_libsystemd" = "yes"]) # substitution into manual pages @@ -1153,6 +1166,7 @@ AC_OUTPUT(dist.conf modules/pacctformat/Makefile modules/basicfuncs/Makefile modules/tfjson/Makefile + modules/tfuuid/Makefile modules/jsonparser/Makefile scripts/Makefile scripts/update-patterndb @@ -1204,5 +1218,5 @@ echo " SQL support (module) : ${enable_sql:=no}" echo " PACCT module (EXPERIMENTAL) : ${enable_pacct:=no}" echo " MongoDB destination (module): ${enable_mongodb:=no}" echo " JSON support (module) : parser=${enable_json_parse:=no}, formatter=${enable_json_format:=no} (using ${with_json})" - +echo " UUID support (module) : ${enable_uuid:=no}" diff --git a/modules/Makefile.am b/modules/Makefile.am index 0d0594b..72c005f 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = afsocket afsql afstreams affile afprog afuser afmongodb csvparser confgen syslogformat pacctformat basicfuncs dbparser tfjson jsonparser dummy +SUBDIRS = afsocket afsql afstreams affile afprog afuser afmongodb csvparser confgen syslogformat pacctformat basicfuncs dbparser tfjson tfuuid jsonparser dummy diff --git a/modules/tfuuid/Makefile.am b/modules/tfuuid/Makefile.am new file mode 100644 index 0000000..9d96fe1 --- /dev/null +++ b/modules/tfuuid/Makefile.am @@ -0,0 +1,11 @@ +moduledir = @moduledir@ +export top_srcdir + +#if ENABLE_UUID +AM_CPPFLAGS = -I$(top_srcdir)/lib -I../../lib $(UUID_CFLAGS) +module_LTLIBRARIES = libtfuuid.la + +libtfuuid_la_SOURCES = tfuuid.c +libtfuuid_la_LIBADD = $(MODULE_DEPS_LIBS) $(UUID_LIBS) +libtfuuid_la_LDFLAGS = $(MODULE_LDFLAGS) +#endif diff --git a/modules/tfuuid/tfuuid.c b/modules/tfuuid/tfuuid.c new file mode 100644 index 0000000..c426cb8 --- /dev/null +++ b/modules/tfuuid/tfuuid.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2012 Gergely Nagy <algernon@balabit.hu> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "plugin.h" +#include "templates.h" +#include "cfg.h" + +#include "config.h" + +#include <uuid/uuid.h> + +static void +tf_uuid(LogMessage *msg, gint argc, GString *argv[], GString *result) +{ + uuid_t uuid; + gint i; + + uuid_generate (uuid); + + for (i = 0; i < sizeof (uuid); i++) + g_string_append_printf (result, "%02x", uuid[i]); +} + +TEMPLATE_FUNCTION_SIMPLE(tf_uuid); + +static Plugin tfuuid_plugins[] = + { + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "UUID"), + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "uuid"), + }; + +gboolean +tfuuid_module_init(GlobalConfig *cfg, CfgArgs *args) +{ + plugin_register(cfg, tfuuid_plugins, G_N_ELEMENTS(tfuuid_plugins)); + return TRUE; +} + +const ModuleInfo module_info = +{ + .canonical_name = "tfuuid", + .version = VERSION, + .description = "The tfuuid module provides a template function to generate UUIDs.", + .core_revision = SOURCE_REVISION, + .plugins = tfuuid_plugins, + .plugins_len = G_N_ELEMENTS(tfuuid_plugins), +}; -- 1.7.7.3
On Mon, 2012-01-02 at 16:55 +0100, Gergely Nagy wrote:
This patch adds a new template function: $(UUID) (also available as $(uuid)), which can be used to generate Universally Unique IDentifiers.
The use case for this is to add an UUID to each message as soon as they're received, so that they can be identified later, accross destinations. This allows me to pre-generate an ID for messages going into mongodb, and send those messages to a different destination too, with the same ID included.
Use it like this:
rewrite r_add_uuid { set("$(UUID)" value("UUID")); }; log default { source(s_network); rewrite(r_add_uuid); destination(d_mongo); destination(d_program); };
That's a great idea, see my comments on the implementation inline.
The module uses the widely available libuuid library to generate the UUIDs.
Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- configure.in | 16 ++++++++++- modules/Makefile.am | 2 +- modules/tfuuid/Makefile.am | 11 ++++++++ modules/tfuuid/tfuuid.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 modules/tfuuid/Makefile.am create mode 100644 modules/tfuuid/tfuuid.c
diff --git a/configure.in b/configure.in index 734d703..83b81ac 100644 --- a/configure.in +++ b/configure.in +if test "x$enable_uuid" = "xyes" || test "x$enable_uuid" = "xauto"; then + PKG_CHECK_MODULES(UUID, uuid, with_uuid="yes", with_uuid="no") + if test "x$with_uuid" = "xno" && test "x$enable_uuid" = "xyes"; then + AC_MSG_ERROR([Could not find libuuid, and uuid support was explicitly enabled.]) + fi + enable_uuid="$with_uuid" +fi +
If possible I'd avoid using another library, there'd a random based UUID generator function in modules/dbparser/patternize.c Can you check if libuuid does anything more than that?
diff --git a/modules/tfuuid/tfuuid.c b/modules/tfuuid/tfuuid.c new file mode 100644 index 0000000..c426cb8 --- /dev/null +++ b/modules/tfuuid/tfuuid.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2012 Gergely Nagy <algernon@balabit.hu> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "plugin.h" +#include "templates.h" +#include "cfg.h" + +#include "config.h" + +#include <uuid/uuid.h> + +static void +tf_uuid(LogMessage *msg, gint argc, GString *argv[], GString *result) +{ + uuid_t uuid; + gint i; + + uuid_generate (uuid); + + for (i = 0; i < sizeof (uuid); i++) + g_string_append_printf (result, "%02x", uuid[i]); +}
hmm... UUID's have a well defined format (with some dashes) and I'd prefer to use that, if the function is called $(uuid). Here's the uuid generator function in patternize.c, could probably be moved to the lib directory (perhaps lib/uuid.c). I wrote that, so relicencing it to LGPL wouldn't be a problem. static void uuid_gen_random(gchar *buf, gsize buflen) { union { struct { guint32 time_low; guint16 time_mid; guint16 time_hi_and_version; guint8 clk_seq_hi_res; guint8 clk_seq_low; guint8 node[6]; guint16 node_low; guint32 node_hi; }; guchar __rnd[16]; } uuid; RAND_bytes(uuid.__rnd, sizeof(uuid)); uuid.clk_seq_hi_res = (uuid.clk_seq_hi_res & ~0xC0) | 0x80; uuid.time_hi_and_version = htons((uuid.time_hi_and_version & ~0xF000) | 0x4000); g_snprintf(buf, buflen, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, uuid.clk_seq_hi_res, uuid.clk_seq_low, uuid.node[0], uuid.node[1], uuid.node[2], uuid.node[3], uuid.node[4], uuid.node[5]); }
+ +TEMPLATE_FUNCTION_SIMPLE(tf_uuid); + +static Plugin tfuuid_plugins[] = + { + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "UUID"), + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "uuid"), + };
why use two names? I'd prefer the lower case one. -- Bazsi
Balazs Scheidler <bazsi@balabit.hu> writes:
If possible I'd avoid using another library, there'd a random based UUID generator function in modules/dbparser/patternize.c
Can you check if libuuid does anything more than that?
I'll have a look, thanks for the pointer!
+ +TEMPLATE_FUNCTION_SIMPLE(tf_uuid); + +static Plugin tfuuid_plugins[] = + { + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "UUID"), + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "uuid"), + };
why use two names? I'd prefer the lower case one.
Because my fingers were used to typing UUID, and I kept misspelling it all the time, and in the end I gave up, fingers won. :( -- |8]
Balazs Scheidler <bazsi@balabit.hu> writes:
diff --git a/configure.in b/configure.in index 734d703..83b81ac 100644 --- a/configure.in +++ b/configure.in +if test "x$enable_uuid" = "xyes" || test "x$enable_uuid" = "xauto"; then + PKG_CHECK_MODULES(UUID, uuid, with_uuid="yes", with_uuid="no") + if test "x$with_uuid" = "xno" && test "x$enable_uuid" = "xyes"; then + AC_MSG_ERROR([Could not find libuuid, and uuid support was explicitly enabled.]) + fi + enable_uuid="$with_uuid" +fi +
If possible I'd avoid using another library, there'd a random based UUID generator function in modules/dbparser/patternize.c
Can you check if libuuid does anything more than that?
libuuid does something more: by default, it uses /dev/urandom, or if that's not available, then falls back to a combination of current time, local ethernet MAC address (if available) and pseudo-random data. I think it's a bit more through than the implementation in patternize.c. On the other hand, I can make the module work with either: libuuid, if available, the implementation in patternize otherwise. I'll see how much work it would be to be able to choose. If it's too much effort, I'll just switch over to your implementation of uuid instead.
+static void +tf_uuid(LogMessage *msg, gint argc, GString *argv[], GString *result) +{ + uuid_t uuid; + gint i; + + uuid_generate (uuid); + + for (i = 0; i < sizeof (uuid); i++) + g_string_append_printf (result, "%02x", uuid[i]); +}
hmm... UUID's have a well defined format (with some dashes) and I'd prefer to use that, if the function is called $(uuid).
Acknowledged, I changed my local copy to use uuid_unparse(), which is both faster (doesn't append byte-by-byte, but generates a dashed hex string, and appends it to result in one go), and uses the dashed format. If I end up with using libuuid, then that'll use the dashed format too.
+ +TEMPLATE_FUNCTION_SIMPLE(tf_uuid); + +static Plugin tfuuid_plugins[] = + { + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "UUID"), + TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "uuid"), + };
why use two names? I'd prefer the lower case one.
I convinced my fingers that $(uuid) is fine, so I'll remove the other one. -- |8]
Balazs Scheidler <bazsi@balabit.hu> writes:
If possible I'd avoid using another library, there'd a random based UUID generator function in modules/dbparser/patternize.c
Can you check if libuuid does anything more than that?
A'ight, I checked further, and the implementation in patternize requires openssl. So here's my idea: I'll move that implementation to lib/uuid.[ch], and use it if openssl is available. If openssl is not available, but libuuid is, it'll use that. If neither is available, it won't build, and tfuuid will be disabled too. This will also mean that patternzie can generate uuids even without openssl, provided libuuid is available, and I don't have to move this logic to tfuuid, but make it an option for anything that wants an uuid. -- |8]
participants (2)
-
Balazs Scheidler
-
Gergely Nagy