Files
mattermost/audit/syslogtls.go
Doug Lauder 6a27ed4a1d MM-22785 audit server CLI (#14144)
Add auditing to server CLI.

Also:
- simplify auditing in API layer
- reduce number of AddMeta calls
- have models serialize themselves
- more consistent field naming
2020-04-08 00:52:30 -04:00

110 lines
2.5 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package audit
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
syslog "github.com/RackSec/srslog"
"github.com/wiggin77/logr"
"github.com/wiggin77/merror"
)
// Syslog outputs log records to local or remote syslog.
type SyslogTLS struct {
logr.Basic
w *syslog.Writer
}
// SyslogParams provides parameters for dialing a syslogTLS daemon.
type SyslogParams struct {
Raddr string
Cert string
Tag string
Insecure bool
}
// NewSyslogTLSTarget creates a target capable of outputting log records to remote or local syslog via TLS.
func NewSyslogTLSTarget(filter logr.Filter, formatter logr.Formatter, params *SyslogParams, maxQueue int) (*SyslogTLS, error) {
config := tls.Config{InsecureSkipVerify: params.Insecure}
if params.Cert != "" {
serverCert, err := ioutil.ReadFile(params.Cert)
if err != nil {
return nil, err
}
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(serverCert)
config.RootCAs = pool
}
writer, err := syslog.DialWithTLSConfig("tcp+tls", params.Raddr, syslog.LOG_INFO, params.Tag, &config)
if err != nil {
return nil, err
}
s := &SyslogTLS{w: writer}
s.Basic.Start(s, s, filter, formatter, maxQueue)
return s, nil
}
// Shutdown stops processing log records after making best effort to flush queue.
func (s *SyslogTLS) Shutdown(ctx context.Context) error {
errs := merror.New()
err := s.Basic.Shutdown(ctx)
errs.Append(err)
err = s.w.Close()
errs.Append(err)
return errs.ErrorOrNil()
}
// Write converts the log record to bytes, via the Formatter,
// and outputs to syslog via TLS.
func (s *SyslogTLS) Write(rec *logr.LogRec) error {
_, stacktrace := s.IsLevelEnabled(rec.Level())
buf := rec.Logger().Logr().BorrowBuffer()
defer rec.Logger().Logr().ReleaseBuffer(buf)
buf, err := s.Formatter().Format(rec, stacktrace, buf)
if err != nil {
return err
}
txt := buf.String()
switch rec.Level() {
case logr.Panic, logr.Fatal:
err = s.w.Crit(txt)
case logr.Error:
err = s.w.Err(txt)
case logr.Warn:
err = s.w.Warning(txt)
case logr.Debug, logr.Trace:
err = s.w.Debug(txt)
default:
// logr.Info plus all custom levels.
err = s.w.Info(txt)
}
if err != nil {
reporter := rec.Logger().Logr().ReportError
reporter(fmt.Errorf("syslog write fail: %w", err))
// syslogTLS writer will try to reconnect.
}
return err
}
// String returns a string representation of this target.
func (s *SyslogTLS) String() string {
return "SyslogTLSTarget"
}