feat(aa-log): speed up log generation.

This commit is contained in:
Alexandre Pujol 2024-04-28 12:06:40 +01:00
parent b4e5837bb9
commit d1fb9574cb
Failed to generate hash of commit
2 changed files with 30 additions and 30 deletions

View file

@ -32,7 +32,8 @@ type systemdLog struct {
// GetApparmorLogs return a list of cleaned apparmor logs from a file // GetApparmorLogs return a list of cleaned apparmor logs from a file
func GetApparmorLogs(file io.Reader, profile string) []string { func GetApparmorLogs(file io.Reader, profile string) []string {
res := "" var logs []string
isAppArmorLog := isAppArmorLogTemplate.Copy() isAppArmorLog := isAppArmorLogTemplate.Copy()
if profile != "" { if profile != "" {
exp := `apparmor=("DENIED"|"ALLOWED"|"AUDIT")` exp := `apparmor=("DENIED"|"ALLOWED"|"AUDIT")`
@ -40,19 +41,15 @@ func GetApparmorLogs(file io.Reader, profile string) []string {
isAppArmorLog = regexp.MustCompile(exp) isAppArmorLog = regexp.MustCompile(exp)
} }
// Select Apparmor logs
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
if isAppArmorLog.MatchString(line) { 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) return util.RemoveDuplicate(logs)
} }
@ -60,23 +57,23 @@ func GetApparmorLogs(file io.Reader, profile string) []string {
func GetAuditLogs(path string) (io.Reader, error) { func GetAuditLogs(path string) (io.Reader, error) {
file, err := os.Open(filepath.Clean(path)) file, err := os.Open(filepath.Clean(path))
if err != nil { 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 // GetJournalctlLogs return a reader with the logs entries from Systemd
func GetJournalctlLogs(path string, useFile bool) (io.Reader, error) { func GetJournalctlLogs(path string, useFile bool) (io.Reader, error) {
var logs []systemdLog var logs []systemdLog
var stdout bytes.Buffer var stdout bytes.Buffer
var unfilteredValue string var scanner *bufio.Scanner
if useFile { if useFile {
content, err := os.ReadFile(filepath.Clean(path)) file, err := os.Open(filepath.Clean(path))
if err != nil { if err != nil {
return nil, err return nil, err
} }
unfilteredValue = string(content) scanner = bufio.NewScanner(file)
} else { } else {
// journalctl -b -o json --output-fields=MESSAGE > systemd.log // journalctl -b -o json --output-fields=MESSAGE > systemd.log
cmd := exec.Command("journalctl", "--boot", "--output=json", "--output-fields=MESSAGE") 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 { if err := cmd.Run(); err != nil {
return nil, err return nil, err
} }
unfilteredValue = stdout.String() scanner = bufio.NewScanner(&stdout)
} }
value := "" var jctlRaw []string
for _, v := range strings.Split(unfilteredValue, "\n") { for scanner.Scan() {
if strings.Contains(v, "apparmor") { line := scanner.Text()
value += v + "\n" if strings.Contains(line, "apparmor") {
jctlRaw = append(jctlRaw, line)
} }
} }
value = strings.Replace(value, "\n", ",\n", -1)
value = strings.TrimSuffix(value, ",\n") jctlStr := "[" + strings.Join(jctlRaw, ",\n") + "]"
value = `[` + value + `]` if err := json.Unmarshal([]byte(jctlStr), &logs); err != nil {
if err := json.Unmarshal([]byte(value), &logs); err != nil {
return nil, err return nil, err
} }
res := ""
var res strings.Builder
for _, log := range logs { 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) // SelectLogFile return the path of the available log file to parse (audit, syslog, .1, .2)

View file

@ -19,6 +19,11 @@ var (
`\s*` + Comment + `.*`, ``, `\s*` + Comment + `.*`, ``,
`(?m)^(?:[\t\s]*(?:\r?\n|\r))+`, ``, `(?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 type RegexReplList []RegexRepl
@ -30,7 +35,7 @@ type RegexRepl struct {
// ToRegexRepl convert slice of regex into a slice of RegexRepl // ToRegexRepl convert slice of regex into a slice of RegexRepl
func ToRegexRepl(in []string) RegexReplList { func ToRegexRepl(in []string) RegexReplList {
out := make([]RegexRepl, 0) out := make([]RegexRepl, 0, len(in)/2)
idx := 0 idx := 0
for idx < len(in)-1 { for idx < len(in)-1 {
regex, repl := in[idx], in[idx+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. // DecodeHexInString decode and replace all hex value in a given string of "key=value" format.
func DecodeHexInString(str string) string { func DecodeHexInString(str string) string {
toDecode := []string{"name", "comm", "profile"} for name, re := range regHex {
for _, name := range toDecode {
exp := name + `=[0-9A-F]+`
re := regexp.MustCompile(exp)
str = re.ReplaceAllStringFunc(str, func(s string) string { str = re.ReplaceAllStringFunc(str, func(s string) string {
hexa := s[len(name)+1:] hexa := s[len(name)+1:]
bs, _ := hex.DecodeString(hexa) bs, _ := hex.DecodeString(hexa)