Giter Club home page Giter Club logo

libaudit-go's Introduction

libaudit in Go

libaudit-go is a go package for interfacing with Linux audit.

Build Status Go Report Card

libaudit-go is a pure Go client library for interfacing with the Linux auditing framework. It provides functions to interact with the auditing subsystems over Netlink, including controlling the rule set and obtaining/interpreting incoming audit events.

libaudit-go can be used to build go applications which perform tasks similar to the standard Linux auditing daemon auditd.

To get started see package documentation at godoc.

For a simple example of usage, see the auditprint tool included in this repository.

sudo service stop auditd
go get -u github.com/mozilla/libaudit-go
cd $GOPATH/src/github.com/mozilla/libaudit-go
go install github.com/mozilla/libaudit-go/auditprint
sudo $GOPATH/bin/auditprint testdata/rules.json

Some key functions are discussed in the overview section below.

Overview

General

NewNetlinkConnection

To use libaudit-go programs will need to initialize a new Netlink connection. NewNetlinkConnection can be used to allocate a new NetlinkConnection type which can then be passed to other functions in the library.

s, err := libaudit.NewNetlinkConnection()
if err != nil {
        fmt.Printf("NewNetlinkConnection: %v\n", err)
} 
defer s.Close()

NetlinkConnection provides a Send and Receive method to send and receive Netlink messages to the kernel, however generally applications will use the various other functions included in libaudit-go and do not need to call these functions directly.

GetAuditEvents

GetAuditEvents starts an audit event monitor in a go-routine and returns. Programs can call this function and specify a callback function as an argument. When the audit event monitor receives a new event, this callback function will be called with the parsed AuditEvent as an argument.

func myCallback(msg *libaudit.AuditEvent, err error) {
        if err != nil {
            // An error occurred getting or parsing the audit event
            return
        }
	// Print the fields
        fmt.Println(msg.Data)
	// Print the raw event
        fmt.Println(msg.Raw)
}

libaudit.GetAuditEvents(s, myCallback)
GetRawAuditEvents

GetRawAuditEvents behaves in a similar manner to GetAuditEvents, however programs can use this function to instead just retrieve raw audit events from the kernel as a string, instead of having libaudit-go parse these audit events into an AuditEvent type.

Audit Rules

Audit rules can be loaded into the kernel using libaudit-go, however the format differs from the common rule set used by userspace tools such as auditctl/auditd.

libaudit-go rulesets are defined as a JSON document. See rules.json as an example. The libaudit-go type which stores the rule set is AuditRules.

SetRules

SetRules can be used to load an audit rule set into the kernel. The function takes a marshalled AuditRules type as an argument (slice of bytes), and converts the JSON based rule set into a set of audit rules suitable for submission to the kernel.

The function then makes the required Netlink calls to clear the existing rule set and load the new rules.

// Load all rules from a file
content, err := ioutil.ReadFile("audit.rules.json")
if err != nil {
        fmt.Printf("error: %v\n", err)
	os.Exit(1)
}

// Set audit rules
err = libaudit.SetRules(s, content)
if err != nil {
        fmt.Printf("error: %v\n", err)
        os.Exit(1)
}

libaudit-go's People

Contributors

aalekh avatar arunk-s avatar hardikj avatar hxjuneja avatar jvehent avatar lzakharov avatar mozilla-github-standards avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libaudit-go's Issues

Libaudit test uses auditctl for verifying test results

Currently libaudit_tests.go uses ouput of auditctl command to check if libaudit functions worked correctly. This behaviour should be changed so that we don't rely on auditctl and our tests should not break if auditctl changes its output behaviour or even auditctl is absent on the client's machine.

has anybody run this recently?

Cannot make it work, and the tests don't pass.
The auditisenabled always fails with unexpected EOF.
I added some printf to see what's in there, the binary.Read should only give that unexpected eof if what it's reading is empty.

I'm on centos7 minimal, but it doesn't seem to run on almost any linux 7, I'm about to test a cantos 6.x machine.

[root@localhost libaudit-go]# go test
mHeaderType 1000
m [0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 244 1 0 0 244 1 0 0 134 0 0 0 0 0 0 0 5 0 0 0]
--- FAIL: TestSetters (0.00s)
libaudit_test.go:192: AuditIsEnabled failed unexpected EOF
libaudit_test.go:195: AuditIsEnabled returned false
FAIL
exit status 1
FAIL _/media/psf/code/libaudit-go 0.005s

If I run it without the prints, same result. Just in case you're thinking I'm draining a buffer or something.

[root@localhost libaudit-go]# go test
--- FAIL: TestSetters (0.00s)
libaudit_test.go:192: AuditIsEnabled failed unexpected EOF
libaudit_test.go:195: AuditIsEnabled returned false
FAIL
exit status 1
FAIL _/media/psf/code/libaudit-go 0.007s

