From 049fb55be655b8df080fe2f930ee8c1f1831cea0 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 12 Sep 2017 01:04:12 -0400 Subject: [PATCH] Support receiving events from audit multicast group (#5081) (#5138) Update to go-libaudit v0.0.6 Closes #4850 (cherry picked from commit c76f14f22b04226efa5043ec99f77ad08e57b9b7) --- CHANGELOG.asciidoc | 2 + NOTICE | 4 +- .../module/audit/kernel/_meta/docs.asciidoc | 25 +- auditbeat/module/audit/kernel/audit_linux.go | 112 +++++- .../module/audit/kernel/audit_linux_test.go | 91 ++++- auditbeat/module/audit/kernel/config.go | 12 +- .../module/audit/kernel/config_linux_test.go | 8 + metricbeat/mb/testing/modules.go | 2 +- .../elastic/go-libaudit/CHANGELOG.md | 6 + .../aucoalesce/mknormalize_data.go | 106 ------ .../github.com/elastic/go-libaudit/audit.go | 22 +- .../go-libaudit/auparse/defs_audit_arches.go | 104 ------ .../auparse/mk_audit_exit_codes.go | 226 ------------ .../go-libaudit/auparse/mk_audit_msg_types.go | 324 ------------------ .../github.com/elastic/go-libaudit/netlink.go | 6 +- vendor/vendor.json | 46 +-- 16 files changed, 283 insertions(+), 813 deletions(-) delete mode 100644 vendor/github.com/elastic/go-libaudit/aucoalesce/mknormalize_data.go delete mode 100644 vendor/github.com/elastic/go-libaudit/auparse/defs_audit_arches.go delete mode 100644 vendor/github.com/elastic/go-libaudit/auparse/mk_audit_exit_codes.go delete mode 100644 vendor/github.com/elastic/go-libaudit/auparse/mk_audit_msg_types.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 118be403cff..7c543d039cc 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -85,6 +85,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta2...master[Check the HEAD di - Changed the number of shards in the default configuration to 3. {issue}5095[5095] +- Add support for receiving audit events using a multicast socket. [issue]4850[4850] + ==== Deprecated *Affecting all Beats* diff --git a/NOTICE b/NOTICE index a8382589a06..1f34ace3597 100644 --- a/NOTICE +++ b/NOTICE @@ -314,8 +314,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- Dependency: github.com/elastic/go-libaudit -Version: v0.0.5 -Revision: 3a005d3d0bbcee26d60e3ab2f1890699746f4da6 +Version: v0.0.6 +Revision: df0d4981f3fce65ffd3d7411dfec3e03231b491c License type (autodetected): Apache License 2.0 ./vendor/github.com/elastic/go-libaudit/LICENSE: -------------------------------------------------------------------- diff --git a/auditbeat/module/audit/kernel/_meta/docs.asciidoc b/auditbeat/module/audit/kernel/_meta/docs.asciidoc index 3b4dd92283b..dce75d808f6 100644 --- a/auditbeat/module/audit/kernel/_meta/docs.asciidoc +++ b/auditbeat/module/audit/kernel/_meta/docs.asciidoc @@ -12,13 +12,6 @@ This metricset establishes a subscription to the kernel to receive the events as they occur. So unlike most other metricsets, the `period` configuration option is unused because it is not implemented using polling. -The Linux kernel only supports a single subscriber to the audit events so this -metricset cannot be used simultaneously with a service like `auditd`. `auditd` -should be disabled if this metricset is being used. If you wish to continue to -use `auditd` instead of this metricset to receive audit messages from the kernel -then consider using {filebeat}/filebeat-module-auditd.html[Filebeat] to collect -the daemon's log files. - The Linux Audit Framework can send multiple messages for a single auditable event. For example, a `rename` syscall causes the kernel to send eight separate messages. Each message describes a different aspect of the activity that is @@ -48,6 +41,24 @@ following example shows all configuration options with their default values. kernel.include_warnings: false ---- +*`kernel.socket_type`*:: This optional setting controls the type of +socket that {beatname_uc} uses to receive events from the kernel. The two +options are `unicast` and `multicast`. ++ +`unicast` should be used when {beatname_uc} is the primary userspace daemon for +receiving audit events and managing the rules. Only a single process can receive +audit events through the "unicast" connection so any other daemons should be +stopped (e.g. stop `auditd`). ++ +`multicast` can be used in kernel versions 3.16 and newer. By using `multicast` +{beatname_uc} will receive an audit event broadcast that is not exclusive to a +a single process. This is ideal for situations where `auditd` is running and +managing the rules. If `multicast` is specified, but the kernel version is less +than 3.16 {beatname_uc} will automatically revert to `unicast`. ++ +By default {beatname_uc} will use `multicast` if the kernel version is 3.16 or +newer and no rules have been defined. Otherwise `unicast` will be used. + *`kernel.resolve_ids`*:: This boolean setting enables the resolution of UIDs and GIDs to their associated names. The default value is true. diff --git a/auditbeat/module/audit/kernel/audit_linux.go b/auditbeat/module/audit/kernel/audit_linux.go index 45314fb4566..59c21de8cb3 100644 --- a/auditbeat/module/audit/kernel/audit_linux.go +++ b/auditbeat/module/audit/kernel/audit_linux.go @@ -2,7 +2,9 @@ package kernel import ( "os" + "strconv" "strings" + "syscall" "time" "github.com/pkg/errors" @@ -48,16 +50,17 @@ type MetricSet struct { // New constructs a new MetricSet. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Experimental("The %v metricset is a beta feature", metricsetName) + cfgwarn.Beta("The %v metricset is a beta feature", metricsetName) config := defaultConfig if err := base.Module().UnpackConfig(&config); err != nil { return nil, errors.Wrap(err, "failed to unpack the audit.kernel config") } - debugf("%v the metricset is running as euid=%v", logPrefix, os.Geteuid()) + _, _, kernel, _ := kernelVersion() + debugf("%v the metricset is running as euid=%v on kernel=%v", logPrefix, os.Geteuid(), kernel) - client, err := libaudit.NewAuditClient(nil) + client, err := newAuditClient(&config) if err != nil { return nil, errors.Wrap(err, "failed to create audit.kernel client") } @@ -71,6 +74,37 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { }, nil } +func newAuditClient(c *Config) (*libaudit.AuditClient, error) { + hasMulticast := hasMulticastSupport() + + switch c.SocketType { + // Attempt to determine the optimal socket_type. + case "": + // Use multicast only when no rules are present. Specifying rules + // implies you want control over the audit framework so you should be + // using unicast. + if rules, _ := c.rules(); len(rules) == 0 && hasMulticast { + c.SocketType = "multicast" + logp.Info("%v kernel.socket_type=multicast will be used.", logPrefix) + } + case "multicast": + if !hasMulticast { + logp.Warn("%v kernel.socket_type is set to multicast "+ + "but based on the kernel version multicast audit subscriptions "+ + "are not supported. unicast will be used instead.", logPrefix) + c.SocketType = "unicast" + } + } + + switch c.SocketType { + case "multicast": + return libaudit.NewMulticastAuditClient(nil) + default: + c.SocketType = "unicast" + return libaudit.NewAuditClient(nil) + } +} + // Run initializes the audit client and receives audit messages from the // kernel until the reporter's done channel is closed. func (ms *MetricSet) Run(reporter mb.PushReporter) { @@ -115,8 +149,14 @@ func (ms *MetricSet) addRules(reporter mb.PushReporter) error { return nil } + client, err := libaudit.NewAuditClient(nil) + if err != nil { + return errors.Wrap(err, "failed to create audit client for adding rules") + } + defer client.Close() + // Delete existing rules. - n, err := ms.client.DeleteRules() + n, err := client.DeleteRules() if err != nil { return errors.Wrap(err, "failed to delete existing rules") } @@ -125,7 +165,7 @@ func (ms *MetricSet) addRules(reporter mb.PushReporter) error { // Add rules from config. var failCount int for _, rule := range rules { - if err = ms.client.AddRule(rule.data); err != nil { + if err = client.AddRule(rule.data); err != nil { // Treat rule add errors as warnings and continue. err = errors.Wrapf(err, "failed to add kernel rule '%v'", rule.flags) reporter.Error(err) @@ -139,6 +179,17 @@ func (ms *MetricSet) addRules(reporter mb.PushReporter) error { } func (ms *MetricSet) initClient() error { + if ms.config.SocketType == "multicast" { + // This request will fail with EPERM if this process does not have + // CAP_AUDIT_CONTROL, but we will ignore the response. The user will be + // required to ensure that auditing is enabled if the process is only + // given CAP_AUDIT_READ. + err := ms.client.SetEnabled(true, libaudit.NoWait) + return errors.Wrap(err, "failed to enable auditing in the kernel") + } + + // Unicast client initialization (requires CAP_AUDIT_CONTROL and that the + // process be in initial PID namespace). status, err := ms.client.GetStatus() if err != nil { return errors.Wrap(err, "failed to get audit status") @@ -348,3 +399,54 @@ func (s *stream) ReassemblyComplete(msgs []*auparse.AuditMessage) { func (s *stream) EventsLost(count int) { lostMetric.Inc() } + +func hasMulticastSupport() bool { + // Check the kernel version because 3.16+ should have multicast + // support. + major, minor, _, err := kernelVersion() + if err != nil { + // Assume not supported. + return false + } + + switch { + case major > 3, + major == 3 && minor >= 16: + return true + } + + return false +} + +func kernelVersion() (major, minor int, full string, err error) { + var uname syscall.Utsname + if err := syscall.Uname(&uname); err != nil { + return 0, 0, "", err + } + + data := make([]byte, len(uname.Release)) + for i, v := range uname.Release { + if v == 0 { + break + } + data[i] = byte(v) + } + + release := string(data) + parts := strings.SplitN(release, ".", 3) + if len(parts) < 2 { + return 0, 0, release, errors.Errorf("failed to parse uname release '%v'", release) + } + + major, err = strconv.Atoi(parts[0]) + if err != nil { + return 0, 0, release, errors.Wrapf(err, "failed to parse major version from '%v'", release) + } + + minor, err = strconv.Atoi(parts[1]) + if err != nil { + return 0, 0, release, errors.Wrapf(err, "failed to parse minor version from '%v'", release) + } + + return major, minor, release, nil +} diff --git a/auditbeat/module/audit/kernel/audit_linux_test.go b/auditbeat/module/audit/kernel/audit_linux_test.go index 7e3cc227dca..a34e151fa9e 100644 --- a/auditbeat/module/audit/kernel/audit_linux_test.go +++ b/auditbeat/module/audit/kernel/audit_linux_test.go @@ -1,24 +1,30 @@ package kernel import ( + "flag" + "fmt" + "os" + "os/exec" "testing" "time" + "github.com/stretchr/testify/assert" + mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/go-libaudit" ) +// Specify the -audit flag when running these tests to interact with the real +// kernel instead of mocks. If running in Docker this requires being in the +// host PID namespace (--pid=host) and having CAP_AUDIT_CONTROL and +// CAP_AUDIT_WRITE (so use --privileged). +var audit = flag.Bool("audit", false, "interact with the real audit framework") + var userLoginMsg = `type=USER_LOGIN msg=audit(1492896301.818:19955): pid=12635 uid=0 auid=4294967295 ses=4294967295 msg='op=login acct=28696E76616C6964207573657229 exe="/usr/sbin/sshd" hostname=? addr=179.38.151.221 terminal=sshd res=failed'` func TestData(t *testing.T) { // Create a mock netlink client that provides the expected responses. mock := NewMock(). - // GetRules response with zero rules. Used by DeleteAll rules. - returnACK().returnDone(). - // AddRule response. - returnACK(). - // AddRule response. - returnACK(). // Get Status response for initClient returnACK().returnStatus(). // Send a single audit message from the kernel. @@ -47,9 +53,74 @@ func getConfig() map[string]interface{} { "module": "audit", "metricsets": []string{"kernel"}, "kernel.failure_mode": "log", - "kernel.audit_rules": ` - -w /etc/passwd -p wa -k auth - -a always,exit -F arch=b64 -S execve -k exec - `, + "kernel.socket_type": "unicast", + } +} + +func TestMulticastClient(t *testing.T) { + if !*audit { + t.Skip("-audit was not specified") + } + + if !hasMulticastSupport() { + t.Skip("no multicast support") + } + + c := map[string]interface{}{ + "module": "audit", + "metricsets": []string{"kernel"}, + "kernel.socket_type": "multicast", + "kernel.audit_rules": fmt.Sprintf(` + -a always,exit -F arch=b64 -F ppid=%d -S execve -k exec + `, os.Getpid()), + } + + // Any commands executed by this process will generate events due to the + // PPID filter we applied to the rule. + time.AfterFunc(time.Second, func() { exec.Command("cat", "/proc/self/status").Output() }) + + ms := mbtest.NewPushMetricSet(t, c) + events, errs := mbtest.RunPushMetricSet(5*time.Second, ms) + if len(errs) > 0 { + t.Fatalf("received errors: %+v", errs) + } + + // The number of events is non-deterministic so there is no validation. + t.Logf("received %d messages via multicast", len(events)) +} + +func TestUnicastClient(t *testing.T) { + if !*audit { + t.Skip("-audit was not specified") + } + + c := map[string]interface{}{ + "module": "audit", + "metricsets": []string{"kernel"}, + "kernel.socket_type": "unicast", + "kernel.audit_rules": fmt.Sprintf(` + -a always,exit -F arch=b64 -F ppid=%d -S execve -k exec + `, os.Getpid()), + } + + // Any commands executed by this process will generate events due to the + // PPID filter we applied to the rule. + time.AfterFunc(time.Second, func() { exec.Command("cat", "/proc/self/status").Output() }) + + ms := mbtest.NewPushMetricSet(t, c) + events, errs := mbtest.RunPushMetricSet(5*time.Second, ms) + if len(errs) > 0 { + t.Fatalf("received errors: %+v", errs) + } + + t.Log(events) + assert.Len(t, events, 1) +} + +func TestKernelVersion(t *testing.T) { + major, minor, full, err := kernelVersion() + if err != nil { + t.Fatal(err) } + t.Logf("major=%v, minor=%v, full=%v", major, minor, full) } diff --git a/auditbeat/module/audit/kernel/config.go b/auditbeat/module/audit/kernel/config.go index cd0d51153a1..885ab47d4b3 100644 --- a/auditbeat/module/audit/kernel/config.go +++ b/auditbeat/module/audit/kernel/config.go @@ -22,6 +22,7 @@ type Config struct { RawMessage bool `config:"kernel.include_raw_message"` // Include the list of raw audit messages in the event. Warnings bool `config:"kernel.include_warnings"` // Include warnings in the event (for dev/debug purposes only). RulesBlob string `config:"kernel.audit_rules"` // Audit rules. One rule per line. + SocketType string `config:"kernel.socket_type"` // Socket type to use with the kernel (unicast or multicast). // Tuning options (advanced, use with care) ReassemblerMaxInFlight uint32 `config:"kernel.reassembler.max_in_flight"` @@ -35,7 +36,7 @@ type auditRule struct { } // Validate validates the rules specified in the config. -func (c Config) Validate() error { +func (c *Config) Validate() error { var errs multierror.Errors _, err := c.rules() if err != nil { @@ -45,6 +46,15 @@ func (c Config) Validate() error { if err != nil { errs = append(errs, err) } + + c.SocketType = strings.ToLower(c.SocketType) + switch c.SocketType { + case "", "unicast", "multicast": + default: + errs = append(errs, errors.Errorf("invalid kernel.socket_type "+ + "'%v' (use unicast, multicast, or don't set a value)", c.SocketType)) + } + return errs.Err() } diff --git a/auditbeat/module/audit/kernel/config_linux_test.go b/auditbeat/module/audit/kernel/config_linux_test.go index 6840846167c..fda2a42c943 100644 --- a/auditbeat/module/audit/kernel/config_linux_test.go +++ b/auditbeat/module/audit/kernel/config_linux_test.go @@ -65,6 +65,14 @@ func TestConfigValidateFailureMode(t *testing.T) { t.Log(err) } +func TestConfigValidateConnectionType(t *testing.T) { + config := defaultConfig + config.SocketType = "Satellite" + err := config.Validate() + assert.Error(t, err) + t.Log(err) +} + func parseConfig(t testing.TB, yaml string) (Config, error) { c, err := common.NewConfigWithYAML([]byte(yaml), "") if err != nil { diff --git a/metricbeat/mb/testing/modules.go b/metricbeat/mb/testing/modules.go index 9209dcd9df9..d2d865e26f0 100644 --- a/metricbeat/mb/testing/modules.go +++ b/metricbeat/mb/testing/modules.go @@ -74,7 +74,7 @@ func newMetricSet(t testing.TB, config interface{}) mb.MetricSet { } m, metricsets, err := mb.NewModule(c, mb.Registry) if err != nil { - t.Fatal(err) + t.Fatal("failed to create new MetricSet", err) } if m == nil { t.Fatal("no module instantiated") diff --git a/vendor/github.com/elastic/go-libaudit/CHANGELOG.md b/vendor/github.com/elastic/go-libaudit/CHANGELOG.md index c679bda2bb5..e5909621ef0 100644 --- a/vendor/github.com/elastic/go-libaudit/CHANGELOG.md +++ b/vendor/github.com/elastic/go-libaudit/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.0.6] + +### Added + +- Add support for listening for audit messages using a multicast group. #9 + ## [0.0.5] ### Changed diff --git a/vendor/github.com/elastic/go-libaudit/aucoalesce/mknormalize_data.go b/vendor/github.com/elastic/go-libaudit/aucoalesce/mknormalize_data.go deleted file mode 100644 index 92cb9ddb718..00000000000 --- a/vendor/github.com/elastic/go-libaudit/aucoalesce/mknormalize_data.go +++ /dev/null @@ -1,106 +0,0 @@ -// +build ignore - -package main - -import ( - "bytes" - "encoding/base64" - "flag" - "fmt" - "go/format" - "io/ioutil" - "os" - "text/template" -) - -var tpl = template.Must(template.New("normalizations").Parse(` -// mknormalize_data.go -// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT - -// Copyright 2017 Elasticsearch Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package aucoalesce - -import ( - "encoding/base64" - "fmt" -) - -var assets map[string][]byte - -func asset(key string) ([]byte, error) { - if assets == nil { - assets = map[string][]byte{} - - var value []byte - {{- range $asset := .Assets }} - value, _ = base64.StdEncoding.DecodeString("{{ $asset.Data }}") - assets["{{ $asset.Name }}"] = value{{ end }} - } - - if value, found := assets[key]; found { - return value, nil - } - return nil, fmt.Errorf("asset not found for key=%v", key) -} -`)) - -type asset struct { - Name string - Data string -} - -var assets []asset - -func addAsset(key, file string) error { - data, err := ioutil.ReadFile(file) - if err != nil { - return err - } - - assets = append(assets, asset{ - Name: key, - Data: base64.StdEncoding.EncodeToString(data), - }) - return nil -} - -type templateVars struct { - Assets []asset -} - -func main() { - flag.Parse() - - args := flag.Args() - if len(args)%2 != 0 { - fmt.Fprintln(os.Stderr, "error: expected pairs of arguments (a key and a filename)") - os.Exit(1) - } - - for i := 0; i < len(args); i += 2 { - addAsset(args[i], args[i+1]) - } - - var buf bytes.Buffer - tpl.Execute(&buf, templateVars{ - Assets: assets, - }) - bs, err := format.Source(buf.Bytes()) - if err != nil { - panic(err) - } - os.Stdout.Write(bs) -} diff --git a/vendor/github.com/elastic/go-libaudit/audit.go b/vendor/github.com/elastic/go-libaudit/audit.go index db427324510..cb3dfbc6eb9 100644 --- a/vendor/github.com/elastic/go-libaudit/audit.go +++ b/vendor/github.com/elastic/go-libaudit/audit.go @@ -43,6 +43,12 @@ const ( AuditSet ) +// Netlink groups. +const ( + NetlinkGroupNone = iota // Group 0 not used + NetlinkGroupReadLog // "best effort" read only socket +) + // WaitMode is a flag to control the behavior of methods that abstract // asynchronous communication for the caller. type WaitMode uint8 @@ -72,13 +78,27 @@ type AuditClient struct { Netlink NetlinkSendReceiver } +// NewMulticastAuditClient creates a new AuditClient that binds to the multicast +// socket subscribes to the audit group. The process should have the +// CAP_AUDIT_READ capability to use this. This audit client should not be used +// for command and control. The resp parameter is optional. If provided resp +// will receive a copy of all data read from the netlink socket. This is useful +// for debugging purposes. +func NewMulticastAuditClient(resp io.Writer) (*AuditClient, error) { + return newAuditClient(NetlinkGroupReadLog, resp) +} + // NewAuditClient creates a new AuditClient. The resp parameter is optional. If // provided resp will receive a copy of all data read from the netlink socket. // This is useful for debugging purposes. func NewAuditClient(resp io.Writer) (*AuditClient, error) { + return newAuditClient(NetlinkGroupNone, resp) +} + +func newAuditClient(netlinkGroups uint32, resp io.Writer) (*AuditClient, error) { buf := make([]byte, syscall.NLMSG_HDRLEN+AuditMessageMaxLength) - netlink, err := NewNetlinkClient(syscall.NETLINK_AUDIT, buf, resp) + netlink, err := NewNetlinkClient(syscall.NETLINK_AUDIT, netlinkGroups, buf, resp) if err != nil { return nil, err } diff --git a/vendor/github.com/elastic/go-libaudit/auparse/defs_audit_arches.go b/vendor/github.com/elastic/go-libaudit/auparse/defs_audit_arches.go deleted file mode 100644 index 8863ea9340c..00000000000 --- a/vendor/github.com/elastic/go-libaudit/auparse/defs_audit_arches.go +++ /dev/null @@ -1,104 +0,0 @@ -// mk_audit_arches.pl -// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT - -// Copyright 2017 Elasticsearch Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build ignore - -package auparse - -/* -#include -*/ -import "C" - -import "fmt" - -// AuditArch represents a machine architecture (i.e. arm, ppc, x86_64). -type AuditArch uint32 - -// List of architectures constants used by then kernel. -const ( - AUDIT_ARCH_AARCH64 AuditArch = C.AUDIT_ARCH_AARCH64 - AUDIT_ARCH_ARM AuditArch = C.AUDIT_ARCH_ARM - AUDIT_ARCH_ARMEB AuditArch = C.AUDIT_ARCH_ARMEB - AUDIT_ARCH_CRIS AuditArch = C.AUDIT_ARCH_CRIS - AUDIT_ARCH_FRV AuditArch = C.AUDIT_ARCH_FRV - AUDIT_ARCH_I386 AuditArch = C.AUDIT_ARCH_I386 - AUDIT_ARCH_IA64 AuditArch = C.AUDIT_ARCH_IA64 - AUDIT_ARCH_M32R AuditArch = C.AUDIT_ARCH_M32R - AUDIT_ARCH_M68K AuditArch = C.AUDIT_ARCH_M68K - AUDIT_ARCH_MIPS AuditArch = C.AUDIT_ARCH_MIPS - AUDIT_ARCH_MIPS64 AuditArch = C.AUDIT_ARCH_MIPS64 - AUDIT_ARCH_MIPS64N32 AuditArch = C.AUDIT_ARCH_MIPS64N32 - AUDIT_ARCH_MIPSEL AuditArch = C.AUDIT_ARCH_MIPSEL - AUDIT_ARCH_MIPSEL64 AuditArch = C.AUDIT_ARCH_MIPSEL64 - AUDIT_ARCH_MIPSEL64N32 AuditArch = C.AUDIT_ARCH_MIPSEL64N32 - AUDIT_ARCH_PARISC AuditArch = C.AUDIT_ARCH_PARISC - AUDIT_ARCH_PARISC64 AuditArch = C.AUDIT_ARCH_PARISC64 - AUDIT_ARCH_PPC AuditArch = C.AUDIT_ARCH_PPC - AUDIT_ARCH_PPC64 AuditArch = C.AUDIT_ARCH_PPC64 - AUDIT_ARCH_PPC64LE AuditArch = C.AUDIT_ARCH_PPC64LE - AUDIT_ARCH_S390 AuditArch = C.AUDIT_ARCH_S390 - AUDIT_ARCH_S390X AuditArch = C.AUDIT_ARCH_S390X - AUDIT_ARCH_SH AuditArch = C.AUDIT_ARCH_SH - AUDIT_ARCH_SH64 AuditArch = C.AUDIT_ARCH_SH64 - AUDIT_ARCH_SHEL AuditArch = C.AUDIT_ARCH_SHEL - AUDIT_ARCH_SHEL64 AuditArch = C.AUDIT_ARCH_SHEL64 - AUDIT_ARCH_SPARC AuditArch = C.AUDIT_ARCH_SPARC - AUDIT_ARCH_SPARC64 AuditArch = C.AUDIT_ARCH_SPARC64 - AUDIT_ARCH_X86_64 AuditArch = C.AUDIT_ARCH_X86_64 -) - -var AuditArchNames = map[AuditArch]string{ - AUDIT_ARCH_AARCH64: "aarch64", - AUDIT_ARCH_ARM: "arm", - AUDIT_ARCH_ARMEB: "armeb", - AUDIT_ARCH_CRIS: "cris", - AUDIT_ARCH_FRV: "frv", - AUDIT_ARCH_I386: "i386", - AUDIT_ARCH_IA64: "ia64", - AUDIT_ARCH_M32R: "m32r", - AUDIT_ARCH_M68K: "m68k", - AUDIT_ARCH_MIPS: "mips", - AUDIT_ARCH_MIPS64: "mips64", - AUDIT_ARCH_MIPS64N32: "mips64n32", - AUDIT_ARCH_MIPSEL: "mipsel", - AUDIT_ARCH_MIPSEL64: "mipsel64", - AUDIT_ARCH_MIPSEL64N32: "mipsel64n32", - AUDIT_ARCH_PARISC: "parisc", - AUDIT_ARCH_PARISC64: "parisc64", - AUDIT_ARCH_PPC: "ppc", - AUDIT_ARCH_PPC64: "ppc64", - AUDIT_ARCH_PPC64LE: "ppc64le", - AUDIT_ARCH_S390: "s390", - AUDIT_ARCH_S390X: "s390x", - AUDIT_ARCH_SH: "sh", - AUDIT_ARCH_SH64: "sh64", - AUDIT_ARCH_SHEL: "shel", - AUDIT_ARCH_SHEL64: "shel64", - AUDIT_ARCH_SPARC: "sparc", - AUDIT_ARCH_SPARC64: "sparc64", - AUDIT_ARCH_X86_64: "x86_64", -} - -func (a AuditArch) String() string { - name, found := AuditArchNames[a] - if found { - return name - } - - return fmt.Sprintf("unknown[%x]", uint32(a)) -} diff --git a/vendor/github.com/elastic/go-libaudit/auparse/mk_audit_exit_codes.go b/vendor/github.com/elastic/go-libaudit/auparse/mk_audit_exit_codes.go deleted file mode 100644 index 57ad8f41f19..00000000000 --- a/vendor/github.com/elastic/go-libaudit/auparse/mk_audit_exit_codes.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2017 Elasticsearch Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build ignore - -package main - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "regexp" - "sort" - "strconv" - "text/template" -) - -const includeErrno = ` -#include -` - -type ErrorNumber struct { - Name string - Value int -} - -// TemplateParams is the data used in evaluating the template. -type TemplateParams struct { - Command string - NameToNum []ErrorNumber - NumToName []ErrorNumber -} - -const header = `// go run {{.Command}}.go -// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT - -// Copyright 2017 Elasticsearch Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -` - -var headerTmpl = template.Must(template.New("header").Parse(header)) - -const godefsTemplate = ` -package auparse - -/* -#include -*/ -import "C" - -// AuditErrnoToNum contains a mapping of POSIX error names to errnos (error numbers). -var AuditErrnoToNum = map[string]int{ -{{- range $err := .NameToNum }} - "{{ $err.Name }}": C.{{ $err.Name }}, -{{- end }} -} - -// AuditErrnoToName contains a mapping of errnos (error numbers) to POSIX names. -var AuditErrnoToName = map[int]string{ -{{- range $err := .NumToName }} - {{ $err.Value }}: "{{ $err.Name }}", -{{- end }} -} -` - -var tmpl = template.Must(template.New("message_types").Parse(godefsTemplate)) - -var ( - errnoDefRegex = regexp.MustCompile(`^#define\s+(E\w+)\s+(\w+)`) -) - -func readErrorNumbers() ([]ErrorNumber, error) { - cmd := exec.Command("gcc", "-E", "-dD", "-") - cmd.Stdin = bytes.NewBufferString(includeErrno) - out, err := cmd.Output() - if err != nil { - return nil, err - } - - errorToNum := map[string]int{} - s := bufio.NewScanner(bytes.NewReader(out)) - for s.Scan() { - matches := errnoDefRegex.FindStringSubmatch(s.Text()) - if len(matches) != 3 { - continue - } - errno, err := strconv.Atoi(matches[2]) - if err != nil { - errorToNum[matches[1]] = -1 - continue - } - - errorToNum[matches[1]] = errno - } - - var errnos []ErrorNumber - for name, value := range errorToNum { - errnos = append(errnos, ErrorNumber{ - Name: name, - Value: value, - }) - } - - sort.Slice(errnos, func(i, j int) bool { - return errnos[i].Value < errnos[j].Value - }) - - return errnos, nil -} - -func run() error { - tmp, err := ioutil.TempDir("", "mk_audit_exit_codes") - if err != nil { - return err - } - defer os.RemoveAll(tmp) - - if err := os.Chdir(tmp); err != nil { - return err - } - - errnos, err := readErrorNumbers() - if err != nil { - return err - } - - // Filter duplicates and sort by name. - var numToName []ErrorNumber - for _, errno := range errnos { - if errno.Value >= 0 { - numToName = append(numToName, errno) - } - } - - // Create output file. - f, err := os.Create("defs.go") - if err != nil { - return err - } - defer f.Close() - - // Evaluate template. - r := TemplateParams{ - Command: filepath.Base(os.Args[0]), - NameToNum: errnos, - NumToName: numToName, - } - if err := tmpl.Execute(f, r); err != nil { - return err - } - - output, err := exec.Command("go", "tool", "cgo", "-godefs", "defs.go").Output() - if err != nil { - return err - } - - buf := new(bytes.Buffer) - if err = headerTmpl.Execute(buf, r); err != nil { - return nil - } - - s := bufio.NewScanner(bytes.NewReader(output)) - for s.Scan() { - if !bytes.HasPrefix(s.Bytes(), []byte("//")) { - buf.Write(s.Bytes()) - buf.WriteByte('\n') - } - } - - if err = ioutil.WriteFile(flagOut, buf.Bytes(), 0644); err != nil { - return err - } - - _, err = exec.Command("gofmt", "-w", "-s", flagOut).Output() - if err != nil { - return err - } - - return nil -} - -var flagOut string - -func main() { - flag.StringVar(&flagOut, "out", "zaudit_exit_codes.go", "output file") - flag.Parse() - - var err error - flagOut, err = filepath.Abs(flagOut) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - - if err := run(); err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } -} diff --git a/vendor/github.com/elastic/go-libaudit/auparse/mk_audit_msg_types.go b/vendor/github.com/elastic/go-libaudit/auparse/mk_audit_msg_types.go deleted file mode 100644 index 340bba2949c..00000000000 --- a/vendor/github.com/elastic/go-libaudit/auparse/mk_audit_msg_types.go +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2017 Elasticsearch Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build ignore - -package main - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "text/template" -) - -// Min and max record/message numbers. -const ( - minRecordNum = 1000 - maxRecordNum = 3000 -) - -// TemplateParams is the data used in evaluating the template. -type TemplateParams struct { - Command string - RecordTypes map[int]string - RecordNames map[string]string -} - -const fileTemplate = ` -// go run {{.Command}}.go -// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT - -// Copyright 2017 Elasticsearch Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package auparse - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -var errInvalidAuditMessageTypName = errors.New("invalid message type") - -// AuditMessageType represents an audit message type used by the kernel. -type AuditMessageType uint16 - -// List of AuditMessageTypes. -const( -{{- range $recordNum, $recordType := .RecordTypes }} - {{ $recordType}} AuditMessageType = {{ $recordNum }} -{{- end }} -) - -var auditMessageTypeToName = map[AuditMessageType]string{ -{{- range $recordType, $recordName := .RecordNames }} - {{ $recordType }}: "{{ $recordName }}", -{{- end }} -} - -func (t AuditMessageType) String() string { - name, found := auditMessageTypeToName[t] - if found { - return name - } - - return fmt.Sprintf("UNKNOWN[%d]", uint16(t)) -} - -func (t AuditMessageType) MarshalText() (text []byte, err error) { - return []byte(strings.ToLower(t.String())), nil -} - -var auditMessageNameToType = map[string]AuditMessageType{ -{{- range $recordType, $recordName := .RecordNames }} - "{{ $recordName }}": {{ $recordType }}, -{{- end }} -} - -// GetAuditMessageType accepts a type name and returns its numerical -// representation. If the name is unknown and error is returned. -func GetAuditMessageType(name string) (AuditMessageType, error) { - typ, found := auditMessageNameToType[name] - if found { - return typ, nil - } - - // Parse type from UNKNOWN[1329]. - start := strings.IndexByte(name, '[') - if start == -1 { - return 0, errInvalidAuditMessageTypName - } - name = name[start+1:] - - end := strings.IndexByte(name, ']') - if end == -1 { - return 0, errInvalidAuditMessageTypName - } - name = name[:end] - - num, err := strconv.ParseUint(name, 10, 16) - if err != nil { - return 0, errInvalidAuditMessageTypName - } - - return AuditMessageType(num), nil -} -` - -var tmpl = template.Must(template.New("message_types").Parse(fileTemplate)) - -var ( - headers = []string{ - `https://raw.githubusercontent.com/linux-audit/audit-kernel/v4.7/include/uapi/linux/audit.h`, - `https://raw.githubusercontent.com/linux-audit/audit-userspace/990aa27ccd02f9743c4f4049887ab89678ab362a/lib/libaudit.h`, - `https://raw.githubusercontent.com/linux-audit/audit-userspace/990aa27ccd02f9743c4f4049887ab89678ab362a/lib/msg_typetab.h`, - } -) - -func DownloadFile(url, destinationDir string) (string, error) { - resp, err := http.Get(url) - if err != nil { - return "", fmt.Errorf("http get failed: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("download failed with http status %v", resp.StatusCode) - } - - name := filepath.Join(destinationDir, filepath.Base(url)) - f, err := os.Create(name) - if err != nil { - return "", fmt.Errorf("failed to create output file: %v", err) - } - - _, err = io.Copy(f, resp.Body) - if err != nil { - return "", fmt.Errorf("failed to write file to disk: %v", err) - } - - return name, nil -} - -var ( - // nameMappingRegex is used to parse name mappings from msg_typetab.h. - nameMappingRegex = regexp.MustCompile(`^_S\((AUDIT_\w+),\s+"(\w+)"`) - - // recordTypeDefinitionRegex is used to parse type definitions from audit - // header files. - recordTypeDefinitionRegex = regexp.MustCompile(`^#define\s+(AUDIT_\w+)\s+(\d+)`) - - // nameExtractorRegex extracts a name from constants that did not have - // an explicit name mapping in msg_typetab.h. - nameExtractorRegex = regexp.MustCompile(`^AUDIT_(\w+)`) -) - -func readMessageTypeTable() (map[string]string, error) { - f, err := os.Open("msg_typetab.h") - if err != nil { - return nil, err - } - defer f.Close() - - constantToStringName := map[string]string{} - s := bufio.NewScanner(f) - for s.Scan() { - matches := nameMappingRegex.FindStringSubmatch(s.Text()) - if len(matches) == 3 { - constantToStringName[matches[1]] = matches[2] - } - } - - return constantToStringName, nil -} - -func readRecordTypes() (map[string]int, error) { - out, err := exec.Command("gcc", "-E", "-dD", "libaudit.h", "audit.h").Output() - if err != nil { - return nil, err - } - - recordTypeToNum := map[string]int{} - s := bufio.NewScanner(bytes.NewReader(out)) - for s.Scan() { - matches := recordTypeDefinitionRegex.FindStringSubmatch(s.Text()) - if len(matches) != 3 { - continue - } - recordNum, _ := strconv.Atoi(matches[2]) - - // Filter constants. - if recordNum >= minRecordNum && recordNum <= maxRecordNum { - recordTypeToNum[matches[1]] = recordNum - } - } - - return recordTypeToNum, nil -} - -func run() error { - tmp, err := ioutil.TempDir("", "mk_audit_msg_types") - if err != nil { - return err - } - defer os.RemoveAll(tmp) - - // Download header files from the Linux audit project. - var files []string - for _, url := range headers { - f, err := DownloadFile(url, tmp) - if err != nil { - return err - } - files = append(files, f) - } - - if err := os.Chdir(tmp); err != nil { - return err - } - - recordTypeToStringName, err := readMessageTypeTable() - if err != nil { - return err - } - - recordTypeToNum, err := readRecordTypes() - if err != nil { - return err - } - - numToRecordType := map[int]string{} - for recordType := range recordTypeToStringName { - num, found := recordTypeToNum[recordType] - if !found { - return fmt.Errorf("missing definition of %v", recordType) - } - numToRecordType[num] = recordType - } - - for recordType, num := range recordTypeToNum { - // Do not replace existing mappings. - if _, found := numToRecordType[num]; found { - continue - } - - numToRecordType[num] = recordType - - matches := nameExtractorRegex.FindStringSubmatch(recordType) - if len(matches) == 2 { - recordTypeToStringName[recordType] = matches[1] - } - } - - // Create output file. - f, err := os.Create(flagOut) - if err != nil { - return err - } - defer f.Close() - - // Evaluate template. - r := TemplateParams{ - Command: filepath.Base(os.Args[0]), - RecordTypes: numToRecordType, - RecordNames: recordTypeToStringName, - } - if err := tmpl.Execute(f, r); err != nil { - return err - } - - return nil -} - -var flagOut string - -func main() { - flag.StringVar(&flagOut, "out", "zaudit_msg_types.go", "output file") - flag.Parse() - - var err error - flagOut, err = filepath.Abs(flagOut) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - - if err := run(); err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } -} diff --git a/vendor/github.com/elastic/go-libaudit/netlink.go b/vendor/github.com/elastic/go-libaudit/netlink.go index aa111d8d4cd..1300245b25a 100644 --- a/vendor/github.com/elastic/go-libaudit/netlink.go +++ b/vendor/github.com/elastic/go-libaudit/netlink.go @@ -73,16 +73,16 @@ type NetlinkClient struct { // (this is useful for debugging). // // The returned NetlinkClient must be closed with Close() when finished. -func NewNetlinkClient(proto int, readBuf []byte, resp io.Writer) (*NetlinkClient, error) { +func NewNetlinkClient(proto int, groups uint32, readBuf []byte, resp io.Writer) (*NetlinkClient, error) { s, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, proto) if err != nil { return nil, err } - src := &syscall.SockaddrNetlink{Family: syscall.AF_NETLINK} + src := &syscall.SockaddrNetlink{Family: syscall.AF_NETLINK, Groups: groups} if err = syscall.Bind(s, src); err != nil { syscall.Close(s) - return nil, err + return nil, errors.Wrap(err, "bind failed") } pid, err := getPortID(s) diff --git a/vendor/vendor.json b/vendor/vendor.json index 69708a13963..22dc49a4a90 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -359,44 +359,44 @@ "revisionTime": "2016-08-05T00:47:13Z" }, { - "checksumSHA1": "Pd9e8K98V1LGGScIG/u4Z36l0P0=", + "checksumSHA1": "/JppfHtRGQSFjB9FlY2jpHhmlhk=", "path": "github.com/elastic/go-libaudit", - "revision": "3a005d3d0bbcee26d60e3ab2f1890699746f4da6", - "revisionTime": "2017-07-24T13:10:22Z", - "version": "v0.0.5", - "versionExact": "v0.0.5" + "revision": "df0d4981f3fce65ffd3d7411dfec3e03231b491c", + "revisionTime": "2017-09-07T20:19:58Z", + "version": "v0.0.6", + "versionExact": "v0.0.6" }, { - "checksumSHA1": "Ca2OhodWbbke1v+cctf9y/HdwZM=", + "checksumSHA1": "n8bRlhOdmfREBoCgStzHWGWiwSY=", "path": "github.com/elastic/go-libaudit/aucoalesce", - "revision": "3a005d3d0bbcee26d60e3ab2f1890699746f4da6", - "revisionTime": "2017-07-24T13:10:22Z", - "version": "v0.0.5", - "versionExact": "v0.0.5" + "revision": "df0d4981f3fce65ffd3d7411dfec3e03231b491c", + "revisionTime": "2017-09-07T20:19:58Z", + "version": "v0.0.6", + "versionExact": "v0.0.6" }, { - "checksumSHA1": "N+9Ssj7RWKl2Sk1DqVmZ2Z3f8Ts=", + "checksumSHA1": "eUIiDm0pSFKNKjWme5s3PtWEoSU=", "path": "github.com/elastic/go-libaudit/auparse", - "revision": "3a005d3d0bbcee26d60e3ab2f1890699746f4da6", - "revisionTime": "2017-07-24T13:10:22Z", - "version": "v0.0.5", - "versionExact": "v0.0.5" + "revision": "df0d4981f3fce65ffd3d7411dfec3e03231b491c", + "revisionTime": "2017-09-07T20:19:58Z", + "version": "v0.0.6", + "versionExact": "v0.0.6" }, { "checksumSHA1": "H0rnscnKHbkjmXc4whC3gtIPR0c=", "path": "github.com/elastic/go-libaudit/rule", - "revision": "3a005d3d0bbcee26d60e3ab2f1890699746f4da6", - "revisionTime": "2017-07-24T13:10:22Z", - "version": "v0.0.5", - "versionExact": "v0.0.5" + "revision": "df0d4981f3fce65ffd3d7411dfec3e03231b491c", + "revisionTime": "2017-09-07T20:19:58Z", + "version": "v0.0.6", + "versionExact": "v0.0.6" }, { "checksumSHA1": "36UaYid29Kyhrsa5D8N6BoM8dVw=", "path": "github.com/elastic/go-libaudit/rule/flags", - "revision": "3a005d3d0bbcee26d60e3ab2f1890699746f4da6", - "revisionTime": "2017-07-24T13:10:22Z", - "version": "v0.0.5", - "versionExact": "v0.0.5" + "revision": "df0d4981f3fce65ffd3d7411dfec3e03231b491c", + "revisionTime": "2017-09-07T20:19:58Z", + "version": "v0.0.6", + "versionExact": "v0.0.6" }, { "checksumSHA1": "3jizmlZPCyo6FAZY8Trk9jA8NH4=",