github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/core/auditlog/auditlog_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 package auditlog_test 4 5 import ( 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "time" 10 11 "github.com/juju/clock/testclock" 12 "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/core/auditlog" 17 ) 18 19 type AuditLogSuite struct { 20 testing.IsolationSuite 21 } 22 23 var _ = gc.Suite(&AuditLogSuite{}) 24 25 func (s *AuditLogSuite) TestAuditLogFile(c *gc.C) { 26 dir := c.MkDir() 27 logFile := auditlog.NewLogFile(dir, 300, 10) 28 err := logFile.AddConversation(auditlog.Conversation{ 29 Who: "deerhoof", 30 What: "gojira", 31 When: "2017-11-27T13:21:24Z", 32 ModelName: "admin/default", 33 ConversationID: "0123456789abcdef", 34 ConnectionID: "AC1", 35 }) 36 c.Assert(err, jc.ErrorIsNil) 37 err = logFile.AddRequest(auditlog.Request{ 38 ConversationID: "0123456789abcdef", 39 ConnectionID: "AC1", 40 RequestID: 25, 41 When: "2017-12-12T11:34:56Z", 42 Facade: "Application", 43 Method: "Deploy", 44 Version: 4, 45 Args: `{"applications": [{"application": "prometheus"}]}`, 46 }) 47 c.Assert(err, jc.ErrorIsNil) 48 err = logFile.AddResponse(auditlog.ResponseErrors{ 49 ConversationID: "0123456789abcdef", 50 ConnectionID: "AC1", 51 RequestID: 25, 52 When: "2017-12-12T11:35:11Z", 53 Errors: []*auditlog.Error{ 54 {Message: "oops", Code: "unauthorized access"}, 55 }, 56 }) 57 c.Assert(err, jc.ErrorIsNil) 58 err = logFile.Close() 59 c.Assert(err, jc.ErrorIsNil) 60 61 bytes, err := ioutil.ReadFile(filepath.Join(dir, "audit.log")) 62 c.Assert(string(bytes), gc.Equals, expectedLogContents) 63 } 64 65 func (s *AuditLogSuite) TestAuditLogFilePriming(c *gc.C) { 66 dir := c.MkDir() 67 logFile := auditlog.NewLogFile(dir, 300, 10) 68 err := logFile.Close() 69 c.Assert(err, jc.ErrorIsNil) 70 71 info, err := os.Stat(filepath.Join(dir, "audit.log")) 72 c.Assert(err, jc.ErrorIsNil) 73 c.Assert(info.Mode(), gc.Equals, os.FileMode(0600)) 74 // The chown will only work when run as root. 75 } 76 77 func (s *AuditLogSuite) TestRecorder(c *gc.C) { 78 var log fakeLog 79 logTime, err := time.Parse(time.RFC3339, "2017-11-27T15:45:23Z") 80 c.Assert(err, jc.ErrorIsNil) 81 clock := testclock.NewClock(logTime) 82 rec, err := auditlog.NewRecorder(&log, clock, auditlog.ConversationArgs{ 83 Who: "wildbirds and peacedrums", 84 What: "Doubt/Hope", 85 ModelName: "admin/default", 86 ConnectionID: 687, 87 }) 88 c.Assert(err, jc.ErrorIsNil) 89 clock.Advance(time.Second) 90 err = rec.AddRequest(auditlog.RequestArgs{ 91 RequestID: 246, 92 Facade: "Death Vessel", 93 Method: "Horchata", 94 Version: 5, 95 Args: `{"a": "something"}`, 96 }) 97 c.Assert(err, jc.ErrorIsNil) 98 clock.Advance(time.Second) 99 err = rec.AddResponse(auditlog.ResponseErrorsArgs{ 100 RequestID: 246, 101 Errors: []*auditlog.Error{{ 102 Message: "something bad", 103 Code: "bad request", 104 }}, 105 }) 106 107 log.stub.CheckCallNames(c, "AddConversation", "AddRequest", "AddResponse") 108 calls := log.stub.Calls() 109 rec0 := calls[0].Args[0].(auditlog.Conversation) 110 callID := rec0.ConversationID 111 c.Assert(rec0, gc.DeepEquals, auditlog.Conversation{ 112 Who: "wildbirds and peacedrums", 113 What: "Doubt/Hope", 114 When: "2017-11-27T15:45:23Z", 115 ModelName: "admin/default", 116 ConnectionID: "2AF", 117 ConversationID: callID, 118 }) 119 c.Assert(calls[1].Args[0], gc.DeepEquals, auditlog.Request{ 120 ConversationID: callID, 121 ConnectionID: "2AF", 122 RequestID: 246, 123 When: "2017-11-27T15:45:24Z", 124 Facade: "Death Vessel", 125 Method: "Horchata", 126 Version: 5, 127 Args: `{"a": "something"}`, 128 }) 129 c.Assert(calls[2].Args[0], gc.DeepEquals, auditlog.ResponseErrors{ 130 ConversationID: callID, 131 ConnectionID: "2AF", 132 RequestID: 246, 133 When: "2017-11-27T15:45:25Z", 134 Errors: []*auditlog.Error{{ 135 Message: "something bad", 136 Code: "bad request", 137 }}, 138 }) 139 } 140 141 type fakeLog struct { 142 stub testing.Stub 143 } 144 145 func (l *fakeLog) AddConversation(m auditlog.Conversation) error { 146 l.stub.AddCall("AddConversation", m) 147 return l.stub.NextErr() 148 } 149 150 func (l *fakeLog) AddRequest(m auditlog.Request) error { 151 l.stub.AddCall("AddRequest", m) 152 return l.stub.NextErr() 153 } 154 155 func (l *fakeLog) AddResponse(m auditlog.ResponseErrors) error { 156 l.stub.AddCall("AddResponse", m) 157 return l.stub.NextErr() 158 } 159 160 func (l *fakeLog) Close() error { 161 l.stub.AddCall("Close") 162 return l.stub.NextErr() 163 } 164 165 var ( 166 expectedLogContents = ` 167 {"conversation":{"who":"deerhoof","what":"gojira","when":"2017-11-27T13:21:24Z","model-name":"admin/default","model-uuid":"","conversation-id":"0123456789abcdef","connection-id":"AC1"}} 168 {"request":{"conversation-id":"0123456789abcdef","connection-id":"AC1","request-id":25,"when":"2017-12-12T11:34:56Z","facade":"Application","method":"Deploy","version":4,"args":"{\"applications\": [{\"application\": \"prometheus\"}]}"}} 169 {"errors":{"conversation-id":"0123456789abcdef","connection-id":"AC1","request-id":25,"when":"2017-12-12T11:35:11Z","errors":[{"message":"oops","code":"unauthorized access"}]}} 170 `[1:] 171 )