Write to syslog from R

Hi,

We have a custom package that we use the query our datawarehouse. Because of new privacy policies, we now must log our queries. So we must add new functionality to our package.

When we query the datawarehouse, we must write an event in the system log (syslog). This event must adhere to the ArcSight CEF standard. Then the ArcSight SIEM (= Security Information and Event Management) harvests the event and stores it.

I tried using the rsyslog package for creating the event and writing it to syslog. However, the prefix of the message is wrong. According to the ArcSight CEF standard, it should only contain the date/time and host name. Also host name should be fully qualified, which is not the case. Because of this, the event is not harvested by the ArcSight SIEM.

I tried using the log4r package, which I assume will give me more flexibility in creating a custom header. However I have to define an appender for writing to the system log, and I don't know how.

Maybe I doing this all wrong. I would sure like to hear your opinion. Any help would be appreciated.

1 Like

Hello FrieseWoudLoper,

This is an example of a log4r appender in combination with the syslognet::syslog function.
Normally I do not use the syslog information, but I installed Kiwi Syslog Server – Free Edition to test the following code.
This is not endorsement for the product (even though it worked out of the box :grinning:)
Check out the parameters of the syslognet::syslog function to see if this might work for you.

Update: Kiwi is listening to port 1468 (unless told otherwise)

library(log4r)
#> 
#> Attaching package: 'log4r'
#> The following object is masked from 'package:base':
#> 
#>     debug

fwl_layout <- function (time_format = "%Y-%m-%d %H:%M:%S") {
  function(level, ...) {
    msg <- paste0(..., collapse = "")
    # sprintf("%-5s [%s] %s\n", level, log4r:::fmt_current_time(time_format), 
    #         msg)
    sprintf("%s %s\n",log4r:::fmt_current_time(time_format), 
            msg)
  }
}

syslog_appender = function(layout=fwl_layout()) {
  stopifnot(is.function(layout))
  layout <- compiler::cmpfun(layout)
  
  function(level, ...) {
    msg <- layout(level, ...)
    #syslognet::syslog(msg,port=1468L)
    syslognet::syslog(msg,host='myhostname',app_name='',proc_id= NULL,port=1468L)
  }
}

fwl_logger <- log4r::logger(threshold = "INFO",appenders= syslog_appender())

log4r_info <- function() {
  log4r::info(fwl_logger, "my_info_message")
}

log4r_error <- function() {
  log4r::error(fwl_logger, "my_error_message")
}

log4r_debug <- function() {
  log4r::debug(fwl_logger, "my_debug_message")
}

log4r_debug()

log4r_info() 

log4r_error() 

Created on 2020-06-15 by the reprex package (v0.3.0)

With entries in syslog:
image

2 Likes

Thank you so much for your solution! I will give it a try. Would this solution also work to write to the local syslog in stead of a remote syslog?

I did use it on my local syslog (having no other).

I assume that logging is already done on the datawarehouse machine.
Why then do you need local logging?

All the best with the project.