feat(aa): improve rule creation from log.
This commit is contained in:
parent
13de4182c8
commit
c7485326e8
15 changed files with 62 additions and 57 deletions
|
|
@ -9,9 +9,9 @@ type Capability struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func CapabilityFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func CapabilityFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Capability{
|
return &Capability{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Name: log["capname"],
|
Name: log["capname"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ type ChangeProfile struct {
|
||||||
ProfileName string
|
ProfileName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChangeProfileFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func ChangeProfileFromLog(log map[string]string) ApparmorRule {
|
||||||
return &ChangeProfile{
|
return &ChangeProfile{
|
||||||
ExecMode: log["mode"],
|
ExecMode: log["mode"],
|
||||||
Exec: log["exec"],
|
Exec: log["exec"],
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ type Dbus struct {
|
||||||
Label string
|
Label string
|
||||||
}
|
}
|
||||||
|
|
||||||
func DbusFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func DbusFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Dbus{
|
return &Dbus{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Access: log["mask"],
|
Access: log["mask"],
|
||||||
Bus: log["bus"],
|
Bus: log["bus"],
|
||||||
Name: log["name"],
|
Name: log["name"],
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,9 @@ type File struct {
|
||||||
Target string
|
Target string
|
||||||
}
|
}
|
||||||
|
|
||||||
func FileFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func FileFromLog(log map[string]string) ApparmorRule {
|
||||||
owner := false
|
|
||||||
if log["fsuid"] == log["ouid"] && log["OUID"] != "root" {
|
|
||||||
owner = true
|
|
||||||
}
|
|
||||||
return &File{
|
return &File{
|
||||||
Qualifier: NewQualifier(owner, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Path: log["name"],
|
Path: log["name"],
|
||||||
Access: maskToAccess[log["requested_mask"]],
|
Access: maskToAccess[log["requested_mask"]],
|
||||||
Target: log["target"],
|
Target: log["target"],
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ type Mount struct {
|
||||||
MountPoint string
|
MountPoint string
|
||||||
}
|
}
|
||||||
|
|
||||||
func MountFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func MountFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Mount{
|
return &Mount{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
MountConditions: MountConditions{
|
MountConditions: MountConditions{
|
||||||
Fs: "",
|
Fs: "",
|
||||||
Op: "",
|
Op: "",
|
||||||
|
|
@ -79,9 +79,9 @@ type Umount struct {
|
||||||
MountPoint string
|
MountPoint string
|
||||||
}
|
}
|
||||||
|
|
||||||
func UmountFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func UmountFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Umount{
|
return &Umount{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
MountConditions: MountConditions{
|
MountConditions: MountConditions{
|
||||||
Fs: "",
|
Fs: "",
|
||||||
Op: "",
|
Op: "",
|
||||||
|
|
@ -116,9 +116,9 @@ type Remount struct {
|
||||||
MountPoint string
|
MountPoint string
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemountFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func RemountFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Remount{
|
return &Remount{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
MountConditions: MountConditions{
|
MountConditions: MountConditions{
|
||||||
Fs: "",
|
Fs: "",
|
||||||
Op: "",
|
Op: "",
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ type Mqueue struct {
|
||||||
Label string
|
Label string
|
||||||
}
|
}
|
||||||
|
|
||||||
func MqueueFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func MqueueFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Mqueue{
|
return &Mqueue{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Access: maskToAccess[log["requested_mask"]],
|
Access: maskToAccess[log["requested_mask"]],
|
||||||
Type: log["type"],
|
Type: log["type"],
|
||||||
Label: log["label"],
|
Label: log["label"],
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ type Network struct {
|
||||||
AddressExpr
|
AddressExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NetworkFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func NetworkFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Network{
|
return &Network{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
AddressExpr: AddressExpr{
|
AddressExpr: AddressExpr{
|
||||||
Source: log["laddr"],
|
Source: log["laddr"],
|
||||||
Destination: log["faddr"],
|
Destination: log["faddr"],
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ type PivotRoot struct {
|
||||||
TargetProfile string
|
TargetProfile string
|
||||||
}
|
}
|
||||||
|
|
||||||
func PivotRootFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func PivotRootFromLog(log map[string]string) ApparmorRule {
|
||||||
return &PivotRoot{
|
return &PivotRoot{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
OldRoot: log["oldroot"],
|
OldRoot: log["oldroot"],
|
||||||
NewRoot: log["root"],
|
NewRoot: log["root"],
|
||||||
TargetProfile: log["name"],
|
TargetProfile: log["name"],
|
||||||
|
|
|
||||||
|
|
@ -66,15 +66,7 @@ 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) {
|
||||||
noNewPrivs := false
|
|
||||||
fileInherit := false
|
|
||||||
if log["operation"] == "file_inherit" {
|
|
||||||
fileInherit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch log["error"] {
|
switch log["error"] {
|
||||||
case "-1":
|
|
||||||
noNewPrivs = true
|
|
||||||
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")
|
||||||
|
|
@ -90,36 +82,36 @@ func (p *AppArmorProfile) AddRule(log map[string]string) {
|
||||||
|
|
||||||
switch log["class"] {
|
switch log["class"] {
|
||||||
case "cap":
|
case "cap":
|
||||||
p.Rules = append(p.Rules, CapabilityFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, CapabilityFromLog(log))
|
||||||
case "net":
|
case "net":
|
||||||
p.Rules = append(p.Rules, NetworkFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, NetworkFromLog(log))
|
||||||
case "mount":
|
case "mount":
|
||||||
p.Rules = append(p.Rules, MountFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, MountFromLog(log))
|
||||||
case "remount":
|
case "remount":
|
||||||
p.Rules = append(p.Rules, RemountFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, RemountFromLog(log))
|
||||||
case "umount":
|
case "umount":
|
||||||
p.Rules = append(p.Rules, UmountFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, UmountFromLog(log))
|
||||||
case "pivot_root":
|
case "pivot_root":
|
||||||
p.Rules = append(p.Rules, PivotRootFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, PivotRootFromLog(log))
|
||||||
case "change_profile":
|
case "change_profile":
|
||||||
p.Rules = append(p.Rules, RemountFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, RemountFromLog(log))
|
||||||
case "mqueue":
|
case "mqueue":
|
||||||
p.Rules = append(p.Rules, MqueueFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, MqueueFromLog(log))
|
||||||
case "signal":
|
case "signal":
|
||||||
p.Rules = append(p.Rules, SignalFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, SignalFromLog(log))
|
||||||
case "ptrace":
|
case "ptrace":
|
||||||
p.Rules = append(p.Rules, PtraceFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, PtraceFromLog(log))
|
||||||
case "namespace":
|
case "namespace":
|
||||||
p.Rules = append(p.Rules, UsernsFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, UsernsFromLog(log))
|
||||||
case "unix":
|
case "unix":
|
||||||
p.Rules = append(p.Rules, UnixFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, UnixFromLog(log))
|
||||||
case "file":
|
case "file":
|
||||||
p.Rules = append(p.Rules, FileFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, FileFromLog(log))
|
||||||
default:
|
default:
|
||||||
if strings.Contains(log["operation"], "dbus") {
|
if strings.Contains(log["operation"], "dbus") {
|
||||||
p.Rules = append(p.Rules, DbusFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, DbusFromLog(log))
|
||||||
} else if log["family"] == "unix" {
|
} else if log["family"] == "unix" {
|
||||||
p.Rules = append(p.Rules, UnixFromLog(log, noNewPrivs, fileInherit))
|
p.Rules = append(p.Rules, UnixFromLog(log))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ type Ptrace struct {
|
||||||
Peer string
|
Peer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtraceFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func PtraceFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Ptrace{
|
return &Ptrace{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Access: maskToAccess[log["requested_mask"]],
|
Access: maskToAccess[log["requested_mask"]],
|
||||||
Peer: log["peer"],
|
Peer: log["peer"],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,24 @@ type Qualifier struct {
|
||||||
FileInherit bool
|
FileInherit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewQualifier(owner, noNewPrivs, fileInherit bool) Qualifier {
|
func NewQualifierFromLog(log map[string]string) Qualifier {
|
||||||
|
owner := false
|
||||||
|
fsuid, hasFsUID := log["fsuid"]
|
||||||
|
ouid, hasOuUID := log["ouid"]
|
||||||
|
OUID, hasOUID := log["OUID"]
|
||||||
|
isDbus := strings.Contains(log["operation"], "dbus")
|
||||||
|
if hasFsUID && hasOuUID && hasOUID && fsuid == ouid && OUID != "root" && !isDbus {
|
||||||
|
owner = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInherit := false
|
||||||
|
if log["operation"] == "file_inherit" {
|
||||||
|
fileInherit = true
|
||||||
|
}
|
||||||
|
noNewPrivs := false
|
||||||
|
if log["error"] == "-1" {
|
||||||
|
noNewPrivs = true
|
||||||
|
}
|
||||||
return Qualifier{
|
return Qualifier{
|
||||||
Audit: false,
|
Audit: false,
|
||||||
AccessType: "",
|
AccessType: "",
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import (
|
||||||
func TestRule_FromLog(t *testing.T) {
|
func TestRule_FromLog(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fromLog func(map[string]string, bool, bool) ApparmorRule
|
fromLog func(map[string]string) ApparmorRule
|
||||||
log map[string]string
|
log map[string]string
|
||||||
want ApparmorRule
|
want ApparmorRule
|
||||||
}{
|
}{
|
||||||
|
|
@ -73,7 +73,7 @@ func TestRule_FromLog(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := tt.fromLog(tt.log, false, false); !reflect.DeepEqual(got, tt.want) {
|
if got := tt.fromLog(tt.log); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("RuleFromLog() = %v, want %v", got, tt.want)
|
t.Errorf("RuleFromLog() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ type Signal struct {
|
||||||
Peer string
|
Peer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SignalFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func SignalFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Signal{
|
return &Signal{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Access: maskToAccess[log["requested_mask"]],
|
Access: maskToAccess[log["requested_mask"]],
|
||||||
Set: log["signal"],
|
Set: log["signal"],
|
||||||
Peer: log["peer"],
|
Peer: log["peer"],
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@ type Unix struct {
|
||||||
PeerAddr string
|
PeerAddr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnixFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func UnixFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Unix{
|
return &Unix{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Access: maskToAccess[log["requested_mask"]],
|
Access: maskToAccess[log["requested_mask"]],
|
||||||
Type: log["sock_type"],
|
Type: log["sock_type"],
|
||||||
Protocol: log["protocol"],
|
Protocol: log["protocol"],
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ type Userns struct {
|
||||||
Create bool
|
Create bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func UsernsFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule {
|
func UsernsFromLog(log map[string]string) ApparmorRule {
|
||||||
return &Userns{
|
return &Userns{
|
||||||
Qualifier: NewQualifier(false, noNewPrivs, fileInherit),
|
Qualifier: NewQualifierFromLog(log),
|
||||||
Create: true,
|
Create: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue