Add tags to snmp_trap input for context name and engine ID (#7633)

Add tags for the context name and engine ID
This commit is contained in:
reimda 2020-06-05 08:35:14 -06:00 committed by GitHub
parent 6f931c9834
commit 49caba9b2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 107 deletions

View File

@ -45,8 +45,6 @@ information.
# auth_password = "pass" # auth_password = "pass"
## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv". ## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv".
# sec_level = "authNoPriv" # sec_level = "authNoPriv"
## Context Name.
# context_name = ""
## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "". ## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "".
# priv_protocol = "" # priv_protocol = ""
## Privacy password used for encrypted messages. ## 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) - mib (string, MIB from SNMPv2-MIB::snmpTrapOID.0 PDU)
- oid (string, OID string from SNMPv2-MIB::snmpTrapOID.0 PDU) - oid (string, OID string from SNMPv2-MIB::snmpTrapOID.0 PDU)
- version (string, "1" or "2c" or "3") - version (string, "1" or "2c" or "3")
- context_name (string, value from v3 trap)
- engine_id (string, value from v3 trap)
- fields: - fields:
- Fields are mapped from variables in the trap. Field names are - Fields are mapped from variables in the trap. Field names are
the trap variable names after MIB lookup. Field values are trap the trap variable names after MIB lookup. Field values are trap

View File

@ -34,7 +34,6 @@ type SnmpTrap struct {
Version string `toml:"version"` Version string `toml:"version"`
// Settings for version 3 // Settings for version 3
ContextName string `toml:"context_name"`
// Values: "noAuthNoPriv", "authNoPriv", "authPriv" // Values: "noAuthNoPriv", "authNoPriv", "authPriv"
SecLevel string `toml:"sec_level"` SecLevel string `toml:"sec_level"`
SecName string `toml:"sec_name"` SecName string `toml:"sec_name"`
@ -44,9 +43,6 @@ type SnmpTrap struct {
// Values: "DES", "AES", "". Default: "" // Values: "DES", "AES", "". Default: ""
PrivProtocol string `toml:"priv_protocol"` PrivProtocol string `toml:"priv_protocol"`
PrivPassword string `toml:"priv_password"` PrivPassword string `toml:"priv_password"`
EngineID string `toml:"-"`
EngineBoots uint32 `toml:"-"`
EngineTime uint32 `toml:"-"`
acc telegraf.Accumulator acc telegraf.Accumulator
listener *gosnmp.TrapListener listener *gosnmp.TrapListener
@ -86,8 +82,6 @@ var sampleConfig = `
# auth_password = "pass" # auth_password = "pass"
## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv". ## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv".
# sec_level = "authNoPriv" # sec_level = "authNoPriv"
## Context Name.
# context_name = ""
## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "". ## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "".
# priv_protocol = "" # priv_protocol = ""
## Privacy password used for encrypted messages. ## 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 { if s.listener.Params.Version == gosnmp.Version3 {
s.listener.Params.ContextName = s.ContextName
s.listener.Params.SecurityModel = gosnmp.UserSecurityModel s.listener.Params.SecurityModel = gosnmp.UserSecurityModel
switch strings.ToLower(s.SecLevel) { switch strings.ToLower(s.SecLevel) {
@ -207,9 +200,6 @@ func (s *SnmpTrap) Start(acc telegraf.Accumulator) error {
} }
s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{ s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
AuthoritativeEngineID: s.EngineID,
AuthoritativeEngineBoots: s.EngineBoots,
AuthoritativeEngineTime: s.EngineTime,
UserName: s.SecName, UserName: s.SecName,
PrivacyProtocol: privacyProtocol, PrivacyProtocol: privacyProtocol,
PrivacyPassphrase: s.PrivPassword, PrivacyPassphrase: s.PrivPassword,
@ -359,6 +349,16 @@ func makeTrapHandler(s *SnmpTrap) handler {
fields[name] = value 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) s.acc.AddFields("snmp_trap", fields, tags, tm)
} }
} }

View File

@ -40,12 +40,12 @@ func fakeExecCmd(_ internal.Duration, x string, y ...string) ([]byte, error) {
return nil, fmt.Errorf("mock " + x + " " + strings.Join(y, " ")) 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 var s gosnmp.GoSNMP
if version == gosnmp.Version3 { if version == gosnmp.Version3 {
var msgFlags gosnmp.SnmpV3MsgFlags var msgFlags gosnmp.SnmpV3MsgFlags
switch strings.ToLower(seclevel) { switch strings.ToLower(secLevel) {
case "noauthnopriv", "": case "noauthnopriv", "":
msgFlags = gosnmp.NoAuthNoPriv msgFlags = gosnmp.NoAuthNoPriv
case "authnopriv": case "authnopriv":
@ -57,7 +57,7 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi
} }
var authenticationProtocol gosnmp.SnmpV3AuthProtocol var authenticationProtocol gosnmp.SnmpV3AuthProtocol
switch strings.ToLower(authproto) { switch strings.ToLower(authProto) {
case "md5": case "md5":
authenticationProtocol = gosnmp.MD5 authenticationProtocol = gosnmp.MD5
case "sha": case "sha":
@ -77,7 +77,7 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi
} }
var privacyProtocol gosnmp.SnmpV3PrivProtocol var privacyProtocol gosnmp.SnmpV3PrivProtocol
switch strings.ToLower(privproto) { switch strings.ToLower(privProto) {
case "aes": case "aes":
privacyProtocol = gosnmp.AES privacyProtocol = gosnmp.AES
case "des": case "des":
@ -102,8 +102,8 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi
AuthoritativeEngineTime: 1, AuthoritativeEngineTime: 1,
UserName: username, UserName: username,
PrivacyProtocol: privacyProtocol, PrivacyProtocol: privacyProtocol,
PrivacyPassphrase: privpass, PrivacyPassphrase: privPass,
AuthenticationPassphrase: authpass, AuthenticationPassphrase: authPass,
AuthenticationProtocol: authenticationProtocol, AuthenticationProtocol: authenticationProtocol,
} }
s = gosnmp.GoSNMP{ s = gosnmp.GoSNMP{
@ -116,6 +116,8 @@ func sendTrap(t *testing.T, port uint16, now uint32, trap gosnmp.SnmpTrap, versi
SecurityParameters: sp, SecurityParameters: sp,
SecurityModel: gosnmp.UserSecurityModel, SecurityModel: gosnmp.UserSecurityModel,
MsgFlags: msgFlags, MsgFlags: msgFlags,
ContextName: contextName,
ContextEngineID: engineID,
} }
} else { } else {
s = gosnmp.GoSNMP{ s = gosnmp.GoSNMP{
@ -162,12 +164,16 @@ func TestReceiveTrap(t *testing.T) {
version gosnmp.SnmpVersion version gosnmp.SnmpVersion
trap gosnmp.SnmpTrap // include pdus trap gosnmp.SnmpTrap // include pdus
// V3 auth and priv parameters // V3 auth and priv parameters
secname string // v3 username secName string // v3 username
seclevel string // v3 security level secLevel string // v3 security level
authproto string // Auth protocol: "", MD5 or SHA authProto string // Auth protocol: "", MD5 or SHA
authpass string // Auth passphrase authPass string // Auth passphrase
privproto string // Priv protocol: "", DES or AES privProto string // Priv protocol: "", DES or AES
privpass string // Priv passphrase privPass string // Priv passphrase
// V3 sender context
contextName string
engineID string
// receive // receive
entries []entry entries []entry
@ -363,10 +369,12 @@ func TestReceiveTrap(t *testing.T) {
}, },
//ordinary v3 coldStart trap no auth and no priv //ordinary v3 coldStart trap no auth and no priv
{ {
name: "v3 coldStart noAuthNoPriv", name: "v3 coldStart noAuthNoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "noAuthNoPriv", secName: "noAuthNoPriv",
seclevel: "noAuthNoPriv", secLevel: "noAuthNoPriv",
contextName: "foo_context_name",
engineID: "bar_engine_id",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -408,11 +416,13 @@ func TestReceiveTrap(t *testing.T) {
testutil.MustMetric( testutil.MustMetric(
"snmp_trap", // name "snmp_trap", // name
map[string]string{ // tags map[string]string{ // tags
"oid": ".1.3.6.1.6.3.1.1.5.1", "oid": ".1.3.6.1.6.3.1.1.5.1",
"name": "coldStart", "name": "coldStart",
"mib": "SNMPv2-MIB", "mib": "SNMPv2-MIB",
"version": "3", "version": "3",
"source": "127.0.0.1", "source": "127.0.0.1",
"context_name": "foo_context_name",
"engine_id": "6261725f656e67696e655f6964",
}, },
map[string]interface{}{ // fields map[string]interface{}{ // fields
"sysUpTimeInstance": now, "sysUpTimeInstance": now,
@ -425,10 +435,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authShaNoPriv", name: "v3 coldStart authShaNoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authShaNoPriv", secName: "authShaNoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -488,10 +498,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authShaNoPriv", name: "v3 coldStart authShaNoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSha224NoPriv", secName: "authSha224NoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "SHA224", authProto: "SHA224",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -550,10 +560,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSha256NoPriv", name: "v3 coldStart authSha256NoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSha256NoPriv", secName: "authSha256NoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "SHA256", authProto: "SHA256",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -612,10 +622,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSha384NoPriv", name: "v3 coldStart authSha384NoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSha384NoPriv", secName: "authSha384NoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "SHA384", authProto: "SHA384",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -674,10 +684,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authShaNoPriv", name: "v3 coldStart authShaNoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSha512NoPriv", secName: "authSha512NoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "SHA512", authProto: "SHA512",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -736,10 +746,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authShaNoPriv", name: "v3 coldStart authShaNoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authShaNoPriv", secName: "authShaNoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -798,10 +808,10 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authMD5NoPriv", name: "v3 coldStart authMD5NoPriv",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authMD5NoPriv", secName: "authMD5NoPriv",
seclevel: "authNoPriv", secLevel: "authNoPriv",
authproto: "MD5", authProto: "MD5",
authpass: "passpass", authPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -860,12 +870,12 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSHAPrivAES", name: "v3 coldStart authSHAPrivAES",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSHAPrivAES", secName: "authSHAPrivAES",
seclevel: "authPriv", secLevel: "authPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
privproto: "AES", privProto: "AES",
privpass: "passpass", privPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -924,12 +934,12 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSHAPrivDES", name: "v3 coldStart authSHAPrivDES",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSHAPrivDES", secName: "authSHAPrivDES",
seclevel: "authPriv", secLevel: "authPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
privproto: "DES", privProto: "DES",
privpass: "passpass", privPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -988,12 +998,12 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSHAPrivAES192", name: "v3 coldStart authSHAPrivAES192",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSHAPrivAES192", secName: "authSHAPrivAES192",
seclevel: "authPriv", secLevel: "authPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
privproto: "AES192", privProto: "AES192",
privpass: "passpass", privPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -1052,12 +1062,12 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSHAPrivAES192C", name: "v3 coldStart authSHAPrivAES192C",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSHAPrivAES192C", secName: "authSHAPrivAES192C",
seclevel: "authPriv", secLevel: "authPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
privproto: "AES192C", privProto: "AES192C",
privpass: "passpass", privPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -1116,12 +1126,12 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSHAPrivAES256", name: "v3 coldStart authSHAPrivAES256",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSHAPrivAES256", secName: "authSHAPrivAES256",
seclevel: "authPriv", secLevel: "authPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
privproto: "AES256", privProto: "AES256",
privpass: "passpass", privPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -1180,12 +1190,12 @@ func TestReceiveTrap(t *testing.T) {
{ {
name: "v3 coldStart authSHAPrivAES256C", name: "v3 coldStart authSHAPrivAES256C",
version: gosnmp.Version3, version: gosnmp.Version3,
secname: "authSHAPrivAES256C", secName: "authSHAPrivAES256C",
seclevel: "authPriv", secLevel: "authPriv",
authproto: "SHA", authProto: "SHA",
authpass: "passpass", authPass: "passpass",
privproto: "AES256C", privProto: "AES256C",
privpass: "passpass", privPass: "passpass",
trap: gosnmp.SnmpTrap{ trap: gosnmp.SnmpTrap{
Variables: []gosnmp.SnmpPDU{ Variables: []gosnmp.SnmpPDU{
{ {
@ -1269,15 +1279,12 @@ func TestReceiveTrap(t *testing.T) {
}, },
Log: testutil.Logger{}, Log: testutil.Logger{},
Version: tt.version.String(), Version: tt.version.String(),
SecName: tt.secname, SecName: tt.secName,
SecLevel: tt.seclevel, SecLevel: tt.secLevel,
AuthProtocol: tt.authproto, AuthProtocol: tt.authProto,
AuthPassword: tt.authpass, AuthPassword: tt.authPass,
PrivProtocol: tt.privproto, PrivProtocol: tt.privProto,
PrivPassword: tt.privpass, PrivPassword: tt.privPass,
EngineID: "80001f8880031dd407f608905e00000000",
EngineBoots: 1,
EngineTime: 1,
} }
require.Nil(t, s.Init()) require.Nil(t, s.Init())
var acc testutil.Accumulator var acc testutil.Accumulator
@ -1294,7 +1301,7 @@ func TestReceiveTrap(t *testing.T) {
s.execCmd = fakeExecCmd s.execCmd = fakeExecCmd
// Send the trap // 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 // Wait for trap to be received
select { select {