feat(aa-log): minor improvment in rule generation & formatting.

This commit is contained in:
Alexandre Pujol 2024-09-26 22:15:46 +01:00
parent fbdf9cea64
commit 83bc7d3ade
Failed to generate hash of commit
7 changed files with 97 additions and 34 deletions

View file

@ -9,8 +9,8 @@ import (
) )
type Base struct { type Base struct {
IsLineRule bool
Comment string Comment string
IsLineRule bool
NoNewPrivs bool NoNewPrivs bool
FileInherit bool FileInherit bool
Optional bool Optional bool

View file

@ -118,6 +118,21 @@ func (r *File) String() string {
} }
func (r *File) Validate() error { func (r *File) Validate() error {
if !isAARE(r.Path) {
return fmt.Errorf("'%s' is not a valid AARE", r.Path)
}
for _, v := range r.Access {
if v == "" {
continue
}
if !slices.Contains(requirements[r.Kind()]["access"], v) ||
!slices.Contains(requirements[r.Kind()]["transition"], v) {
return fmt.Errorf("invalid mode '%s'", v)
}
}
if r.Target != "" && !isAARE(r.Target) {
return fmt.Errorf("'%s' is not a valid AARE", r.Target)
}
return nil return nil
} }
@ -260,6 +275,12 @@ func (r *Link) String() string {
} }
func (r *Link) Validate() error { func (r *Link) Validate() error {
if !isAARE(r.Path) {
return fmt.Errorf("'%s' is not a valid AARE", r.Path)
}
if !isAARE(r.Target) {
return fmt.Errorf("'%s' is not a valid AARE", r.Target)
}
return nil return nil
} }

View file

