1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
14
"github.com/juju/errors"
15
"github.com/juju/loggo"
16
"github.com/juju/utils"
17
"gopkg.in/natefinch/lumberjack.v2"
20
var logger = loggo.GetLogger("juju.audit")
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
29
logger.Errorf("Unable to prime %s (proceeding anyway): %v", logPath, err)
32
handler := &auditLogFileSink{
33
fileLogger: &lumberjack.Logger{
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)
47
return errors.Trace(err)
49
if err := f.Close(); err != nil {
50
return errors.Trace(err)
52
err = utils.ChownPath(path, "syslog")
53
return errors.Trace(err)
56
type auditLogFileSink struct {
57
fileLogger io.WriteCloser
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"),
68
fmt.Sprintf("%v", entry.Data),