github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/audit/syslogtls.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package audit 5 6 import ( 7 "context" 8 "crypto/tls" 9 "crypto/x509" 10 "fmt" 11 "io/ioutil" 12 13 syslog "github.com/RackSec/srslog" 14 "github.com/wiggin77/logr" 15 "github.com/wiggin77/merror" 16 ) 17 18 // Syslog outputs log records to local or remote syslog. 19 type SyslogTLS struct { 20 logr.Basic 21 w *syslog.Writer 22 } 23 24 // SyslogParams provides parameters for dialing a syslogTLS daemon. 25 type SyslogParams struct { 26 Raddr string 27 Cert string 28 Tag string 29 Insecure bool 30 } 31 32 // NewSyslogTLSTarget creates a target capable of outputting log records to remote or local syslog via TLS. 33 func NewSyslogTLSTarget(filter logr.Filter, formatter logr.Formatter, params *SyslogParams, maxQueue int) (*SyslogTLS, error) { 34 config := tls.Config{InsecureSkipVerify: params.Insecure} 35 36 if params.Cert != "" { 37 serverCert, err := ioutil.ReadFile(params.Cert) 38 if err != nil { 39 return nil, err 40 } 41 pool := x509.NewCertPool() 42 pool.AppendCertsFromPEM(serverCert) 43 config.RootCAs = pool 44 } 45 46 writer, err := syslog.DialWithTLSConfig("tcp+tls", params.Raddr, syslog.LOG_INFO, params.Tag, &config) 47 if err != nil { 48 return nil, err 49 } 50 51 s := &SyslogTLS{w: writer} 52 s.Basic.Start(s, s, filter, formatter, maxQueue) 53 54 return s, nil 55 } 56 57 // Shutdown stops processing log records after making best 58 // effort to flush queue. 59 func (s *SyslogTLS) Shutdown(ctx context.Context) error { 60 errs := merror.New() 61 62 err := s.Basic.Shutdown(ctx) 63 errs.Append(err) 64 65 err = s.w.Close() 66 errs.Append(err) 67 68 return errs.ErrorOrNil() 69 } 70 71 // Write converts the log record to bytes, via the Formatter, 72 // and outputs to syslog via TLS. 73 func (s *SyslogTLS) Write(rec *logr.LogRec) error { 74 _, stacktrace := s.IsLevelEnabled(rec.Level()) 75 76 buf := rec.Logger().Logr().BorrowBuffer() 77 defer rec.Logger().Logr().ReleaseBuffer(buf) 78 79 buf, err := s.Formatter().Format(rec, stacktrace, buf) 80 if err != nil { 81 return err 82 } 83 txt := buf.String() 84 85 switch rec.Level() { 86 case logr.Panic, logr.Fatal: 87 err = s.w.Crit(txt) 88 case logr.Error: 89 err = s.w.Err(txt) 90 case logr.Warn: 91 err = s.w.Warning(txt) 92 case logr.Debug, logr.Trace: 93 err = s.w.Debug(txt) 94 default: 95 // logr.Info plus all custom levels. 96 err = s.w.Info(txt) 97 } 98 99 if err != nil { 100 reporter := rec.Logger().Logr().ReportError 101 reporter(fmt.Errorf("syslog write fail: %w", err)) 102 // syslogTLS writer will try to reconnect. 103 } 104 return err 105 } 106 107 // String returns a string representation of this target. 108 func (s *SyslogTLS) String() string { 109 return "SyslogTLSTarget" 110 }