Skip to content

Commit

Permalink
Add SetImmutable to audit client
Browse files Browse the repository at this point in the history
SetImmutable is used to lock the audit configuration so that it can't be
changed. Locking the configuration is intended to be the last command you
issue. Any attempt to change the configuration in this mode will be
audited and denied. The configuration can only be changed by rebooting the
machine.

Closes #55
  • Loading branch information
andrewkroh committed Jun 18, 2020
1 parent 92371be commit ba0bbab
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added support for big endian. #48
- Added semantic versioning support via go modules. #61
- Add ECS categorization support for events by record type and syscall. #62
- Added `SetImmutable` to the audit client for marking the audit settings
as immutable within the kernel. #55 #68

### Removed

Expand Down
15 changes: 14 additions & 1 deletion audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,19 @@ func (c *AuditClient) SetEnabled(enabled bool, wm WaitMode) error {
return c.set(status, wm)
}

// SetImmutable is used to lock the audit configuration so that it can't be
// changed. Locking the configuration is intended to be the last command you
// issue. Any attempt to change the configuration in this mode will be
// audited and denied. The configuration can only be changed by rebooting the
// machine.
func (c *AuditClient) SetImmutable(wm WaitMode) error {
status := AuditStatus{
Mask: AuditStatusEnabled,
Enabled: 2,
}
return c.set(status, wm)
}

// SetFailure sets the action that the kernel will perform when the backlog
// limit is reached or when it encounters an error and cannot proceed.
func (c *AuditClient) SetFailure(fm FailureMode, wm WaitMode) error {
Expand Down Expand Up @@ -587,7 +600,7 @@ var sizeofAuditStatus = int(unsafe.Sizeof(AuditStatus{}))
// https://github.com/linux-audit/audit-kernel/blob/v4.7/include/uapi/linux/audit.h#L413-L427
type AuditStatus struct {
Mask AuditStatusMask // Bit mask for valid entries.
Enabled uint32 // 1 = enabled, 0 = disabled
Enabled uint32 // 1 = enabled, 0 = disabled, 2 = immutable
Failure uint32 // Failure-to-log action.
PID uint32 // PID of auditd process.
RateLimit uint32 // Messages rate limit (per second).
Expand Down
38 changes: 36 additions & 2 deletions audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ import (
// docker run -it --rm -v `pwd`:/go/src/github.com/elastic/go-libaudit --pid=host --privileged golang:1.10.2 /bin/bash

var (
hexdump = flag.Bool("hexdump", false, "dump kernel responses to stdout in hexdump -C format")
list = flag.Bool("l", false, "dump rules")
hexdump = flag.Bool("hexdump", false, "dump kernel responses to stdout in hexdump -C format")
list = flag.Bool("l", false, "dump rules")
immutable = flag.Bool("immutable", false, "test setting kernel as immutable (requires reboot to undo)")
)

// testRule is a base64 representation of the following rule.
Expand Down Expand Up @@ -748,6 +749,39 @@ func TestAuditClientGetStatusAsync(t *testing.T) {
}
}

func TestAuditClientSetImmutable(t *testing.T) {
if os.Geteuid() != 0 {
t.Skip("must be root to enable audit")
}
if !*immutable {
t.Skip("use -immutable to test SetImmutable")
}

var dumper io.WriteCloser
if *hexdump {
dumper = hex.Dumper(os.Stdout)
defer dumper.Close()
}

c, err := NewAuditClient(dumper)
if err != nil {
t.Fatal(err)
}
defer c.Close()

err = c.SetImmutable(WaitForReply)
if err != nil {
t.Fatal(err)
}
t.Log("SetImmutable complete")

status, err := getStatus(t)
if err != nil {
t.Fatal(err)
}
assert.EqualValues(t, 2, status.Enabled)
}

func TestRuleParsing(t *testing.T) {
var rules []string
switch runtime.GOARCH {
Expand Down
8 changes: 8 additions & 0 deletions cmd/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var (
diag = fs.String("diag", "", "dump raw information from kernel to file")
rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)")
backlog = fs.Uint("backlog", 8192, "backlog limit")
immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)")
receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+")
)

Expand Down Expand Up @@ -128,6 +129,13 @@ func read() error {
}
}

if status.Enabled != 2 {
log.Debugf("setting kernel settings as immutable")
if err = client.SetImmutable(libaudit.NoWait); err != nil {
return errors.Wrap(err, "failed to set kernel as immutable")
}
}

log.Debugf("sending message to kernel registering our PID (%v) as the audit daemon", os.Getpid())
if err = client.SetPID(libaudit.NoWait); err != nil {
return errors.Wrap(err, "failed to set audit PID")
Expand Down

0 comments on commit ba0bbab

Please sign in to comment.