From 1316e0dddedc993898cc4a22a54c1f12f86c0922 Mon Sep 17 00:00:00 2001 From: Alexandre Pujol Date: Sun, 19 Feb 2023 17:53:49 +0000 Subject: [PATCH] feat(aa-log): better integration with journalctl & new usage page. --- cmd/aa-log/main.go | 51 ++++++++++++++++++++++++++--------------- cmd/aa-log/main_test.go | 8 +++---- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/cmd/aa-log/main.go b/cmd/aa-log/main.go index 31cf72abb..ea17baa1a 100644 --- a/cmd/aa-log/main.go +++ b/cmd/aa-log/main.go @@ -1,5 +1,5 @@ // aa-log - Review AppArmor generated messages -// Copyright (C) 2021-2022 Alexandre Pujol +// Copyright (C) 2021-2023 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package main @@ -20,6 +20,23 @@ import ( "strings" ) +const usage = `aa-log [-h] [--systemd] [--dbus] [--file file] [profile] + + Review AppArmor generated messages in a colorful way. Supports logs from + auditd, systemd, syslog as well as dbus session events. + + It can be given an optional profile name to filter the output with. + + Default logs are read from '/var/log/audit/audit.log'. Other files in + '/var/log/audit/' can easily be checked: 'aa-log -f 1' parses 'audit.log.1' + +Options: + -h, --help Show this help message and exit. + -f, --file FILE Set a logfile or a suffix to the default log file. + -s, --systemd Parse systemd logs from journalctl. + +` + // Command line options var ( help bool @@ -104,23 +121,21 @@ func getAuditLogs(path string) (io.Reader, error) { } // getJournalctlLogs return a reader with the logs entries from Systemd -func getJournalctlLogs(path string, user bool, useFile bool) (io.Reader, error) { +func getJournalctlLogs(path string, useFile bool) (io.Reader, error) { var logs []SystemdLog var stdout bytes.Buffer var value string if useFile { + // content, err := os.ReadFile(filepath.Clean(path)) content, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return nil, err } value = string(content) } else { - mode := "--system" - if user { - mode = "--user" - } - cmd := exec.Command("journalctl", mode, "--boot", "--unit=dbus.service", "--output=json") + // journalctl -b -o json > systemd.log + cmd := exec.Command("journalctl", "--boot", "--output=json") cmd.Stdout = &stdout if err := cmd.Run(); err != nil { return nil, err @@ -131,6 +146,7 @@ func getJournalctlLogs(path string, user bool, useFile bool) (io.Reader, error) value = strings.Replace(value, "\n", ",\n", -1) value = strings.TrimSuffix(value, ",\n") value = `[` + value + `]` + // fmt.Printf("value: %v\n", value) if err := json.Unmarshal([]byte(value), &logs); err != nil { return nil, err } @@ -189,7 +205,7 @@ func NewApparmorLogs(file io.Reader, profile string) AppArmorLogs { } } aa["profile"] = decodeHex(aa["profile"]) - toDecode := []string{"profile", "name", "comm"} + toDecode := []string{"name", "comm"} for _, name := range toDecode { if value, ok := aa[name]; ok { aa[name] = decodeHex(value) @@ -267,7 +283,7 @@ func aaLog(logger string, path string, profile string) error { case "auditd": file, err = getAuditLogs(path) case "systemd": - file, err = getJournalctlLogs(path, true, path != LogFile) + file, err = getJournalctlLogs(path, path != LogFile) default: err = fmt.Errorf("Logger %s not supported.", logger) } @@ -281,21 +297,18 @@ func aaLog(logger string, path string, profile string) error { func init() { flag.BoolVar(&help, "h", false, "Show this help message and exit.") - flag.StringVar(&path, "f", LogFile, - "Set a log`file` or a suffix to the default log file.") - flag.BoolVar(&systemd, "s", false, "Parse systemd dbus logs.") + flag.BoolVar(&help, "help", false, "Show this help message and exit.") + flag.StringVar(&path, "f", LogFile, "Set a logfile or a suffix to the default log file.") + flag.StringVar(&path, "file", LogFile, "Set a logfile or a suffix to the default log file.") + flag.BoolVar(&systemd, "s", false, "Parse systemd logs from journalctl.") + flag.BoolVar(&systemd, "systemd", false, "Parse systemd logs from journalctl.") } func main() { + flag.Usage = func() { fmt.Print(usage) } flag.Parse() if help { - fmt.Printf(`aa-log [-h] [-s] [-f file] [profile] - - Review AppArmor generated messages in a colorful way. - It can be given an optional profile name to filter the output with. - -`) - flag.PrintDefaults() + flag.Usage() os.Exit(0) } diff --git a/cmd/aa-log/main_test.go b/cmd/aa-log/main_test.go index 75232b460..28af46c9f 100644 --- a/cmd/aa-log/main_test.go +++ b/cmd/aa-log/main_test.go @@ -94,7 +94,7 @@ func TestAppArmorEvents(t *testing.T) { }, }, { - name: "dbus system", + name: "dbus_system", event: `type=USER_AVC msg=audit(1111111111.111:1111): pid=1780 uid=102 auid=4294967295 ses=4294967295 subj=? msg='apparmor="ALLOWED" operation="dbus_method_call" bus="system" path="/org/freedesktop/PolicyKit1/Authority" interface="org.freedesktop.PolicyKit1.Authority" member="CheckAuthorization" mask="send" name="org.freedesktop.PolicyKit1" pid=1794 label="snapd" peer_pid=1790 peer_label="polkitd" exe="/usr/bin/dbus-daemon" sauid=102 hostname=? addr=? terminal=?'UID="messagebus" AUID="unset" SAUID="messagebus"`, want: AppArmorLogs{ { @@ -113,7 +113,7 @@ func TestAppArmorEvents(t *testing.T) { }, }, { - name: "dbus session", + name: "dbus_session", event: `apparmor="ALLOWED" operation="dbus_bind" bus="session" name="org.freedesktop.portal.Documents" mask="bind" pid=2174 label="xdg-document-portal"`, want: AppArmorLogs{ { @@ -221,13 +221,11 @@ func Test_getJournalctlLogs(t *testing.T) { tests := []struct { name string path string - user bool useFile bool want AppArmorLogs }{ { name: "gsd-xsettings", - user: true, useFile: true, path: "../../tests/systemd.log", want: AppArmorLogs{ @@ -255,7 +253,7 @@ func Test_getJournalctlLogs(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - reader, _ := getJournalctlLogs(tt.path, tt.user, tt.useFile) + reader, _ := getJournalctlLogs(tt.path, tt.useFile) if got := NewApparmorLogs(reader, tt.name); !reflect.DeepEqual(got, tt.want) { t.Errorf("NewApparmorLogs() = %v, want %v", got, tt.want) }