mirror of
https://github.com/roddhjav/apparmor.d.git
synced 2024-11-14 23:43:56 +01:00
Rewrite aa-log.
This commit is contained in:
parent
2cc4d69e9e
commit
ac2386957b
@ -1,5 +1,8 @@
|
||||
---
|
||||
|
||||
include:
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
PKGDEST: $CI_PROJECT_DIR/packages
|
||||
PACKAGER: 'Alexandre Pujol <alexandre@pujol.io>'
|
||||
@ -21,6 +24,28 @@ bash:
|
||||
PKGBUILD
|
||||
debian/apparmor.d.postinst debian/apparmor.d.postrm
|
||||
|
||||
golangci-lint:
|
||||
stage: lint
|
||||
image: golangci/golangci-lint
|
||||
script:
|
||||
- cd src && golangci-lint run
|
||||
|
||||
goreport:
|
||||
stage: lint
|
||||
image: golang
|
||||
before_script:
|
||||
- cd /tmp
|
||||
- git clone https://github.com/gojp/goreportcard.git
|
||||
- cd goreportcard
|
||||
- make install
|
||||
- go install ./cmd/goreportcard-cli
|
||||
- cd $CI_PROJECT_DIR
|
||||
script:
|
||||
- goreportcard-cli -v -t 90
|
||||
|
||||
sast:
|
||||
stage: lint
|
||||
|
||||
|
||||
# Package Build
|
||||
# -------------
|
||||
|
17
PKGBUILD
17
PKGBUILD
@ -5,10 +5,11 @@ pkgname=apparmor.d
|
||||
pkgver=0.001
|
||||
pkgrel=1
|
||||
pkgdesc="Full set of apparmor profiles"
|
||||
arch=("any")
|
||||
arch=("x86_64")
|
||||
url="https://github.com/roddhjav/$pkgname"
|
||||
license=('GPL2')
|
||||
depends=('apparmor')
|
||||
makedepends=('go' 'git')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/$pkgname"
|
||||
@ -22,6 +23,16 @@ prepare() {
|
||||
./configure --distribution=archlinux
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/$pkgname/src"
|
||||
export CGO_CPPFLAGS="${CPPFLAGS}"
|
||||
export CGO_CFLAGS="${CFLAGS}"
|
||||
export CGO_CXXFLAGS="${CXXFLAGS}"
|
||||
export CGO_LDFLAGS="${LDFLAGS}"
|
||||
export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
|
||||
go build -o ../.build/ ./cmd/aa-log
|
||||
}
|
||||
|
||||
package() {
|
||||
local _build='.build/apparmor.d'
|
||||
cd "$srcdir/$pkgname"
|
||||
@ -45,6 +56,6 @@ package() {
|
||||
"$pkgdir/usr/lib/systemd/system/$service.d/apparmor.conf"
|
||||
done
|
||||
|
||||
# Set special access rights
|
||||
chmod 0755 "$pkgdir"/usr/bin/*
|
||||
# Internal tool
|
||||
install -Dm755 .build/aa-log "$pkgdir"/usr/bin/aa-log
|
||||
}
|
||||
|
@ -12,19 +12,9 @@ profile aa-log @{exec_path} {
|
||||
|
||||
@{exec_path} mr,
|
||||
|
||||
/{usr/,}bin/{,ba,da}sh rix,
|
||||
/{usr/,}bin/awk rix,
|
||||
/{usr/,}bin/env rix,
|
||||
/{usr/,}bin/gawk rix,
|
||||
/{usr/,}bin/grep rix,
|
||||
/{usr/,}bin/mawk rix,
|
||||
/{usr/,}bin/sed rix,
|
||||
|
||||
/usr/share/terminfo/x/xterm-256color r,
|
||||
|
||||
/var/log/audit/audit.log r,
|
||||
|
||||
/dev/tty rw,
|
||||
@{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size r,
|
||||
|
||||
include if exists <local/aa-log>
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Review AppArmor generated messages
|
||||
# Copyright (C) 2021 Alexandre Pujol <alexandre@pujol.io>
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
readonly LOGFILE=/var/log/audit/audit.log
|
||||
|
||||
# Parses AppArmor logs to hide unnecessary information and remove duplicates.
|
||||
_apparmor_log() {
|
||||
local state="$1" profile="$2"
|
||||
grep -a "$state" "$LOGFILE" \
|
||||
| grep "profile=\"$profile.*\"" \
|
||||
| sed -e 's/AVC //' \
|
||||
-e "s/apparmor=\"$state\"/$state/" \
|
||||
-e 's/type=msg=audit(.*): //' \
|
||||
-e 's/pid=.* comm/comm/' \
|
||||
-e 's/ fsuid.*//' \
|
||||
| awk '!x[$0]++'
|
||||
|
||||
}
|
||||
|
||||
_apparmor_log DENIED "$@"
|
||||
_apparmor_log ALLOWED "$@"
|
143
src/cmd/aa-log/main.go
Normal file
143
src/cmd/aa-log/main.go
Normal file
@ -0,0 +1,143 @@
|
||||
// aa-log - Review AppArmor generated messages
|
||||
// Copyright (C) 2021 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LogFile is the path to the file to query
|
||||
const LogFile = "/var/log/audit/audit.log"
|
||||
|
||||
// Colors
|
||||
const (
|
||||
Reset = "\033[0m"
|
||||
FgYellow = "\033[33m"
|
||||
FgBlue = "\033[34m"
|
||||
FgMagenta = "\033[35m"
|
||||
BoldRed = "\033[1;31m"
|
||||
BoldGreen = "\033[1;32m"
|
||||
)
|
||||
|
||||
// AppArmorLog describes a apparmor log entry
|
||||
type AppArmorLog struct {
|
||||
State string
|
||||
Profile string
|
||||
Operation string
|
||||
Name string
|
||||
Content string
|
||||
}
|
||||
|
||||
func removeDuplicateLog(logs []string) []string {
|
||||
list := []string{}
|
||||
keys := make(map[string]interface{})
|
||||
keys[""] = true
|
||||
for _, log := range logs {
|
||||
if _, v := keys[log]; !v {
|
||||
keys[log] = true
|
||||
list = append(list, log)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func parseApparmorLogs(file *os.File, profile string) []AppArmorLog {
|
||||
log := ""
|
||||
exp := fmt.Sprintf("^.*apparmor=(\"DENIED\"|\"ALLOWED\").* profile=\"%s.*\".*$", profile)
|
||||
isAppArmorLog := regexp.MustCompile(exp)
|
||||
|
||||
// Select Apparmor logs
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if isAppArmorLog.MatchString(line) {
|
||||
log += line + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Clean logs
|
||||
cleanAppArmorLogs := []*regexp.Regexp{
|
||||
regexp.MustCompile(`type=AVC msg=audit(.*): `),
|
||||
regexp.MustCompile(` fsuid.*`),
|
||||
}
|
||||
for _, clean := range cleanAppArmorLogs {
|
||||
log = clean.ReplaceAllLiteralString(log, "")
|
||||
}
|
||||
replaceAppArmorLogs := regexp.MustCompile(`pid=.* comm`)
|
||||
log = replaceAppArmorLogs.ReplaceAllLiteralString(log, "comm")
|
||||
|
||||
// Remove doublon in logs
|
||||
logs := strings.Split(log, "\n")
|
||||
logs = removeDuplicateLog(logs)
|
||||
|
||||
// Parse log into ApparmorLog struct
|
||||
aaLogs := make([]AppArmorLog, 0)
|
||||
getState := regexp.MustCompile(`apparmor=\"([A-Z]*)\"`)
|
||||
getProfile := regexp.MustCompile(`profile=\"([A-Za-z0-9_.\-/]*)\" `)
|
||||
getOperation := regexp.MustCompile(`operation="(\w+)"`)
|
||||
getName := regexp.MustCompile(` name=([A-Za-z0-9_.\-/#"]*)`)
|
||||
cleanContent := []*regexp.Regexp{getState, getProfile, getOperation, getName}
|
||||
for _, log := range logs {
|
||||
name := ""
|
||||
names := getName.FindStringSubmatch(log)
|
||||
if len(names) >= 2 {
|
||||
name = strings.Trim(names[1], `"`)
|
||||
}
|
||||
|
||||
content := log
|
||||
for _, clean := range cleanContent {
|
||||
content = clean.ReplaceAllLiteralString(content, "")
|
||||
}
|
||||
aaLogs = append(aaLogs,
|
||||
AppArmorLog{
|
||||
State: getState.FindStringSubmatch(log)[1],
|
||||
Profile: getProfile.FindStringSubmatch(log)[1],
|
||||
Operation: getOperation.FindStringSubmatch(log)[1],
|
||||
Name: name,
|
||||
Content: content[2:],
|
||||
})
|
||||
}
|
||||
|
||||
return aaLogs
|
||||
}
|
||||
|
||||
func printFormatedApparmorLogs(aaLogs []AppArmorLog) {
|
||||
state := map[string]string{
|
||||
"DENIED": BoldRed + "DENIED " + Reset,
|
||||
"ALLOWED": BoldGreen + "ALLOWED" + Reset,
|
||||
}
|
||||
for _, log := range aaLogs {
|
||||
fmt.Println(state[log.State],
|
||||
FgBlue+log.Profile,
|
||||
FgYellow+log.Operation,
|
||||
FgMagenta+log.Name+Reset,
|
||||
log.Content)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
profile := ""
|
||||
if len(os.Args) >= 2 {
|
||||
profile = os.Args[1]
|
||||
}
|
||||
|
||||
file, err := os.Open(LogFile)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
fmt.Println("Error closing file:", err)
|
||||
}
|
||||
}()
|
||||
|
||||
aaLogs := parseApparmorLogs(file, profile)
|
||||
printFormatedApparmorLogs(aaLogs)
|
||||
}
|
3
src/go.mod
Normal file
3
src/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module gitlab.com/roddhjav/apparmor.d
|
||||
|
||||
go 1.17
|
0
src/go.sum
Normal file
0
src/go.sum
Normal file
Loading…
Reference in New Issue
Block a user