From d1fb9574cbce3693aa146ffc769355557a13a335 Mon Sep 17 00:00:00 2001 From: Alexandre Pujol Date: Sun, 28 Apr 2024 12:06:40 +0100 Subject: [PATCH] feat(aa-log): speed up log generation. --- pkg/logs/loggers.go | 48 ++++++++++++++++++++++----------------------- pkg/util/tools.go | 12 +++++++----- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pkg/logs/loggers.go b/pkg/logs/loggers.go index 0848944c..faa76a1f 100644 --- a/pkg/logs/loggers.go +++ b/pkg/logs/loggers.go @@ -32,7 +32,8 @@ type systemdLog struct { // GetApparmorLogs return a list of cleaned apparmor logs from a file func GetApparmorLogs(file io.Reader, profile string) []string { - res := "" + var logs []string + isAppArmorLog := isAppArmorLogTemplate.Copy() if profile != "" { exp := `apparmor=("DENIED"|"ALLOWED"|"AUDIT")` @@ -40,19 +41,15 @@ func GetApparmorLogs(file io.Reader, profile string) []string { isAppArmorLog = regexp.MustCompile(exp) } - // Select Apparmor logs scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if isAppArmorLog.MatchString(line) { - res += line + "\n" + logs = append(logs, + regCleanLogs.Replace(util.DecodeHexInString(line)), + ) } } - - // Clean & remove doublon in logs - res = util.DecodeHexInString(res) - res = regCleanLogs.Replace(res) - logs := strings.Split(res, "\n") return util.RemoveDuplicate(logs) } @@ -60,23 +57,23 @@ func GetApparmorLogs(file io.Reader, profile string) []string { func GetAuditLogs(path string) (io.Reader, error) { file, err := os.Open(filepath.Clean(path)) if err != nil { - return file, err + return nil, err } - return file, err + return file, nil } // GetJournalctlLogs return a reader with the logs entries from Systemd func GetJournalctlLogs(path string, useFile bool) (io.Reader, error) { var logs []systemdLog var stdout bytes.Buffer - var unfilteredValue string + var scanner *bufio.Scanner if useFile { - content, err := os.ReadFile(filepath.Clean(path)) + file, err := os.Open(filepath.Clean(path)) if err != nil { return nil, err } - unfilteredValue = string(content) + scanner = bufio.NewScanner(file) } else { // journalctl -b -o json --output-fields=MESSAGE > systemd.log cmd := exec.Command("journalctl", "--boot", "--output=json", "--output-fields=MESSAGE") @@ -84,26 +81,27 @@ func GetJournalctlLogs(path string, useFile bool) (io.Reader, error) { if err := cmd.Run(); err != nil { return nil, err } - unfilteredValue = stdout.String() + scanner = bufio.NewScanner(&stdout) } - value := "" - for _, v := range strings.Split(unfilteredValue, "\n") { - if strings.Contains(v, "apparmor") { - value += v + "\n" + var jctlRaw []string + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "apparmor") { + jctlRaw = append(jctlRaw, line) } } - value = strings.Replace(value, "\n", ",\n", -1) - value = strings.TrimSuffix(value, ",\n") - value = `[` + value + `]` - if err := json.Unmarshal([]byte(value), &logs); err != nil { + + jctlStr := "[" + strings.Join(jctlRaw, ",\n") + "]" + if err := json.Unmarshal([]byte(jctlStr), &logs); err != nil { return nil, err } - res := "" + + var res strings.Builder for _, log := range logs { - res += log.Message + "\n" + res.WriteString(log.Message + "\n") } - return strings.NewReader(res), nil + return strings.NewReader(res.String()), nil } // SelectLogFile return the path of the available log file to parse (audit, syslog, .1, .2) diff --git a/pkg/util/tools.go b/pkg/util/tools.go index eb339faa..c7d91a8d 100644 --- a/pkg/util/tools.go +++ b/pkg/util/tools.go @@ -19,6 +19,11 @@ var ( `\s*` + Comment + `.*`, ``, `(?m)^(?:[\t\s]*(?:\r?\n|\r))+`, ``, }) + regHex = map[string]*regexp.Regexp{ + "name": regexp.MustCompile(`name=[0-9A-F]+`), + "comm": regexp.MustCompile(`comm=[0-9A-F]+`), + "profile": regexp.MustCompile(`profile=[0-9A-F]+`), + } ) type RegexReplList []RegexRepl @@ -30,7 +35,7 @@ type RegexRepl struct { // ToRegexRepl convert slice of regex into a slice of RegexRepl func ToRegexRepl(in []string) RegexReplList { - out := make([]RegexRepl, 0) + out := make([]RegexRepl, 0, len(in)/2) idx := 0 for idx < len(in)-1 { regex, repl := in[idx], in[idx+1] @@ -52,10 +57,7 @@ func (rr RegexReplList) Replace(str string) string { // DecodeHexInString decode and replace all hex value in a given string of "key=value" format. func DecodeHexInString(str string) string { - toDecode := []string{"name", "comm", "profile"} - for _, name := range toDecode { - exp := name + `=[0-9A-F]+` - re := regexp.MustCompile(exp) + for name, re := range regHex { str = re.ReplaceAllStringFunc(str, func(s string) string { hexa := s[len(name)+1:] bs, _ := hex.DecodeString(hexa)