feat(aa-log): resolve all main apparmor vars in log.
This also deprecate the anonymize option
This commit is contained in:
parent
5ee31716ae
commit
e0f79b9c9a
4 changed files with 57 additions and 123 deletions
|
|
@ -28,19 +28,17 @@ Options:
|
||||||
-h, --help Show this help message and exit.
|
-h, --help Show this help message and exit.
|
||||||
-f, --file FILE Set a logfile or a suffix to the default log file.
|
-f, --file FILE Set a logfile or a suffix to the default log file.
|
||||||
-s, --systemd Parse systemd logs from journalctl.
|
-s, --systemd Parse systemd logs from journalctl.
|
||||||
-a, --anonymize Anonymize the logs.
|
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
// Command line options
|
// Command line options
|
||||||
var (
|
var (
|
||||||
help bool
|
help bool
|
||||||
anonymize bool
|
|
||||||
path string
|
path string
|
||||||
systemd bool
|
systemd bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func aaLog(logger string, path string, profile string, anonymize bool) error {
|
func aaLog(logger string, path string, profile string) error {
|
||||||
var err error
|
var err error
|
||||||
var file io.Reader
|
var file io.Reader
|
||||||
|
|
||||||
|
|
@ -56,9 +54,6 @@ func aaLog(logger string, path string, profile string, anonymize bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
aaLogs := logs.NewApparmorLogs(file, profile)
|
aaLogs := logs.NewApparmorLogs(file, profile)
|
||||||
if anonymize {
|
|
||||||
aaLogs.Anonymize()
|
|
||||||
}
|
|
||||||
fmt.Print(aaLogs.String())
|
fmt.Print(aaLogs.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -70,8 +65,6 @@ func init() {
|
||||||
flag.StringVar(&path, "file", "", "Set a logfile or a suffix to the default log file.")
|
flag.StringVar(&path, "file", "", "Set a logfile or a suffix to the default log file.")
|
||||||
flag.BoolVar(&systemd, "s", false, "Parse systemd logs from journalctl.")
|
flag.BoolVar(&systemd, "s", false, "Parse systemd logs from journalctl.")
|
||||||
flag.BoolVar(&systemd, "systemd", false, "Parse systemd logs from journalctl.")
|
flag.BoolVar(&systemd, "systemd", false, "Parse systemd logs from journalctl.")
|
||||||
flag.BoolVar(&anonymize, "a", false, "Anonymize the logs.")
|
|
||||||
flag.BoolVar(&anonymize, "anonymize", false, "Anonymize the logs.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -93,7 +86,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
logfile := logs.GetLogFile(path)
|
logfile := logs.GetLogFile(path)
|
||||||
err := aaLog(logger, logfile, profile, anonymize)
|
err := aaLog(logger, logfile, profile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func TestGetJournalctlLogs(t *testing.T) {
|
||||||
"profile": "",
|
"profile": "",
|
||||||
"label": "gsd-xsettings",
|
"label": "gsd-xsettings",
|
||||||
"operation": "dbus_method_call",
|
"operation": "dbus_method_call",
|
||||||
"name": ":1.88",
|
"name": ":*",
|
||||||
"mask": "receive",
|
"mask": "receive",
|
||||||
"bus": "session",
|
"bus": "session",
|
||||||
"path": "/org/gtk/Settings",
|
"path": "/org/gtk/Settings",
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os/user"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -30,16 +29,51 @@ const (
|
||||||
boldYellow = "\033[1;33m"
|
boldYellow = "\033[1;33m"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Anonymized username
|
|
||||||
const Username = "AAD"
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
quoted bool
|
quoted bool
|
||||||
isAppArmorLogTemplate = regexp.MustCompile(`apparmor=("DENIED"|"ALLOWED"|"AUDIT")`)
|
isAppArmorLogTemplate = regexp.MustCompile(`apparmor=("DENIED"|"ALLOWED"|"AUDIT")`)
|
||||||
regAALogs = util.ToRegexRepl([]string{
|
regCleanLogs = util.ToRegexRepl([]string{
|
||||||
|
// Clean apparmor log file
|
||||||
`.*apparmor="`, `apparmor="`,
|
`.*apparmor="`, `apparmor="`,
|
||||||
`(peer_|)pid=[0-9]*\s`, " ",
|
`(peer_|)pid=[0-9]*\s`, " ",
|
||||||
`\x1d`, " ",
|
`\x1d`, " ",
|
||||||
|
|
||||||
|
// Resolve classic user variables
|
||||||
|
`/home/[^/]+/.cache`, `@{user_cache_dirs}`,
|
||||||
|
`/home/[^/]+/.config`, `@{user_config_dirs}`,
|
||||||
|
`/home/[^/]+/.local/share`, `@{user_share_dirs}`,
|
||||||
|
`/home/[^/]+/.local/state`, `@{user_state_dirs}`,
|
||||||
|
`/home/[^/]+/.local/bin`, `@{user_bin_dirs}`,
|
||||||
|
`/home/[^/]+/.local/lib`, `@{user_lib_dirs}`,
|
||||||
|
`/home/[^/]+/.ssh`, `@{HOME}/@{XDG_SSH_DIR}`,
|
||||||
|
`/home/[^/]+/.gnupg`, `@{HOME}/@{XDG_GPG_DIR}`,
|
||||||
|
`/home/[^/]+`, `@{HOME}`,
|
||||||
|
|
||||||
|
// Resolve classic system variables
|
||||||
|
`/usr/lib(|32|64|exec)`, `@{lib}`,
|
||||||
|
`/usr/(|s)bin`, `@{bin}`,
|
||||||
|
`/run/`, `@{run}/`,
|
||||||
|
`user/[0-9]*/`, `user/@{uid}/`,
|
||||||
|
`/proc/`, `@{PROC}/`,
|
||||||
|
`@{PROC}/[0-9]*/`, `@{PROC}/@{pid}/`,
|
||||||
|
`@{PROC}/@{pid}/task/[0-9]*/`, `@{PROC}/@{pid}/task/@{tid}/`,
|
||||||
|
`/sys/`, `@{sys}/`,
|
||||||
|
`@{PROC}@{sys}/`, `@{PROC}/sys/`,
|
||||||
|
|
||||||
|
// Some system glob
|
||||||
|
`pci[/0-9:.]+`, `pci[0-9]*/**/`, // PCI structure
|
||||||
|
`:1.[0-9]*`, `:*`, // dbus peer name
|
||||||
|
`@{bin}/(|ba|da)sh`, `@{bin}/{,ba,da}sh`, // collect all shell
|
||||||
|
`@{lib}/modules/[^/]+\/`, `@{lib}/modules/*/`, // strip kernel version numbers from kernel module accesses
|
||||||
|
|
||||||
|
// Remove basic rules from abstractions/base
|
||||||
|
`(?m)^.*/etc/[^/]+so.*$`, ``,
|
||||||
|
`(?m)^.*@{lib}/[^/]+so.*$`, ``,
|
||||||
|
`(?m)^.*@{lib}/locale/.*$`, ``,
|
||||||
|
`(?m)^.*/usr/share/(locale|zoneinfo)/.*$`, ``,
|
||||||
|
`(?m)^.*/usr/share/zoneinfo/.*$`, ``,
|
||||||
|
`(?m)^.*/dev/(null|zero|full).*$`, ``,
|
||||||
|
`(?m)^.*/dev/(u|)random.*$`, ``,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -81,12 +115,10 @@ func NewApparmorLogs(file io.Reader, profile string) AppArmorLogs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean logs
|
// Clean & remove doublon in logs
|
||||||
for _, aa := range regAALogs {
|
for _, aa := range regCleanLogs {
|
||||||
log = aa.Regex.ReplaceAllLiteralString(log, aa.Repl)
|
log = aa.Regex.ReplaceAllLiteralString(log, aa.Repl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove doublon in logs
|
|
||||||
logs := strings.Split(log, "\n")
|
logs := strings.Split(log, "\n")
|
||||||
logs = util.RemoveDuplicate(logs)
|
logs = util.RemoveDuplicate(logs)
|
||||||
|
|
||||||
|
|
@ -117,26 +149,6 @@ func NewApparmorLogs(file io.Reader, profile string) AppArmorLogs {
|
||||||
return aaLogs
|
return aaLogs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anonymize the logs before reporting
|
|
||||||
func (aaLogs AppArmorLogs) Anonymize() {
|
|
||||||
user, _ := user.Current()
|
|
||||||
keys := []string{"name", "comm"}
|
|
||||||
regAnonymizeLogs := util.ToRegexRepl([]string{
|
|
||||||
user.Username, Username,
|
|
||||||
`/home/[^/]+`, `/home/` + Username,
|
|
||||||
`[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*`, `b08dfa60-83e7-567a-1921-a715000001fb`,
|
|
||||||
})
|
|
||||||
for _, log := range aaLogs {
|
|
||||||
for _, key := range keys {
|
|
||||||
if _, ok := log[key]; ok {
|
|
||||||
for _, aa := range regAnonymizeLogs {
|
|
||||||
log[key] = aa.Regex.ReplaceAllLiteralString(log[key], aa.Repl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a formatted AppArmor logs string
|
// String returns a formatted AppArmor logs string
|
||||||
func (aaLogs AppArmorLogs) String() string {
|
func (aaLogs AppArmorLogs) String() string {
|
||||||
// Apparmor log states
|
// Apparmor log states
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ var (
|
||||||
"apparmor": "ALLOWED",
|
"apparmor": "ALLOWED",
|
||||||
"profile": "man",
|
"profile": "man",
|
||||||
"operation": "exec",
|
"operation": "exec",
|
||||||
"name": "/usr/bin/preconv",
|
"name": "@{bin}/preconv",
|
||||||
"target": "man_groff",
|
"target": "man_groff",
|
||||||
"info": "no new privs",
|
"info": "no new privs",
|
||||||
"comm": "man",
|
"comm": "man",
|
||||||
|
|
@ -55,7 +55,7 @@ var (
|
||||||
"interface": "org.freedesktop.DBus",
|
"interface": "org.freedesktop.DBus",
|
||||||
"member": "AddMatch",
|
"member": "AddMatch",
|
||||||
"peer_label": "dbus-daemon",
|
"peer_label": "dbus-daemon",
|
||||||
"exe": "/usr/bin/dbus-daemon",
|
"exe": "@{bin}/dbus-daemon",
|
||||||
"sauid": "102",
|
"sauid": "102",
|
||||||
"hostname": "?",
|
"hostname": "?",
|
||||||
"addr": "?",
|
"addr": "?",
|
||||||
|
|
@ -79,7 +79,7 @@ func TestAppArmorEvents(t *testing.T) {
|
||||||
want: AppArmorLogs{
|
want: AppArmorLogs{
|
||||||
{
|
{
|
||||||
"apparmor": "ALLOWED",
|
"apparmor": "ALLOWED",
|
||||||
"profile": "/usr/sbin/httpd2-prefork//vhost_foo",
|
"profile": "@{bin}/httpd2-prefork//vhost_foo",
|
||||||
"operation": "rename_dest",
|
"operation": "rename_dest",
|
||||||
"name": "/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg",
|
"name": "/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg",
|
||||||
"comm": "httpd2-prefork",
|
"comm": "httpd2-prefork",
|
||||||
|
|
@ -99,7 +99,7 @@ func TestAppArmorEvents(t *testing.T) {
|
||||||
"apparmor": "ALLOWED",
|
"apparmor": "ALLOWED",
|
||||||
"profile": "foo bar",
|
"profile": "foo bar",
|
||||||
"operation": "file_perm",
|
"operation": "file_perm",
|
||||||
"name": "/home/foo/.bash_history",
|
"name": "@{HOME}/.bash_history",
|
||||||
"comm": "bash",
|
"comm": "bash",
|
||||||
"requested_mask": "rw",
|
"requested_mask": "rw",
|
||||||
"denied_mask": "rw",
|
"denied_mask": "rw",
|
||||||
|
|
@ -117,7 +117,7 @@ func TestAppArmorEvents(t *testing.T) {
|
||||||
"apparmor": "ALLOWED",
|
"apparmor": "ALLOWED",
|
||||||
"profile": "/sbin/klogd",
|
"profile": "/sbin/klogd",
|
||||||
"operation": "file_mmap",
|
"operation": "file_mmap",
|
||||||
"name": "var/run/nscd/passwd",
|
"name": "var@{run}/nscd/passwd",
|
||||||
"comm": "id",
|
"comm": "id",
|
||||||
"info": "Failed name lookup - disconnected path",
|
"info": "Failed name lookup - disconnected path",
|
||||||
"requested_mask": "r",
|
"requested_mask": "r",
|
||||||
|
|
@ -144,7 +144,7 @@ func TestAppArmorEvents(t *testing.T) {
|
||||||
"interface": "org.freedesktop.PolicyKit1.Authority",
|
"interface": "org.freedesktop.PolicyKit1.Authority",
|
||||||
"member": "CheckAuthorization",
|
"member": "CheckAuthorization",
|
||||||
"peer_label": "polkitd",
|
"peer_label": "polkitd",
|
||||||
"exe": "/usr/bin/dbus-daemon",
|
"exe": "@{bin}/dbus-daemon",
|
||||||
"sauid": "102",
|
"sauid": "102",
|
||||||
"hostname": "?",
|
"hostname": "?",
|
||||||
"addr": "?",
|
"addr": "?",
|
||||||
|
|
@ -195,7 +195,7 @@ func TestNewApparmorLogs(t *testing.T) {
|
||||||
"apparmor": "DENIED",
|
"apparmor": "DENIED",
|
||||||
"profile": "dnsmasq",
|
"profile": "dnsmasq",
|
||||||
"operation": "open",
|
"operation": "open",
|
||||||
"name": "/proc/sys/kernel/osrelease",
|
"name": "@{PROC}/sys/kernel/osrelease",
|
||||||
"comm": "dnsmasq",
|
"comm": "dnsmasq",
|
||||||
"requested_mask": "r",
|
"requested_mask": "r",
|
||||||
"denied_mask": "r",
|
"denied_mask": "r",
|
||||||
|
|
@ -208,7 +208,7 @@ func TestNewApparmorLogs(t *testing.T) {
|
||||||
"apparmor": "DENIED",
|
"apparmor": "DENIED",
|
||||||
"profile": "dnsmasq",
|
"profile": "dnsmasq",
|
||||||
"operation": "open",
|
"operation": "open",
|
||||||
"name": "/proc/1/environ",
|
"name": "@{PROC}/@{pid}/environ",
|
||||||
"comm": "dnsmasq",
|
"comm": "dnsmasq",
|
||||||
"requested_mask": "r",
|
"requested_mask": "r",
|
||||||
"denied_mask": "r",
|
"denied_mask": "r",
|
||||||
|
|
@ -221,7 +221,7 @@ func TestNewApparmorLogs(t *testing.T) {
|
||||||
"apparmor": "DENIED",
|
"apparmor": "DENIED",
|
||||||
"profile": "dnsmasq",
|
"profile": "dnsmasq",
|
||||||
"operation": "open",
|
"operation": "open",
|
||||||
"name": "/proc/cmdline",
|
"name": "@{PROC}/cmdline",
|
||||||
"comm": "dnsmasq",
|
"comm": "dnsmasq",
|
||||||
"requested_mask": "r",
|
"requested_mask": "r",
|
||||||
"denied_mask": "r",
|
"denied_mask": "r",
|
||||||
|
|
@ -272,7 +272,7 @@ func TestAppArmorLogs_String(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "man",
|
name: "man",
|
||||||
aaLogs: refMan,
|
aaLogs: refMan,
|
||||||
want: "\033[1;32mALLOWED\033[0m \033[34mman\033[0m \033[33mexec\033[0m \033[35m/usr/bin/preconv\033[0m -> \033[35mman_groff\033[0m info=\"no new privs\" comm=man requested_mask=\033[1;31mx\033[0m denied_mask=\033[1;31mx\033[0m error=-1\n",
|
want: "\033[1;32mALLOWED\033[0m \033[34mman\033[0m \033[33mexec\033[0m \033[35m@{bin}/preconv\033[0m -> \033[35mman_groff\033[0m info=\"no new privs\" comm=man requested_mask=\033[1;31mx\033[0m denied_mask=\033[1;31mx\033[0m error=-1\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "power-profiles-daemon",
|
name: "power-profiles-daemon",
|
||||||
|
|
@ -288,74 +288,3 @@ func TestAppArmorLogs_String(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppArmorLogs_Anonymize(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
aaLogs AppArmorLogs
|
|
||||||
want AppArmorLogs
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Anonymize Username",
|
|
||||||
aaLogs: AppArmorLogs{
|
|
||||||
{
|
|
||||||
"apparmor": "ALLOWED",
|
|
||||||
"profile": "foo",
|
|
||||||
"operation": "file_perm",
|
|
||||||
"name": "/home/foo/.bash_history",
|
|
||||||
"comm": "bash",
|
|
||||||
"requested_mask": "rw",
|
|
||||||
"denied_mask": "rw",
|
|
||||||
"parent": "16001",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: AppArmorLogs{
|
|
||||||
{
|
|
||||||
"apparmor": "ALLOWED",
|
|
||||||
"profile": "foo",
|
|
||||||
"operation": "file_perm",
|
|
||||||
"name": "/home/AAD/.bash_history",
|
|
||||||
"comm": "bash",
|
|
||||||
"requested_mask": "rw",
|
|
||||||
"denied_mask": "rw",
|
|
||||||
"parent": "16001",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Anonymize UUID",
|
|
||||||
aaLogs: AppArmorLogs{
|
|
||||||
{
|
|
||||||
"apparmor": "ALLOWED",
|
|
||||||
"profile": "drkonqi",
|
|
||||||
"operation": "file_perm",
|
|
||||||
"name": "/sys/devices/pci0000:00/0000:00:02.0/drm/card1/metrics/399d3001-97d6-4240-b065-4fb843138e17/id",
|
|
||||||
"comm": "bash",
|
|
||||||
"requested_mask": "r",
|
|
||||||
"denied_mask": "r",
|
|
||||||
"parent": "16001",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: AppArmorLogs{
|
|
||||||
{
|
|
||||||
"apparmor": "ALLOWED",
|
|
||||||
"profile": "drkonqi",
|
|
||||||
"operation": "file_perm",
|
|
||||||
"name": "/sys/devices/pci0000:00/0000:00:02.0/drm/card1/metrics/b08dfa60-83e7-567a-1921-a715000001fb/id",
|
|
||||||
"comm": "bash",
|
|
||||||
"requested_mask": "r",
|
|
||||||
"denied_mask": "r",
|
|
||||||
"parent": "16001",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
tt.aaLogs.Anonymize()
|
|
||||||
if !reflect.DeepEqual(tt.aaLogs, tt.want) {
|
|
||||||
t.Errorf("Anonymize() = %v, want %v", tt.aaLogs, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue