diff --git a/README.md b/README.md index e34e4fe..119a0fb 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ I became interested in creating a replacement for the existing daemon. * Safe : Written in a modern language that is type safe and performant * Fast : Never ever ever ever block if we can avoid it * Outputs json : Yay -* Pluggable pipelines : Reports to syslog by default, but easily extended +* Pluggable pipelines : Can write to syslog, local file, or stdout. Additional outputs are easily written. * Connects to the linux kernel via netlink (info [here](https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/kernel/audit.c?id=refs/tags/v3.14.56) and [here](https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/include/uapi/linux/audit.h?h=linux-3.14.y)) ## Usage diff --git a/audit.go b/audit.go index fb009a6..efbc7a5 100644 --- a/audit.go +++ b/audit.go @@ -97,6 +97,14 @@ func createOutput(config *viper.Viper) (*AuditWriter, error) { } } + if config.GetBool("output.stdout.enabled") == true { + i++ + writer, err = createStdOutOutput(config) + if err != nil { + return nil, err + } + } + if i > 1 { return nil, errors.New("Only one output can be enabled at a time") } @@ -185,6 +193,20 @@ func createFileOutput(config *viper.Viper) (*AuditWriter, error) { return NewAuditWriter(f, attempts), nil } +func createStdOutOutput(config *viper.Viper) (*AuditWriter, error) { + attempts := config.GetInt("output.stdout.attempts") + if attempts < 1 { + return nil, errors.New( + fmt.Sprintf("Output attempts for stdout must be at least 1, %v provided", attempts), + ) + } + + // l logger is no longer stdout + l.SetOutput(os.Stderr) + + return NewAuditWriter(os.Stdout, attempts), nil +} + func createFilters(config *viper.Viper) []AuditFilter { var err error var ok bool @@ -272,12 +294,13 @@ func main() { el.Fatal(err) } - if err := setRules(config, lExec); err != nil { + // output needs to be created before anything that write to stdout + writer, err := createOutput(config) + if err != nil { el.Fatal(err) } - writer, err := createOutput(config) - if err != nil { + if err := setRules(config, lExec); err != nil { el.Fatal(err) } diff --git a/audit_test.go b/audit_test.go index f63b5bb..b31cab2 100644 --- a/audit_test.go +++ b/audit_test.go @@ -207,6 +207,23 @@ func Test_createSyslogOutput(t *testing.T) { assert.IsType(t, &syslog.Writer{}, w.w) } +func Test_createStdOutOutput(t *testing.T) { + // attempts error + c := viper.New() + c.Set("output.stdout.attempts", 0) + w, err := createStdOutOutput(c) + assert.EqualError(t, err, "Output attempts for stdout must be at least 1, 0 provided") + assert.Nil(t, w) + + // All good + c = viper.New() + c.Set("output.stdout.attempts", 1) + w, err = createStdOutOutput(c) + assert.Nil(t, err) + assert.NotNil(t, w) + assert.IsType(t, &os.File{}, w.w) +} + func Test_createOutput(t *testing.T) { // no outputs c := viper.New() @@ -265,6 +282,14 @@ func Test_createOutput(t *testing.T) { assert.EqualError(t, err, "Output attempts for file must be at least 1, 0 provided") assert.Nil(t, w) + // stdout error + c = viper.New() + c.Set("output.stdout.enabled", true) + c.Set("output.stdout.attempts", 0) + w, err = createOutput(c) + assert.EqualError(t, err, "Output attempts for stdout must be at least 1, 0 provided") + assert.Nil(t, w) + // All good syslog c = viper.New() c.Set("output.syslog.attempts", 1) diff --git a/go-audit.yaml.example b/go-audit.yaml.example index 590910d..ce2bf71 100644 --- a/go-audit.yaml.example +++ b/go-audit.yaml.example @@ -26,13 +26,19 @@ message_tracking: # Configure where to output audit events # Only 1 output can be active at a given time output: - # Writes logs to syslog - syslog: + # Writes to stdout + # All program status logging will be moved to stderr + stdout: enabled: true - # Total number of attempts to send a message before considering the syslog server gone + # Total number of attempts to write a line before considering giving up # If a write fails go-audit will sleep for 1 second before retrying - # default is 3 + # Default is 3 + attempts: 2 + + # Writes logs to syslog + syslog: + enabled: false attempts: 5 # Configure the type of socket this should be, default is unixgram @@ -54,9 +60,6 @@ output: # Appends logs to a file file: enabled: false - - # Total number of attempts to write a line before considering giving up - # If a write fails go-audit will sleep for 1 second before retrying attempts: 2 # Path of the file to write lines to