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  }