feat(aa-log): improve error formating on rules.

This commit is contained in:
Alexandre Pujol 2023-10-20 23:11:11 +01:00
parent 04cae35e6e
commit 46d25ed922
Failed to generate hash of commit
6 changed files with 45 additions and 13 deletions

View file

@ -62,7 +62,7 @@ var (
"apparmor": "ALLOWED", "apparmor": "ALLOWED",
"class": "mount", "class": "mount",
"operation": "mount", "operation": "mount",
"info": "failed perms check", // TODO: not attach_disconnected "info": "failed perms check",
"error": "-13", "error": "-13",
"profile": "dockerd", "profile": "dockerd",
"name": "/var/lib/docker/overlay2/metacopy-check906831159/merged/", "name": "/var/lib/docker/overlay2/metacopy-check906831159/merged/",
@ -71,11 +71,13 @@ var (
"srcname": "overlay", "srcname": "overlay",
} }
mount1 = &Mount{ mount1 = &Mount{
Qualifier: Qualifier{Comment: "failed perms check"},
MountConditions: MountConditions{FsType: "overlay", Options: []string{}}, MountConditions: MountConditions{FsType: "overlay", Options: []string{}},
Source: "overlay", Source: "overlay",
MountPoint: "/var/lib/docker/overlay2/opaque-bug-check1209538631/merged/", MountPoint: "/var/lib/docker/overlay2/opaque-bug-check1209538631/merged/",
} }
mount2 = &Mount{ mount2 = &Mount{
Qualifier: Qualifier{Comment: "failed perms check"},
MountConditions: MountConditions{FsType: "overlay", Options: []string{}}, MountConditions: MountConditions{FsType: "overlay", Options: []string{}},
Source: "overlay", Source: "overlay",
MountPoint: "/var/lib/docker/overlay2/metacopy-check906831159/merged/", MountPoint: "/var/lib/docker/overlay2/metacopy-check906831159/merged/",

View file

@ -66,15 +66,16 @@ func (p *AppArmorProfile) String() string {
// AddRule adds a new rule to the profile from a log map // AddRule adds a new rule to the profile from a log map
func (p *AppArmorProfile) AddRule(log map[string]string) { func (p *AppArmorProfile) AddRule(log map[string]string) {
// Generate profile flags and extra rules
switch log["error"] { switch log["error"] {
case "-2": case "-2":
if !slices.Contains(p.Flags, "mediate_deleted") { if !slices.Contains(p.Flags, "mediate_deleted") {
p.Flags = append(p.Flags, "mediate_deleted") p.Flags = append(p.Flags, "mediate_deleted")
} }
case "-13": case "-13":
// FIXME: -13 can be a lot of things, not only attach_disconnected if strings.Contains(log["info"], "namespace creation restricted") {
// Eg: info="User namespace creation restricted" p.Rules = append(p.Rules, UsernsFromLog(log))
if !slices.Contains(p.Flags, "attach_disconnected") { } else if strings.Contains(log["info"], "disconnected path") && !slices.Contains(p.Flags, "attach_disconnected") {
p.Flags = append(p.Flags, "attach_disconnected") p.Flags = append(p.Flags, "attach_disconnected")
} }
default: default:

View file

@ -153,7 +153,6 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: mount2Log, log: mount2Log,
want: &AppArmorProfile{ want: &AppArmorProfile{
Profile: Profile{ Profile: Profile{
Flags: []string{"attach_disconnected"},
Rules: []ApparmorRule{mount2}, Rules: []ApparmorRule{mount2},
}, },
}, },

View file

@ -4,7 +4,9 @@
package aa package aa
import "strings" import (
"strings"
)
type Rule struct { type Rule struct {
Comment string Comment string
@ -12,7 +14,6 @@ type Rule struct {
FileInherit bool FileInherit bool
} }
func (r *Rule) Less(other any) bool { func (r *Rule) Less(other any) bool {
return false return false
} }
@ -28,6 +29,8 @@ type Qualifier struct {
Owner bool Owner bool
NoNewPrivs bool NoNewPrivs bool
FileInherit bool FileInherit bool
Optional bool
Comment string
Prefix string Prefix string
Padding string Padding string
} }
@ -46,20 +49,41 @@ func NewQualifierFromLog(log map[string]string) Qualifier {
if log["apparmor"] == "AUDIT" { if log["apparmor"] == "AUDIT" {
audit = true audit = true
} }
fileInherit := false fileInherit := false
if log["operation"] == "file_inherit" { if log["operation"] == "file_inherit" {
fileInherit = true fileInherit = true
} }
noNewPrivs := false noNewPrivs := false
if log["error"] == "-1" { optional := false
msg := ""
switch log["error"] {
case "-1":
if strings.Contains(log["info"], "optional:") {
optional = true
msg = strings.Replace(log["info"], "optional: ", "", 1)
} else {
noNewPrivs = true noNewPrivs = true
} }
case "-13":
ignoreProfileInfo := []string{"namespace", "disconnected path"}
for _, info := range ignoreProfileInfo {
if strings.Contains(log["info"], info) {
break
}
}
msg = log["info"]
default:
}
return Qualifier{ return Qualifier{
Audit: audit, Audit: audit,
AccessType: "",
Owner: owner, Owner: owner,
NoNewPrivs: noNewPrivs, NoNewPrivs: noNewPrivs,
FileInherit: fileInherit, FileInherit: fileInherit,
Optional: optional,
Comment: msg,
} }
} }

View file

@ -30,12 +30,12 @@ var (
tmplAppArmorProfile = generateTemplate() tmplAppArmorProfile = generateTemplate()
// convert apparmor requested mask to apparmor access mode // convert apparmor requested mask to apparmor access mode
// TODO: Should be a map of slice, not exhausive yet // TODO: Should be a map of slice, not exhaustive yet
maskToAccess = map[string]string{ maskToAccess = map[string]string{
"a": "w", "a": "w",
"c": "w", "c": "w",
"d": "w", "d": "w",
"k": "rk", "k": "k",
"l": "l", "l": "l",
"m": "rm", "m": "rm",
"r": "r", "r": "r",

View file

@ -1,5 +1,5 @@
{{- define "comment" -}} {{- define "comment" -}}
{{- if or .FileInherit .NoNewPrivs -}} {{- if or .FileInherit .NoNewPrivs .Optional .Comment -}}
{{- " #" -}} {{- " #" -}}
{{- end -}} {{- end -}}
{{- if .FileInherit -}} {{- if .FileInherit -}}
@ -8,4 +8,10 @@
{{- if .NoNewPrivs -}} {{- if .NoNewPrivs -}}
{{- " no new privs" -}} {{- " no new privs" -}}
{{- end -}} {{- end -}}
{{- if .Optional -}}
{{- " optional:" -}}
{{- end -}}
{{- with .Comment -}}
{{ " " }}{{ . }}
{{- end -}}
{{- end -}} {{- end -}}