| 35 | } |
| 36 | |
| 37 | func LoadParserDump(filepath string) (*ParserResults, error) { |
| 38 | logger := log.WithField("file", filepath) |
| 39 | |
| 40 | dumpData, err := os.Open(filepath) |
| 41 | if err != nil { |
| 42 | return nil, err |
| 43 | } |
| 44 | defer dumpData.Close() |
| 45 | |
| 46 | results, err := io.ReadAll(dumpData) |
| 47 | if err != nil { |
| 48 | return nil, err |
| 49 | } |
| 50 | |
| 51 | pdump := ParserResults{} |
| 52 | |
| 53 | if err := yaml.Unmarshal(results, &pdump); err != nil { |
| 54 | return nil, err |
| 55 | } |
| 56 | |
| 57 | /* we know that some variables should always be set, |
| 58 | let's check if they're present in last parser output of last stage */ |
| 59 | |
| 60 | stages := maptools.SortedKeys(pdump) |
| 61 | |
| 62 | var lastStage string |
| 63 | |
| 64 | // Loop over stages to find last successful one with at least one parser |
| 65 | for i := len(stages) - 2; i >= 0; i-- { |
| 66 | if len(pdump[stages[i]]) != 0 { |
| 67 | lastStage = stages[i] |
| 68 | break |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | parsers := make([]string, 0, len(pdump[lastStage])) |
| 73 | |
| 74 | for k := range pdump[lastStage] { |
| 75 | parsers = append(parsers, k) |
| 76 | } |
| 77 | |
| 78 | sort.Strings(parsers) |
| 79 | |
| 80 | if len(parsers) == 0 { |
| 81 | return nil, errors.New("no parser found. Please install the appropriate parser and retry") |
| 82 | } |
| 83 | |
| 84 | lastParser := parsers[len(parsers)-1] |
| 85 | |
| 86 | for idx, result := range pdump[lastStage][lastParser] { |
| 87 | if result.Evt.StrTime == "" { |
| 88 | logger.Warningf("Line %d/%d is missing evt.StrTime. It is most likely a mistake as it will prevent your logs to be processed in time-machine/forensic mode.", idx, len(pdump[lastStage][lastParser])) |
| 89 | } else { |
| 90 | logger.Debugf("Line %d/%d has evt.StrTime set to '%s'", idx, len(pdump[lastStage][lastParser]), result.Evt.StrTime) |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | return &pdump, nil |