diff --git a/pkg/aa/rules.go b/pkg/aa/rules.go index cc778309..3244247d 100644 --- a/pkg/aa/rules.go +++ b/pkg/aa/rules.go @@ -4,6 +4,10 @@ package aa +import ( + "golang.org/x/exp/slices" +) + // Preamble section of a profile type Preamble struct { Abi []Abi @@ -200,3 +204,107 @@ type File struct { Target string } +// Rules constructors from logs + +func NewQualifier(owner, noNewPrivs, fileInherit bool) Qualifier { + return Qualifier{ + Audit: false, + AccessType: "", + Owner: owner, + NoNewPrivs: noNewPrivs, + FileInherit: fileInherit, + } +} + +func NewCapability(log map[string]string, noNewPrivs, fileInherit bool) Capability { + return Capability{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + Name: log["capname"], + } +} + +func NewNetwork(log map[string]string, noNewPrivs, fileInherit bool) Network { + return Network{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + AddressExpr: AddressExpr{ + Source: log["laddr"], + Destination: log["faddr"], + Port: log["lport"], + }, + Domain: log["family"], + Type: log["sock_type"], + Protocol: log["protocol"], + } +} + +func NewFile(log map[string]string, noNewPrivs, fileInherit bool) File { + owner := false + if log["fsuid"] == log["ouid"] && log["OUID"] != "root" { + owner = true + } + return File{ + Qualifier: NewQualifier(owner, noNewPrivs, fileInherit), + Path: log["name"], + Access: maskToAccess[log["requested_mask"]], + Target: log["target"], + } +} + +func NewSignal(log map[string]string, noNewPrivs, fileInherit bool) Signal { + return Signal{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + Access: maskToAccess[log["requested_mask"]], + Set: log["signal"], + Peer: log["peer"], + } +} + +func NewPtrace(log map[string]string, noNewPrivs, fileInherit bool) Ptrace { + return Ptrace{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + Access: maskToAccess[log["requested_mask"]], + Peer: log["peer"], + } +} + +func NewUnix(log map[string]string, noNewPrivs, fileInherit bool) Unix { + return Unix{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + Access: maskToAccess[log["requested_mask"]], + Type: log["sock_type"], + Protocol: log["protocol"], + Address: log["addr"], + Label: log["peer_label"], + Attr: log["attr"], + Opt: log["opt"], + Peer: log["peer"], + PeerAddr: log["peer_addr"], + } +} + +func NewMount(log map[string]string, noNewPrivs, fileInherit bool) Mount { + return Mount{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + MountConditions: MountConditions{ + Fs: "", + Op: "", + FsType: log["fstype"], + Options: []string{}, + }, + Source: log["srcname"], + MountPoint: log["name"], + } +} + +func NewDbus(log map[string]string, noNewPrivs, fileInherit bool) Dbus { + return Dbus{ + Qualifier: NewQualifier(false, noNewPrivs, fileInherit), + Access: log["mask"], + Bus: log["bus"], + Name: log["name"], + Path: log["path"], + Interface: log["interface"], + Member: log["member"], + Label: log["peer_label"], + } +} diff --git a/pkg/aa/template.go b/pkg/aa/template.go new file mode 100644 index 00000000..eb4beb47 --- /dev/null +++ b/pkg/aa/template.go @@ -0,0 +1,38 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2023 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package aa + +import ( + _ "embed" + "strings" +) + +// TODO: Should be a map of slice, not exhausive yet +var maskToAccess = map[string]string{ + "a": "w", + "c": "w", + "d": "w", + "k": "rk", + "l": "l", + "m": "rm", + "r": "r", + "ra": "rw", + "read write": "read write", + "read": "read", + "readby": "readby", + "receive": "receive", + "rm": "rm", + "rw": "rw", + "send receive": "send receive", + "send": "send", + "w": "w", + "wc": "w", + "wr": "rw", + "wrc": "rw", + "wrd": "rw", + "write": "write", + "x": "rix", +} +