From 49caba9b2f0f61f06ba4ab4020c864970e952351 Mon Sep 17 00:00:00 2001 From: reimda Date: Fri, 5 Jun 2020 08:35:14 -0600 Subject: [PATCH] Add tags to snmp_trap input for context name and engine ID (#7633) Add tags for the context name and engine ID --- plugins/inputs/snmp_trap/README.md | 4 +- plugins/inputs/snmp_trap/snmp_trap.go | 20 +-- plugins/inputs/snmp_trap/snmp_trap_test.go | 197 +++++++++++---------- 3 files changed, 114 insertions(+), 107 deletions(-) diff --git a/plugins/inputs/snmp_trap/README.md b/plugins/inputs/snmp_trap/README.md index 630566518..046f18e49 100644 --- a/plugins/inputs/snmp_trap/README.md +++ b/plugins/inputs/snmp_trap/README.md @@ -45,8 +45,6 @@ information. # auth_password = "pass" ## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv". # sec_level = "authNoPriv" - ## Context Name. - # context_name = "" ## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "". # priv_protocol = "" ## Privacy password used for encrypted messages. @@ -87,6 +85,8 @@ On Mac OS, listening on privileged ports is unrestricted on versions - mib (string, MIB from SNMPv2-MIB::snmpTrapOID.0 PDU) - oid (string, OID string from SNMPv2-MIB::snmpTrapOID.0 PDU) - version (string, "1" or "2c" or "3") + - context_name (string, value from v3 trap) + - engine_id (string, value from v3 trap) - fields: - Fields are mapped from variables in the trap. Field names are the trap variable names after MIB lookup. Field values are trap diff --git a/plugins/inputs/snmp_trap/snmp_trap.go b/plugins/inputs/snmp_trap/snmp_trap.go index 9db058955..dbf0cdbf3 100644 --- a/plugins/inputs/snmp_trap/snmp_trap.go +++ b/plugins/inputs/snmp_trap/snmp_trap.go @@ -34,7 +34,6 @@ type SnmpTrap struct { Version string `toml:"version"` // Settings for version 3 - ContextName string `toml:"context_name"` // Values: "noAuthNoPriv", "authNoPriv", "authPriv" SecLevel string `toml:"sec_level"` SecName string `toml:"sec_name"` @@ -44,9 +43,6 @@ type SnmpTrap struct { // Values: "DES", "AES", "". Default: "" PrivProtocol string `toml:"priv_protocol"` PrivPassword string `toml:"priv_password"` - EngineID string `toml:"-"` - EngineBoots uint32 `toml:"-"` - EngineTime uint32 `toml:"-"` acc telegraf.Accumulator listener *gosnmp.TrapListener @@ -86,8 +82,6 @@ var sampleConfig = ` # auth_password = "pass" ## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv". # sec_level = "authNoPriv" - ## Context Name. - # context_name = "" ## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "". # priv_protocol = "" ## Privacy password used for encrypted messages. @@ -152,7 +146,6 @@ func (s *SnmpTrap) Start(acc telegraf.Accumulator) error { } if s.listener.Params.Version == gosnmp.Version3 { - s.listener.Params.ContextName = s.ContextName s.listener.Params.SecurityModel = gosnmp.UserSecurityModel switch strings.ToLower(s.SecLevel) { @@ -207,9 +200,6 @@ func (s *SnmpTrap) Start(acc telegraf.Accumulator) error { } s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{ - AuthoritativeEngineID: s.EngineID, - AuthoritativeEngineBoots: s.EngineBoots, - AuthoritativeEngineTime: s.EngineTime, UserName: s.SecName, PrivacyProtocol: privacyProtocol, PrivacyPassphrase: s.PrivPassword, @@ -359,6 +349,16 @@ func makeTrapHandler(s *SnmpTrap) handler { fields[name] = value } + if packet.Version == gosnmp.Version3 { + if packet.ContextName != "" { + tags["context_name"] = packet.ContextName + } + if packet.ContextEngineID != "" { + // SNMP RFCs like 3411 and 5343 show engine ID as a hex string + tags["engine_id"] = fmt.Sprintf("%x", packet.ContextEngineID) + } + } + s.acc.AddFields("snmp_trap", fields, tags, tm) } } diff --git a/plugins/inputs/snmp_trap/snmp_trap_test.go b/plugins/inputs/snmp_trap/snmp_trap_test.go index ccd723399..dcc9b5d68 100644 --- a/plugins/inputs/snmp_trap/snmp_trap_test.go +++ b/plugins/inputs/snmp_trap/snmp_trap_test.go @@ -40,12 +40,12 @@ func fakeExecCmd(_ internal.Duration, x string, y ...string) ([]byte, error) { return nil, fmt.Errorf("mock " + x + " " + strings.Join(y, " ")) } -func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, version gosnmp.SnmpVersion, seclevel string, username string, authproto string, authpass string, privproto string, privpass string) { +func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, version gosnmp.SnmpVersion, secLevel string, username string, authProto string, authPass string, privProto string, privPass string, contextName string, engineID string) { var s gosnmp.GoSNMP if version == gosnmp.Version3 { var msgFlags gosnmp.SnmpV3MsgFlags - switch strings.ToLower(seclevel) { + switch strings.ToLower(secLevel) { case "noauthnopriv", "": msgFlags = gosnmp.NoAuthNoPriv case "authnopriv": @@ -57,7 +57,7 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi } var authenticationProtocol gosnmp.SnmpV3AuthProtocol - switch strings.ToLower(authproto) { + switch strings.ToLower(authProto) { case "md5": authenticationProtocol = gosnmp.MD5 case "sha": @@ -77,7 +77,7 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi } var privacyProtocol gosnmp.SnmpV3PrivProtocol - switch strings.ToLower(privproto) { + switch strings.ToLower(privProto) { case "aes": privacyProtocol = gosnmp.AES case "des": @@ -102,8 +102,8 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi AuthoritativeEngineTime: 1, UserName: username, PrivacyProtocol: privacyProtocol, - PrivacyPassphrase: privpass, - AuthenticationPassphrase: authpass, + PrivacyPassphrase: privPass, + AuthenticationPassphrase: authPass, AuthenticationProtocol: authenticationProtocol, } s = gosnmp.GoSNMP{ @@ -116,6 +116,8 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi SecurityParameters: sp, SecurityModel: gosnmp.UserSecurityModel, MsgFlags: msgFlags, + ContextName: contextName, + ContextEngineID: engineID, } } else { s = gosnmp.GoSNMP{ @@ -162,12 +164,16 @@ func TestReceiveTrap(t *testing.T) { version gosnmp.SnmpVersion trap gosnmp.SnmpTrap // include pdus // V3 auth and priv parameters - secname string // v3 username - seclevel string // v3 security level - authproto string // Auth protocol: "", MD5 or SHA - authpass string // Auth passphrase - privproto string // Priv protocol: "", DES or AES - privpass string // Priv passphrase + secName string // v3 username + secLevel string // v3 security level + authProto string // Auth protocol: "", MD5 or SHA + authPass string // Auth passphrase + privProto string // Priv protocol: "", DES or AES + privPass string // Priv passphrase + + // V3 sender context + contextName string + engineID string // receive entries []entry @@ -363,10 +369,12 @@ func TestReceiveTrap(t *testing.T) { }, //ordinary v3 coldStart trap no auth and no priv { - name: "v3 coldStart noAuthNoPriv", - version: gosnmp.Version3, - secname: "noAuthNoPriv", - seclevel: "noAuthNoPriv", + name: "v3 coldStart noAuthNoPriv", + version: gosnmp.Version3, + secName: "noAuthNoPriv", + secLevel: "noAuthNoPriv", + contextName: "foo_context_name", + engineID: "bar_engine_id", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -408,11 +416,13 @@ func TestReceiveTrap(t *testing.T) { testutil.MustMetric( "snmp_trap", // name map[string]string{ // tags - "oid": ".1.3.6.1.6.3.1.1.5.1", - "name": "coldStart", - "mib": "SNMPv2-MIB", - "version": "3", - "source": "127.0.0.1", + "oid": ".1.3.6.1.6.3.1.1.5.1", + "name": "coldStart", + "mib": "SNMPv2-MIB", + "version": "3", + "source": "127.0.0.1", + "context_name": "foo_context_name", + "engine_id": "6261725f656e67696e655f6964", }, map[string]interface{}{ // fields "sysUpTimeInstance": now, @@ -425,10 +435,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authShaNoPriv", version: gosnmp.Version3, - secname: "authShaNoPriv", - seclevel: "authNoPriv", - authproto: "SHA", - authpass: "passpass", + secName: "authShaNoPriv", + secLevel: "authNoPriv", + authProto: "SHA", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -488,10 +498,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authShaNoPriv", version: gosnmp.Version3, - secname: "authSha224NoPriv", - seclevel: "authNoPriv", - authproto: "SHA224", - authpass: "passpass", + secName: "authSha224NoPriv", + secLevel: "authNoPriv", + authProto: "SHA224", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -550,10 +560,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSha256NoPriv", version: gosnmp.Version3, - secname: "authSha256NoPriv", - seclevel: "authNoPriv", - authproto: "SHA256", - authpass: "passpass", + secName: "authSha256NoPriv", + secLevel: "authNoPriv", + authProto: "SHA256", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -612,10 +622,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSha384NoPriv", version: gosnmp.Version3, - secname: "authSha384NoPriv", - seclevel: "authNoPriv", - authproto: "SHA384", - authpass: "passpass", + secName: "authSha384NoPriv", + secLevel: "authNoPriv", + authProto: "SHA384", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -674,10 +684,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authShaNoPriv", version: gosnmp.Version3, - secname: "authSha512NoPriv", - seclevel: "authNoPriv", - authproto: "SHA512", - authpass: "passpass", + secName: "authSha512NoPriv", + secLevel: "authNoPriv", + authProto: "SHA512", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -736,10 +746,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authShaNoPriv", version: gosnmp.Version3, - secname: "authShaNoPriv", - seclevel: "authNoPriv", - authproto: "SHA", - authpass: "passpass", + secName: "authShaNoPriv", + secLevel: "authNoPriv", + authProto: "SHA", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -798,10 +808,10 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authMD5NoPriv", version: gosnmp.Version3, - secname: "authMD5NoPriv", - seclevel: "authNoPriv", - authproto: "MD5", - authpass: "passpass", + secName: "authMD5NoPriv", + secLevel: "authNoPriv", + authProto: "MD5", + authPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -860,12 +870,12 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSHAPrivAES", version: gosnmp.Version3, - secname: "authSHAPrivAES", - seclevel: "authPriv", - authproto: "SHA", - authpass: "passpass", - privproto: "AES", - privpass: "passpass", + secName: "authSHAPrivAES", + secLevel: "authPriv", + authProto: "SHA", + authPass: "passpass", + privProto: "AES", + privPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -924,12 +934,12 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSHAPrivDES", version: gosnmp.Version3, - secname: "authSHAPrivDES", - seclevel: "authPriv", - authproto: "SHA", - authpass: "passpass", - privproto: "DES", - privpass: "passpass", + secName: "authSHAPrivDES", + secLevel: "authPriv", + authProto: "SHA", + authPass: "passpass", + privProto: "DES", + privPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -988,12 +998,12 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSHAPrivAES192", version: gosnmp.Version3, - secname: "authSHAPrivAES192", - seclevel: "authPriv", - authproto: "SHA", - authpass: "passpass", - privproto: "AES192", - privpass: "passpass", + secName: "authSHAPrivAES192", + secLevel: "authPriv", + authProto: "SHA", + authPass: "passpass", + privProto: "AES192", + privPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -1052,12 +1062,12 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSHAPrivAES192C", version: gosnmp.Version3, - secname: "authSHAPrivAES192C", - seclevel: "authPriv", - authproto: "SHA", - authpass: "passpass", - privproto: "AES192C", - privpass: "passpass", + secName: "authSHAPrivAES192C", + secLevel: "authPriv", + authProto: "SHA", + authPass: "passpass", + privProto: "AES192C", + privPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -1116,12 +1126,12 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSHAPrivAES256", version: gosnmp.Version3, - secname: "authSHAPrivAES256", - seclevel: "authPriv", - authproto: "SHA", - authpass: "passpass", - privproto: "AES256", - privpass: "passpass", + secName: "authSHAPrivAES256", + secLevel: "authPriv", + authProto: "SHA", + authPass: "passpass", + privProto: "AES256", + privPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -1180,12 +1190,12 @@ func TestReceiveTrap(t *testing.T) { { name: "v3 coldStart authSHAPrivAES256C", version: gosnmp.Version3, - secname: "authSHAPrivAES256C", - seclevel: "authPriv", - authproto: "SHA", - authpass: "passpass", - privproto: "AES256C", - privpass: "passpass", + secName: "authSHAPrivAES256C", + secLevel: "authPriv", + authProto: "SHA", + authPass: "passpass", + privProto: "AES256C", + privPass: "passpass", trap: gosnmp.SnmpTrap{ Variables: []gosnmp.SnmpPDU{ { @@ -1269,15 +1279,12 @@ func TestReceiveTrap(t *testing.T) { }, Log: testutil.Logger{}, Version: tt.version.String(), - SecName: tt.secname, - SecLevel: tt.seclevel, - AuthProtocol: tt.authproto, - AuthPassword: tt.authpass, - PrivProtocol: tt.privproto, - PrivPassword: tt.privpass, - EngineID: "80001f8880031dd407f608905e00000000", - EngineBoots: 1, - EngineTime: 1, + SecName: tt.secName, + SecLevel: tt.secLevel, + AuthProtocol: tt.authProto, + AuthPassword: tt.authPass, + PrivProtocol: tt.privProto, + PrivPassword: tt.privPass, } require.Nil(t, s.Init()) var acc testutil.Accumulator @@ -1294,7 +1301,7 @@ func TestReceiveTrap(t *testing.T) { s.execCmd = fakeExecCmd // Send the trap - sendTrap(t, port, now, tt.trap, tt.version, tt.seclevel, tt.secname, tt.authproto, tt.authpass, tt.privproto, tt.privpass) + sendTrap(t, port, now, tt.trap, tt.version, tt.secLevel, tt.secName, tt.authProto, tt.authPass, tt.privProto, tt.privPass, tt.contextName, tt.engineID) // Wait for trap to be received select {