parseAuditJSONL parses an audit.jsonl file and returns a slice of audit log entries.
(jsonlPath string)
| 119 | |
| 120 | // parseAuditJSONL parses an audit.jsonl file and returns a slice of audit log entries. |
| 121 | func parseAuditJSONL(jsonlPath string) ([]AuditLogEntry, error) { |
| 122 | firewallPolicyLog.Printf("Parsing audit JSONL: %s", jsonlPath) |
| 123 | |
| 124 | file, err := os.Open(jsonlPath) |
| 125 | if err != nil { |
| 126 | return nil, fmt.Errorf("failed to open audit JSONL: %w", err) |
| 127 | } |
| 128 | defer file.Close() |
| 129 | |
| 130 | var entries []AuditLogEntry |
| 131 | scanner := bufio.NewScanner(file) |
| 132 | // Set larger buffer for potentially long lines |
| 133 | scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024) |
| 134 | |
| 135 | lineNum := 0 |
| 136 | for scanner.Scan() { |
| 137 | lineNum++ |
| 138 | line := strings.TrimSpace(scanner.Text()) |
| 139 | if line == "" { |
| 140 | continue |
| 141 | } |
| 142 | |
| 143 | var entry AuditLogEntry |
| 144 | if err := json.Unmarshal([]byte(line), &entry); err != nil { |
| 145 | firewallPolicyLog.Printf("Skipping malformed JSONL line %d: %v", lineNum, err) |
| 146 | continue |
| 147 | } |
| 148 | entries = append(entries, entry) |
| 149 | } |
| 150 | |
| 151 | if err := scanner.Err(); err != nil { |
| 152 | return nil, fmt.Errorf("error reading audit JSONL: %w", err) |
| 153 | } |
| 154 | |
| 155 | firewallPolicyLog.Printf("Parsed %d audit log entries from %d lines", len(entries), lineNum) |
| 156 | return entries, nil |
| 157 | } |
| 158 | |
| 159 | // domainMatchesRule checks if a domain matches a policy rule. |
| 160 | // Domain matching follows AWF conventions: |