// fmt.Println("mHeaderType",m.Header.Type)
// fmt.Println("m",m.Data)

// Convert the response to auditStatus
buf := bytes.NewBuffer(m.Data)
err = binary.Read(buf, nativeEndian(), &status)
if err != nil {
	return false, err
}
if status.Enabled == 1 {
	return true, nil
}
return false, nil

}

Question regarding auditRuleData

Hi,

I'm working on a Rust audit implementation, and I'm looking at existing implementations, since I could not find much documentation online.

One question I had is: what is the point of the Buflen field in the auditRuleData struct?

type auditRuleData struct {
	Flags      uint32                     `struc:"uint32,little"` // AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND
	Action     uint32                     `struc:"uint32,little"` // AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS
	FieldCount uint32                     `struc:"uint32,little"`
	Mask       [AUDIT_BITMASK_SIZE]uint32 `struc:"[64]uint32,little"` // syscall(s) affected
	Fields     [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Values     [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Fieldflags [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Buflen     uint32                     `struc:"uint32,little,sizeof=Buf"` // total length of string fields
	Buf        []byte                     `struc:"[]byte,little"`            // string fields buffer
}

For field with string values, it seems that the string length is already encoded in the Values field.

Here is an example (from rules.go#L441-L443):

			rule.Values[rule.FieldCount] = (uint32)(vlen)
			rule.Buflen = rule.Buflen + (uint32)(vlen)
			rule.Buf = append(rule.Buf, valbyte[:]...)

Also, is it possible to have multiple string fields in the same rule? If so, Buflen will only contain the length for the last value.

Thanks for making libaudit-go, it's the only non-C project with readable code and reasonable coverage of the protocol I could find and it's of great help :)

Panic at first run

While running the example code from gsoc16, the program first panicked, the worked correctly the second time I ran it.

# ./main 
{"class":"log","parameters":"audit is enabled"}
{"class":"log","parameters":{"stack":[5447707,4758930,4756548,4559457]}}
panic: AuditSetPID failed: auditGetReply failed: error while parsing NetlinkMessage: Nlmsghdr header length unexpected 1936028448, actual packet length 16

goroutine 5 [running]:
panic(0x6bee60, 0xc420133bf0)
    /usr/lib/go/src/runtime/panic.go:500 +0x1a1
mig.ninja/mig/modules/audit.(*run).runAudit(0xc42007a280, 0xc42000d190, 0xc420026078, 0xc420026080, 0x815580, 0xc420133bf0)
    /tmp/gsoc16/vendor/src/mig.ninja/mig/modules/audit/audit.go:251 +0x415
created by mig.ninja/mig/modules/audit.(*run).Run
    /tmp/gsoc16/vendor/src/mig.ninja/mig/modules/audit/audit.go:144 +0x1f7

Misc / review

(error handling) If err != 0 continue? the double statement seems not necessary
The follow-up "continue" might need to return error conditions to the caller though (instead of https://github.com/mozilla/libaudit-go/blob/master/audit_events.go#L51)

The maps should probably be in a separate file for maintainability. Maybe put all this + syscall name in a separate directory such as "go-kernel-headers" so that it's clean-enough

kernel panic under virtual machine

Issue

stop auditprint and kernel got panic

~/go/src/github.com/mozilla/libaudit-go# $GOPATH/bin/aud itprint testdata/rules.json

kernel logs

[  173.399485] audit: netlink_unicast sending to audit_pid=5074 returned error: -111
[  173.401834] Kernel panic - not syncing: audit: audit_pid=5074 reset
[  173.401834] 
[  173.403537] CPU: 2 PID: 936 Comm: kauditd Not tainted 4.4.0-75-generic #96~14.04.1-Ubuntu
[  173.405335] Hardware name: OpenStack Foundation OpenStack Nova, BIOS Ubuntu-1.8.2-1ubuntu1~cloud0 04/01/2014
[  173.405789]  0000000000000000 ffff880234c17d68 ffffffff813dce3c ffffffff81ccf361
[  173.405789]  ffff8800babaf0e4 ffff880234c17de0 ffffffff81182e9c 0000000000000010
[  173.405789]  ffff880234c17df0 ffff880234c17d90 ffff880234c17da0 ffff880234c17e28
[  173.405789] Call Trace:
[  173.405789]  [] dump_stack+0x63/0x87
[  173.405789]  [] panic+0xc8/0x20f
[  173.405789]  [] audit_panic+0x5e/0x60
[  173.405789]  [] audit_log_lost+0x3f/0xc0
[  173.405789]  [] kauditd_send_skb+0x122/0x150
[  173.405789]  [] ? audit_printk_skb+0x70/0x70
[  173.405789]  [] kauditd_thread+0x78/0x190
[  173.405789]  [] ? prepare_to_wait_event+0xf0/0xf0
[  173.405789]  [] kthread+0xc9/0xe0
[  173.405789]  [] ? kthread_park+0x60/0x60
[  173.405789]  [] ret_from_fork+0x3f/0x70
[  173.405789]  [] ? kthread_park+0x60/0x60
[  173.405789] Kernel Offset: disabled
[  173.405789] ---[ end Kernel panic - not syncing: audit: audit_pid=5074 reset

Env

go version: go version go1.7 linux/amd64

OS
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"

dpkg -l | grep audit
ii auditd 1:2.3.2-2ubuntu1 amd64 User space tools for security auditing
ii libaudit-common 1:2.3.2-2ubuntu1 all Dynamic library for security auditing - common files
ii libaudit1:amd64 1:2.3.2-2ubuntu1 amd64 Dynamic library for security auditing
ii libauparse0:amd64 1:2.3.2-2ubuntu1 amd64 Dynamic library for parsing security auditing

AuditSetPID fails when auditd is running on the system

When auditd is already running on the system, calls to AuditSetPID will end up failing, and do not provide any indication of what the issue is aside from an errno integer. Not sure if there is a better way to handle this, or perhaps convert the incoming errno value into something more indicative of what the problem is.

Add travisci support

For running go test xxx in particular
Would be also ok to have a makefile that allows for "make test" which travisci would just call

Use Godoc for documentation

http://godoc.org/golang.org/x/tools/cmd/godoc
https://godoc.org/

Good doc is quite important for a package/library. Currently the readme.md doc is nice, but doc-from-code is nicer and always more accurate. I would change the readme to only give the high level guidance and how to get started then point to godoc (it can be local, not necessarily on godoc.org, or in both places even) so that doc is always correct.

If using a makefile, a target to generate the doc would also be good, see issue #12 that is related

i386 compilation errors

Hello!

I'm trying to use libaudit-go on i386, but it fails with the following errors:

vendor/github.com/mozilla/libaudit-go/headers/cloneflag_tab.go:27:2: constant 2147483648 overflows int
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go:35:2: constant 2147767344 overflows int
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go:36:2: constant 2147767345 overflows int
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go:37:2: constant 3223086243 overflows int
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go:38:2: constant 3222824112 overflows int
vendor/github.com/mozilla/libaudit-go/headers/ioctlreq_tab.go:39:2: constant 3222824113 overflows int
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:15:5: undefined: syscall.SYS_SEMOP
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:16:2: undefined: syscall.SYS_SEMGET
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:17:2: undefined: syscall.SYS_SEMCTL
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:19:2: undefined: syscall.SYS_MSGSND
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:20:2: undefined: syscall.SYS_MSGRCV
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:21:2: undefined: syscall.SYS_MSGGET
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:22:2: undefined: syscall.SYS_MSGCTL
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:23:2: undefined: syscall.SYS_SHMAT
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:24:2: undefined: syscall.SYS_SHMDT
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:25:2: undefined: syscall.SYS_SHMGET
vendor/github.com/mozilla/libaudit-go/headers/ipc_tab.go:25:2: too many errors

Sample test:

package main
Linux debian 4.19.0-6-686-pae #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) i686 GNU/Linux
import (
    "fmt"
    "github.com/mozilla/libaudit-go"
)

func main(){
    fmt.Println("Hello")
}

This is a Debian/GNU Linux buster (up to date)
go version go1.11.6 linux/386
Linux debian 4.19.0-6-686-pae #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) i686 GNU/Linux

I can somehow workaround the overflows error by changing int to int64, but no idea how to solve the undefined errors. Can anyone help me?

FileWatch Output is Null

I have this rule: -w /home/sunshine/Documents/files -p rwxa -k file .
When I ran "sudo go run main.go audit.rules", audit events were shown except for file watches. I always get this output. Type:EOF Info: {}. The info is always null.

run the auditprint but cannot get anything output

hi,i was run the auditprint success but i cant get anythig output,my intent is use this lib to dispatch audit log to other server and analysis,can i to do this ?

environment:

go version: go1.12.9 linux/amd64
os: Ubuntu 16.04_X86_64

ps: I not install the auditd client,see this #21

The func Receive in libaudit.go costs too much performance

The func Receive in libaudit.go make a new buf every time to receive the netlink message, dose it cost too much performance? And it is easy to trigger the GC mechanism, leading to CPU fluctuations. Is it more appropriate to use a global buffer? Is it safe to do this?

can it run when auditd run ?

hello, i want to monitor who access this file "/etc/passwd"
when system "auditd" is running, "auditprint" cannot run,

I don't want to stop auditd daemon, because our clients donot allow us to do.
the ausearch cmd can audit logs, but it is not event-notify fashon.

so, is there any way to run auditprint when auditd is running ?

Add support for all Message Types in Getreply endpoint

basically eliminate-

2015/11/20 15:34:23 Unknown: 1327
2015/11/20 15:35:11 Unknown: 1326
2015/11/20 15:35:53 Unknown: 1326
2015/11/20 15:36:18 Unknown: 1326
2015/11/20 15:36:23 Unknown: 1326
2015/11/20 15:36:23 Unknown: 1326
2015/11/20 15:36:29 Unknown: 1326

Documentation improvements

See issue #13 before starting on this issue

Stray code (cleanup/remove/fix or add comment):

libaudit-go requires root to run go tests

Right now go test fails unless the test is run as root, and netlink is available

--- FAIL: TestNetlinkConnection (0.00s)
libaudit_test.go:43: NewNetlinkConnection failed not root user, exiting
panic: runtime error: invalid memory address or nil pointer dereference
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x493db8]

It would be good if the tests could run as a regular user, potentially using an emulated netlink socket or something with a consistent event feed

Replace log package for warnings/errors to be redirected to stderr

We are using log package for notifying of both logs and errors which is not desirable.
A suitable package/way should exist to separate them and direct them to stdout or stderr

As suggested by @HardikJ :

Also for string like "Acknowledged!!" and "NLMSG ERROR", I would recommend to implement a
debug flag and print them in debug flag only.

The data of NetlinkMessage message is truncated

I'm not sure whether it's kernel's BUG or libaudit-go's BUG。

The following is the definition of nlmsghdr, nlmsg_len is the length of message including header

struct nlmsghdr {
    __u32       nlmsg_len;  /* Length of message including header */                                                                                          
    ......                                                                                                  
};

But in kernel, the nlmsg_len is the length of message, excluding header

struct sk_buff *audit_make_reply(__u32 portid, int seq, int type, int done,
				 int multi, const void *payload, int size)
{
    ......
    nlh	= nlmsg_put(skb, portid, seq, t, size, flags);
    ......
}

So, if we do as the following steps in libaudit-go, the data of NetlinkMessage message will be truncated

func parseAuditNetlinkMessage(b []byte) (ret []NetlinkMessage, err error) {                                                                                   
    ......
    datalen := m.Header.Len - syscall.NLMSG_HDRLEN 
    ......
}

In fact I think it's the BUG of kernel,

auditprint.go: Block at Receive when calling the DeleteAllRules

I'm trying to run auditprint.go on a ubuntu16.04 machine. After I ran the program, there is no output. After some print statement, I found that the program will be blocked after calling the DeleteAllRules in the main function. I followed the call hierarchy and the program is actually get block at the Receive function that get called in the auditGetReply:

if m.Header.Type == syscall.NLMSG_ERROR {
	e := int32(hostEndian.Uint32(m.Data[0:4]))
	if e == 0 {
		// ACK response from the kernel; if chkAck is true
		// we just return as there is nothing left to do
		if chkAck {
			break done
		}
		// Otherwise, keep going so we can get the response
		// we want
		continue
	} else {
		return ret, fmt.Errorf("error while recieving reply %v", e)
	}
}

After receiving the first message, the program enter this loop and since the chkAck is set to false, the program continue to the next loop and get block at the receive call.

I'm trying to get this working, but don't have any clue.

Do not panic on rule load failure

Eg:

panic: SetRules failed: auditSetupAndAddWatchDir failed: file at /etc/systemd does not exist

Instead this should be a warning. The reason for that is the same reason audit does not necessarily fails (depending on settings). It allows for ensuring the daemon starts even if your configuration differs.

It would also be ok to make the skip optional

Socket Connection

I am using libaudit library and my program runs in ubuntu. Can libaudit creates the netlink connection in CentOS(guest os) running on vbox instead in ubuntu(host os)?

CODE_OF_CONDUCT.md file missing

As of January 1 2019, Mozilla requires that all GitHub projects include this CODE_OF_CONDUCT.md file in the project root. The file has two parts:

  1. Required Text - All text under the headings Community Participation Guidelines and How to Report, are required, and should not be altered.
  2. Optional Text - The Project Specific Etiquette heading provides a space to speak more specifically about ways people can work effectively and inclusively together. Some examples of those can be found on the Firefox Debugger project, and Common Voice. (The optional part is commented out in the raw template file, and will not be visible until you modify and uncomment that part.)

If you have any questions about this file, or Code of Conduct policies and procedures, please see Mozilla-GitHub-Standards or email [email protected].

(Message COC001)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.