github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/audit/auditlogfile.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package audit
     5  
     6  import (
     7  	"io"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"time"
    12  
    13  	"fmt"
    14  	"github.com/juju/errors"
    15  	"github.com/juju/loggo"
    16  	"github.com/juju/utils"
    17  	"gopkg.in/natefinch/lumberjack.v2"
    18  )
    19  
    20  var logger = loggo.GetLogger("juju.audit")
    21  
    22  // NewLogFileSink returns an audit entry sink which writes
    23  // to an audit.log file in the specified directory.
    24  func NewLogFileSink(logDir string) AuditEntrySinkFn {
    25  	logPath := filepath.Join(logDir, "audit.log")
    26  	if err := primeLogFile(logPath); err != nil {
    27  		// This isn't a fatal error so log and continue if priming
    28  		// fails.
    29  		logger.Errorf("Unable to prime %s (proceeding anyway): %v", logPath, err)
    30  	}
    31  
    32  	handler := &auditLogFileSink{
    33  		fileLogger: &lumberjack.Logger{
    34  			Filename:   logPath,
    35  			MaxSize:    300, // MB
    36  			MaxBackups: 10,
    37  		},
    38  	}
    39  	return handler.handle
    40  }
    41  
    42  // primeLogFile ensures the logsink log file is created with the
    43  // correct mode and ownership.
    44  func primeLogFile(path string) error {
    45  	f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)
    46  	if err != nil {
    47  		return errors.Trace(err)
    48  	}
    49  	if err := f.Close(); err != nil {
    50  		return errors.Trace(err)
    51  	}
    52  	err = utils.ChownPath(path, "syslog")
    53  	return errors.Trace(err)
    54  }
    55  
    56  type auditLogFileSink struct {
    57  	fileLogger io.WriteCloser
    58  }
    59  
    60  func (a *auditLogFileSink) handle(entry AuditEntry) error {
    61  	_, err := a.fileLogger.Write([]byte(strings.Join([]string{
    62  		entry.Timestamp.In(time.UTC).Format("2006-01-02 15:04:05"),
    63  		entry.ModelUUID,
    64  		entry.RemoteAddress,
    65  		entry.OriginName,
    66  		entry.OriginType,
    67  		entry.Operation,
    68  		fmt.Sprintf("%v", entry.Data),
    69  	}, ",") + "\n"))
    70  	return err
    71  }