@ -17,10 +17,10 @@ const (
func init() { func init() {
requirements[MOUNT] = requirement{ requirements[MOUNT] = requirement{
"flags": { "flags": {
"acl", "async", "atime", "ro", "rw", "bind", "rbind", "dev", "ro", "rw", "acl", "async", "atime", "bind", "dev", "diratime",
"diratime", "dirsync", "exec", "iversion", "loud", "mand", "move", "dirsync", "exec", "iversion", "loud", "mand", "move", "noacl",
"noacl", "noatime", "nodev", "nodiratime", "noexec", "noiversion", "noatime", "nodev", "nodiratime", "noexec", "noiversion", "nomand",
"nomand", "norelatime", "nosuid", "nouser", "private", "relatime", "norelatime", "nosuid", "nouser", "private", "rbind", "relatime",
"remount", "rprivate", "rshared", "rslave", "runbindable", "shared", "remount", "rprivate", "rshared", "rslave", "runbindable", "shared",
"silent", "slave", "strictatime", "suid", "sync", "unbindable", "silent", "slave", "strictatime", "suid", "sync", "unbindable",
"user", "verbose", "user", "verbose",

View file

@ -495,9 +495,15 @@ func (r rule) String() string {
} }
func isAARE(str string) bool { func isAARE(str string) bool {
return strings.HasPrefix(str, "@") || if len(str) < 1 {
strings.HasPrefix(str, "/") || return false
strings.HasPrefix(str, "\"") }
switch str[0] {
case '@', '/', '"':
return true
default:
return false
}
} }
// Convert a slice of internal rules to a slice of ApparmorRule. // Convert a slice of internal rules to a slice of ApparmorRule.
@ -652,8 +658,8 @@ done:
} }
// Parse apparmor profile rules by paragraphs // Parse apparmor profile rules by paragraphs
func ParseRules(input string) ([]Rules, []string, error) { func ParseRules(input string) (ParaRules, []string, error) {
paragraphRules := []Rules{} paragraphRules := ParaRules{}
paragraphs := []string{} paragraphs := []string{}
for _, match := range regParagraph.FindAllStringSubmatch(input, -1) { for _, match := range regParagraph.FindAllStringSubmatch(input, -1) {

View file

@ -139,16 +139,18 @@ func (p *Profile) GetAttachments() string {
var ( var (
newLogMap = map[string]func(log map[string]string) Rule{ newLogMap = map[string]func(log map[string]string) Rule{
// class
"rlimits": newRlimitFromLog, "rlimits": newRlimitFromLog,
"cap": newCapabilityFromLog,
"io_uring": newIOUringFromLog,
"signal": newSignalFromLog,
"ptrace": newPtraceFromLog,
"namespace": newUsernsFromLog, "namespace": newUsernsFromLog,
"unix": newUnixFromLog, "cap": newCapabilityFromLog,
"dbus": newDbusFromLog, "net": newNetworkFromLog,
"posix_mqueue": newMqueueFromLog, "posix_mqueue": newMqueueFromLog,
"sysv_mqueue": newMqueueFromLog, "sysv_mqueue": newMqueueFromLog,
"signal": newSignalFromLog,
"ptrace": newPtraceFromLog,
"unix": newUnixFromLog,
"io_uring": newIOUringFromLog,
"dbus": newDbusFromLog,
"mount": func(log map[string]string) Rule { "mount": func(log map[string]string) Rule {
if strings.Contains(log["flags"], "remount") { if strings.Contains(log["flags"], "remount") {
return newRemountFromLog(log) return newRemountFromLog(log)
@ -156,7 +158,6 @@ var (
newRule := newLogMountMap[log["operation"]] newRule := newLogMountMap[log["operation"]]
return newRule(log) return newRule(log)
}, },
"net": newNetworkFromLog,
"file": func(log map[string]string) Rule { "file": func(log map[string]string) Rule {
if log["operation"] == "change_onexec" { if log["operation"] == "change_onexec" {
return newChangeProfileFromLog(log) return newChangeProfileFromLog(log)
@ -164,14 +165,19 @@ var (
return newFileFromLog(log) return newFileFromLog(log)
} }
}, },
"exec": newFileFromLog, // operation
"getattr": newFileFromLog, "capable": newCapabilityFromLog,
"mkdir": newFileFromLog, "chmod": newFileFromLog,
"mknod": newFileFromLog, "exec": newFileFromLog,
"open": newFileFromLog, "getattr": newFileFromLog,
"rename_src": newFileFromLog, "link": newFileFromLog,
"truncate": newFileFromLog, "mkdir": newFileFromLog,
"unlink": newFileFromLog, "mknod": newFileFromLog,
"open": newFileFromLog,
"rename_dest": newFileFromLog,
"rename_src": newFileFromLog,
"truncate": newFileFromLog,
"unlink": newFileFromLog,
} }
newLogMountMap = map[string]func(log map[string]string) Rule{ newLogMountMap = map[string]func(log map[string]string) Rule{
"mount": newMountFromLog, "mount": newMountFromLog,
@ -213,7 +219,7 @@ func (p *Profile) AddRule(log map[string]string) {
case strings.Contains(log["operation"], "dbus"): case strings.Contains(log["operation"], "dbus"):
p.Rules = append(p.Rules, newDbusFromLog(log)) p.Rules = append(p.Rules, newDbusFromLog(log))
default: default:
fmt.Printf("unknown log type: %s", log["operation"]) fmt.Printf("unknown log type: %s\n", log["operation"])
} }
} }
} }

View file

@ -94,7 +94,7 @@ func (r Rules) Delete(i int) Rules {
} }
func (r Rules) DeleteKind(kind Kind) Rules { func (r Rules) DeleteKind(kind Kind) Rules {
res := make(Rules, 0) res := make(Rules, 0, len(r))
for _, rule := range r { for _, rule := range r {
if rule == nil { if rule == nil {
continue continue
@ -106,8 +106,8 @@ func (r Rules) DeleteKind(kind Kind) Rules {
return res return res
} }
func (r Rules) Filter(filter Kind) Rules { func (r Rules) FilterOut(filter Kind) Rules {
res := make(Rules, 0) res := make(Rules, 0, len(r))
for _, rule := range r { for _, rule := range r {
if rule == nil { if rule == nil {
continue continue
@ -119,8 +119,21 @@ func (r Rules) Filter(filter Kind) Rules {
return res return res
} }
func (r Rules) Filter(filter Kind) Rules {
res := make(Rules, 0, len(r))
for _, rule := range r {
if rule == nil {
continue
}
if rule.Kind() == filter {
res = append(res, rule)
}
}
return res
}
func (r Rules) GetVariables() []*Variable { func (r Rules) GetVariables() []*Variable {
res := make([]*Variable, 0) res := make([]*Variable, 0, len(r))
for _, rule := range r { for _, rule := range r {
switch rule := rule.(type) { switch rule := rule.(type) {
case *Variable: case *Variable:
@ -131,7 +144,7 @@ func (r Rules) GetVariables() []*Variable {
} }
func (r Rules) GetIncludes() []*Include { func (r Rules) GetIncludes() []*Include {
res := make([]*Include, 0) res := make([]*Include, 0, len(r))
for _, rule := range r { for _, rule := range r {
switch rule := rule.(type) { switch rule := rule.(type) {
case *Include: case *Include:
@ -247,3 +260,20 @@ func (r Rules) Format() Rules {
r.setPaddings(paddingsIndex, paddingsMaxLen) r.setPaddings(paddingsIndex, paddingsMaxLen)
return r return r
} }
// ParaRules is a slice of Rules grouped by paragraph
type ParaRules []Rules
func (r ParaRules) Flatten() Rules {
totalLen := 0
for i := range r {
totalLen += len(r[i])
}
res := make(Rules, 0, totalLen)
for i := range r {
res = append(res, r[i]...)
}
return res
}

View file

@ -138,7 +138,7 @@ var (
// The order AARE should be sorted // The order AARE should be sorted
stringAlphabet = []byte( stringAlphabet = []byte(
"!\"#$%&'*(){}[]+,-./:;<=>?@\\^_`|~0123456789abcdefghijklmnopqrstuvwxyz", "!\"#$%&'*(){}[]@+,-./:;<=>?\\^_`|~0123456789abcdefghijklmnopqrstuvwxyz",
) )
stringWeights = generateWeights(stringAlphabet) stringWeights = generateWeights(stringAlphabet)
@ -232,11 +232,11 @@ func cjoin(i any) string {
} }
} }
func kindOf(i any) string { func kindOf(i Rule) string {
if i == nil { if i == nil {
return "" return ""
} }
return i.(Rule).Kind().String() return i.Kind().String()
} }
func setindent(i string) string { func setindent(i string) string {