@@ -48,23 +48,54 @@ type AuditEvent struct {
4848 AuthorizeDecision string
4949}
5050
51+ // MissingEventsReport provides an analysis if any events are missing
52+ type MissingEventsReport struct {
53+ FirstEventChecked * auditinternal.Event
54+ LastEventChecked * auditinternal.Event
55+ NumEventsChecked int
56+ MissingEvents []AuditEvent
57+ }
58+
59+ // String returns a human readable string representation of the report
60+ func (m * MissingEventsReport ) String () string {
61+ return fmt .Sprintf (`missing %d events
62+
63+ - first event checked: %#v
64+
65+ - last event checked: %#v
66+
67+ - number of events checked: %d
68+
69+ - missing events: %#v` , len (m .MissingEvents ), m .FirstEventChecked , m .LastEventChecked , m .NumEventsChecked , m .MissingEvents )
70+ }
71+
5172// CheckAuditLines searches the audit log for the expected audit lines.
52- // if includeID is true the event ids will also be verified
53- func CheckAuditLines (stream io.Reader , expected []AuditEvent , version schema.GroupVersion ) (missing []AuditEvent , err error ) {
73+ func CheckAuditLines (stream io.Reader , expected []AuditEvent , version schema.GroupVersion ) (missingReport * MissingEventsReport , err error ) {
5474 expectations := buildEventExpectations (expected )
5575
5676 scanner := bufio .NewScanner (stream )
57- for scanner .Scan () {
77+
78+ missingReport = & MissingEventsReport {
79+ MissingEvents : expected ,
80+ }
81+
82+ var i int
83+ for i = 0 ; scanner .Scan (); i ++ {
5884 line := scanner .Text ()
85+
5986 e := & auditinternal.Event {}
6087 decoder := audit .Codecs .UniversalDecoder (version )
6188 if err := runtime .DecodeInto (decoder , []byte (line ), e ); err != nil {
62- return expected , fmt .Errorf ("failed decoding buf: %s, apiVersion: %s" , line , version )
89+ return missingReport , fmt .Errorf ("failed decoding buf: %s, apiVersion: %s" , line , version )
6390 }
91+ if i == 0 {
92+ missingReport .FirstEventChecked = e
93+ }
94+ missingReport .LastEventChecked = e
6495
6596 event , err := testEventFromInternal (e )
6697 if err != nil {
67- return expected , err
98+ return missingReport , err
6899 }
69100
70101 // If the event was expected, mark it as found.
@@ -73,15 +104,16 @@ func CheckAuditLines(stream io.Reader, expected []AuditEvent, version schema.Gro
73104 }
74105 }
75106 if err := scanner .Err (); err != nil {
76- return expected , err
107+ return missingReport , err
77108 }
78109
79- missing = findMissing (expectations )
80- return missing , nil
110+ missingEvents := findMissing (expectations )
111+ missingReport .MissingEvents = missingEvents
112+ missingReport .NumEventsChecked = i
113+ return missingReport , nil
81114}
82115
83116// CheckAuditList searches an audit event list for the expected audit events.
84- // if includeID is true the event ids will also be verified
85117func CheckAuditList (el auditinternal.EventList , expected []AuditEvent ) (missing []AuditEvent , err error ) {
86118 expectations := buildEventExpectations (expected )
87119
@@ -133,7 +165,6 @@ func buildEventExpectations(expected []AuditEvent) map[AuditEvent]bool {
133165}
134166
135167// testEventFromInternal takes an internal audit event and returns a test event
136- // if includeID is true the event id will be included
137168func testEventFromInternal (e * auditinternal.Event ) (AuditEvent , error ) {
138169 event := AuditEvent {
139170 Level : e .Level ,
0 commit comments