feat(contrib): add snmp2cpe (#1625)
This commit is contained in:
50
contrib/snmp2cpe/README.md
Normal file
50
contrib/snmp2cpe/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# snmp2cpe
|
||||
|
||||
## Main Features
|
||||
|
||||
- Estimate hardware and OS CPE from SNMP reply of network devices
|
||||
|
||||
## Installation
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/future-architect/vuls.git
|
||||
$ make build-snmp2cpe
|
||||
```
|
||||
|
||||
## Command Reference
|
||||
|
||||
```console
|
||||
$ snmp2cpe help
|
||||
snmp2cpe: SNMP reply To CPE
|
||||
|
||||
Usage:
|
||||
snmp2cpe [command]
|
||||
|
||||
Available Commands:
|
||||
completion Generate the autocompletion script for the specified shell
|
||||
convert snmpget reply to CPE
|
||||
help Help about any command
|
||||
v1 snmpget with SNMPv1
|
||||
v2c snmpget with SNMPv2c
|
||||
v3 snmpget with SNMPv3
|
||||
version Print the version
|
||||
|
||||
Flags:
|
||||
-h, --help help for snmp2cpe
|
||||
|
||||
Use "snmp2cpe [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
$ snmp2cpe v2c --debug 192.168.1.99 public
|
||||
2023/03/28 14:16:54 DEBUG: .1.3.6.1.2.1.1.1.0 ->
|
||||
2023/03/28 14:16:54 DEBUG: .1.3.6.1.2.1.47.1.1.1.1.12.1 -> Fortinet
|
||||
2023/03/28 14:16:54 DEBUG: .1.3.6.1.2.1.47.1.1.1.1.7.1 -> FGT_50E
|
||||
2023/03/28 14:16:54 DEBUG: .1.3.6.1.2.1.47.1.1.1.1.10.1 -> FortiGate-50E v5.4.6,build1165b1165,171018 (GA)
|
||||
{"192.168.1.99":{"entPhysicalTables":{"1":{"entPhysicalMfgName":"Fortinet","entPhysicalName":"FGT_50E","entPhysicalSoftwareRev":"FortiGate-50E v5.4.6,build1165b1165,171018 (GA)"}}}}
|
||||
|
||||
$ snmp2cpe v2c 192.168.1.99 public | snmp2cpe convert
|
||||
{"192.168.1.99":["cpe:2.3:h:fortinet:fortigate-50e:-:*:*:*:*:*:*:*","cpe:2.3:o:fortinet:fortios:5.4.6:*:*:*:*:*:*:*"]}
|
||||
```
|
||||
15
contrib/snmp2cpe/cmd/main.go
Normal file
15
contrib/snmp2cpe/cmd/main.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
rootCmd "github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cmd/root"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := rootCmd.NewCmdRoot().Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to exec snmp2cpe: %s\n", fmt.Sprintf("%+v", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
52
contrib/snmp2cpe/pkg/cmd/convert/convert.go
Normal file
52
contrib/snmp2cpe/pkg/cmd/convert/convert.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cpe"
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/snmp"
|
||||
)
|
||||
|
||||
// NewCmdConvert ...
|
||||
func NewCmdConvert() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "convert",
|
||||
Short: "snmpget reply to CPE",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Example: `$ snmp2cpe v2c 192.168.11.11 public | snmp2cpe convert
|
||||
$ snmp2cpe v2c 192.168.11.11 public | snmp2cpe convert -
|
||||
$ snmp2cpe v2c 192.168.11.11 public > v2c.json && snmp2cpe convert v2c.json`,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
r := os.Stdin
|
||||
if len(args) == 1 && args[0] != "-" {
|
||||
f, err := os.Open(args[0])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to open %s", args[0])
|
||||
}
|
||||
defer f.Close()
|
||||
r = f
|
||||
}
|
||||
|
||||
var reply map[string]snmp.Result
|
||||
if err := json.NewDecoder(r).Decode(&reply); err != nil {
|
||||
return errors.Wrap(err, "failed to decode")
|
||||
}
|
||||
|
||||
converted := map[string][]string{}
|
||||
for ipaddr, res := range reply {
|
||||
converted[ipaddr] = cpe.Convert(res)
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(os.Stdout).Encode(converted); err != nil {
|
||||
return errors.Wrap(err, "failed to encode")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
30
contrib/snmp2cpe/pkg/cmd/root/root.go
Normal file
30
contrib/snmp2cpe/pkg/cmd/root/root.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package root
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
convertCmd "github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cmd/convert"
|
||||
v1Cmd "github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cmd/v1"
|
||||
v2cCmd "github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cmd/v2c"
|
||||
v3Cmd "github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cmd/v3"
|
||||
versionCmd "github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cmd/version"
|
||||
)
|
||||
|
||||
// NewCmdRoot ...
|
||||
func NewCmdRoot() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "snmp2cpe <command>",
|
||||
Short: "snmp2cpe",
|
||||
Long: "snmp2cpe: SNMP reply To CPE",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
cmd.AddCommand(v1Cmd.NewCmdV1())
|
||||
cmd.AddCommand(v2cCmd.NewCmdV2c())
|
||||
cmd.AddCommand(v3Cmd.NewCmdV3())
|
||||
cmd.AddCommand(convertCmd.NewCmdConvert())
|
||||
cmd.AddCommand(versionCmd.NewCmdVersion())
|
||||
|
||||
return cmd
|
||||
}
|
||||
47
contrib/snmp2cpe/pkg/cmd/v1/v1.go
Normal file
47
contrib/snmp2cpe/pkg/cmd/v1/v1.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/gosnmp/gosnmp"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/snmp"
|
||||
)
|
||||
|
||||
// SNMPv1Options ...
|
||||
type SNMPv1Options struct {
|
||||
Debug bool
|
||||
}
|
||||
|
||||
// NewCmdV1 ...
|
||||
func NewCmdV1() *cobra.Command {
|
||||
opts := &SNMPv1Options{
|
||||
Debug: false,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "v1 <IP Address> <Community>",
|
||||
Short: "snmpget with SNMPv1",
|
||||
Example: "$ snmp2cpe v1 192.168.100.1 public",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
r, err := snmp.Get(gosnmp.Version1, args[0], snmp.WithCommunity(args[1]), snmp.WithDebug(opts.Debug))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to snmpget")
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(os.Stdout).Encode(map[string]snmp.Result{args[0]: r}); err != nil {
|
||||
return errors.Wrap(err, "failed to encode")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.Debug, "debug", "", false, "debug mode")
|
||||
|
||||
return cmd
|
||||
}
|
||||
47
contrib/snmp2cpe/pkg/cmd/v2c/v2c.go
Normal file
47
contrib/snmp2cpe/pkg/cmd/v2c/v2c.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package v2c
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/gosnmp/gosnmp"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/snmp"
|
||||
)
|
||||
|
||||
// SNMPv2cOptions ...
|
||||
type SNMPv2cOptions struct {
|
||||
Debug bool
|
||||
}
|
||||
|
||||
// NewCmdV2c ...
|
||||
func NewCmdV2c() *cobra.Command {
|
||||
opts := &SNMPv2cOptions{
|
||||
Debug: false,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "v2c <IP Address> <Community>",
|
||||
Short: "snmpget with SNMPv2c",
|
||||
Example: "$ snmp2cpe v2c 192.168.100.1 public",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
r, err := snmp.Get(gosnmp.Version2c, args[0], snmp.WithCommunity(args[1]), snmp.WithDebug(opts.Debug))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to snmpget")
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(os.Stdout).Encode(map[string]snmp.Result{args[0]: r}); err != nil {
|
||||
return errors.Wrap(err, "failed to encode")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.Debug, "debug", "", false, "debug mode")
|
||||
|
||||
return cmd
|
||||
}
|
||||
39
contrib/snmp2cpe/pkg/cmd/v3/v3.go
Normal file
39
contrib/snmp2cpe/pkg/cmd/v3/v3.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/gosnmp/gosnmp"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/snmp"
|
||||
)
|
||||
|
||||
// SNMPv3Options ...
|
||||
type SNMPv3Options struct {
|
||||
Debug bool
|
||||
}
|
||||
|
||||
// NewCmdV3 ...
|
||||
func NewCmdV3() *cobra.Command {
|
||||
opts := &SNMPv3Options{
|
||||
Debug: false,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "v3 <args>",
|
||||
Short: "snmpget with SNMPv3",
|
||||
Example: "$ snmp2cpe v3",
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
_, err := snmp.Get(gosnmp.Version3, "", snmp.WithDebug(opts.Debug))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to snmpget")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.Debug, "debug", "", false, "debug mode")
|
||||
|
||||
return cmd
|
||||
}
|
||||
23
contrib/snmp2cpe/pkg/cmd/version/version.go
Normal file
23
contrib/snmp2cpe/pkg/cmd/version/version.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/future-architect/vuls/config"
|
||||
)
|
||||
|
||||
// NewCmdVersion ...
|
||||
func NewCmdVersion() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the version",
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
fmt.Fprintf(os.Stdout, "snmp2cpe %s %s\n", config.Version, config.Revision)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
212
contrib/snmp2cpe/pkg/cpe/cpe.go
Normal file
212
contrib/snmp2cpe/pkg/cpe/cpe.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package cpe
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/snmp"
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/util"
|
||||
)
|
||||
|
||||
// Convert ...
|
||||
func Convert(result snmp.Result) []string {
|
||||
var cpes []string
|
||||
|
||||
switch detectVendor(result) {
|
||||
case "Cisco":
|
||||
var p, v string
|
||||
lhs, _, _ := strings.Cut(result.SysDescr0, " RELEASE SOFTWARE")
|
||||
for _, s := range strings.Split(lhs, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
switch {
|
||||
case strings.Contains(s, "Cisco NX-OS"):
|
||||
p = "nx-os"
|
||||
case strings.Contains(s, "Cisco IOS Software"), strings.Contains(s, "Cisco Internetwork Operating System Software IOS"):
|
||||
p = "ios"
|
||||
if strings.Contains(lhs, "IOSXE") || strings.Contains(lhs, "IOS-XE") {
|
||||
p = "ios_xe"
|
||||
}
|
||||
case strings.HasPrefix(s, "Version "):
|
||||
v = strings.ToLower(strings.TrimPrefix(s, "Version "))
|
||||
}
|
||||
}
|
||||
if p != "" && v != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:cisco:%s:%s:*:*:*:*:*:*:*", p, v))
|
||||
}
|
||||
|
||||
if t, ok := result.EntPhysicalTables[1]; ok {
|
||||
if t.EntPhysicalName != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:cisco:%s:-:*:*:*:*:*:*:*", strings.ToLower(t.EntPhysicalName)))
|
||||
}
|
||||
if p != "" && t.EntPhysicalSoftwareRev != "" {
|
||||
s, _, _ := strings.Cut(t.EntPhysicalSoftwareRev, " RELEASE SOFTWARE")
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:cisco:%s:%s:*:*:*:*:*:*:*", p, strings.ToLower(strings.TrimSuffix(s, ","))))
|
||||
}
|
||||
}
|
||||
case "Juniper Networks":
|
||||
if strings.HasPrefix(result.SysDescr0, "Juniper Networks, Inc.") {
|
||||
for _, s := range strings.Split(strings.TrimPrefix(result.SysDescr0, "Juniper Networks, Inc. "), ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
switch {
|
||||
case strings.HasPrefix(s, "qfx"), strings.HasPrefix(s, "ex"), strings.HasPrefix(s, "mx"), strings.HasPrefix(s, "ptx"), strings.HasPrefix(s, "acx"), strings.HasPrefix(s, "bti"), strings.HasPrefix(s, "srx"):
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:juniper:%s:-:*:*:*:*:*:*:*", strings.Fields(s)[0]))
|
||||
case strings.HasPrefix(s, "kernel JUNOS "):
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:juniper:junos:%s:*:*:*:*:*:*:*", strings.ToLower(strings.Fields(strings.TrimPrefix(s, "kernel JUNOS "))[0])))
|
||||
}
|
||||
}
|
||||
|
||||
if t, ok := result.EntPhysicalTables[1]; ok {
|
||||
if t.EntPhysicalSoftwareRev != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:juniper:junos:%s:*:*:*:*:*:*:*", strings.ToLower(t.EntPhysicalSoftwareRev)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
h, v, ok := strings.Cut(result.SysDescr0, " version ")
|
||||
if ok {
|
||||
cpes = append(cpes,
|
||||
fmt.Sprintf("cpe:2.3:h:juniper:%s:-:*:*:*:*:*:*:*", strings.ToLower(h)),
|
||||
fmt.Sprintf("cpe:2.3:o:juniper:screenos:%s:*:*:*:*:*:*:*", strings.ToLower(strings.Fields(v)[0])),
|
||||
)
|
||||
}
|
||||
}
|
||||
case "Arista Networks":
|
||||
v, h, ok := strings.Cut(result.SysDescr0, " running on an ")
|
||||
if ok {
|
||||
if strings.HasPrefix(v, "Arista Networks EOS version ") {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:arista:eos:%s:*:*:*:*:*:*:*", strings.ToLower(strings.TrimPrefix(v, "Arista Networks EOS version "))))
|
||||
}
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:/h:arista:%s:-:*:*:*:*:*:*:*", strings.ToLower(strings.TrimPrefix(h, "Arista Networks "))))
|
||||
}
|
||||
if t, ok := result.EntPhysicalTables[1]; ok {
|
||||
if t.EntPhysicalSoftwareRev != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:arista:eos:%s:*:*:*:*:*:*:*", strings.ToLower(t.EntPhysicalSoftwareRev)))
|
||||
}
|
||||
}
|
||||
case "Fortinet":
|
||||
if t, ok := result.EntPhysicalTables[1]; ok {
|
||||
if strings.HasPrefix(t.EntPhysicalName, "FGT_") {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:fortinet:fortigate-%s:-:*:*:*:*:*:*:*", strings.ToLower(strings.TrimPrefix(t.EntPhysicalName, "FGT_"))))
|
||||
}
|
||||
for _, s := range strings.Fields(t.EntPhysicalSoftwareRev) {
|
||||
switch {
|
||||
case strings.HasPrefix(s, "FortiGate-"):
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:fortinet:%s:-:*:*:*:*:*:*:*", strings.ToLower(s)))
|
||||
case strings.HasPrefix(s, "v") && strings.Contains(s, "build"):
|
||||
if v, _, found := strings.Cut(strings.TrimPrefix(s, "v"), ",build"); found {
|
||||
if _, err := version.NewVersion(v); err == nil {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:fortinet:fortios:%s:*:*:*:*:*:*:*", v))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case "YAMAHA":
|
||||
var h, v string
|
||||
for _, s := range strings.Fields(result.SysDescr0) {
|
||||
switch {
|
||||
case strings.HasPrefix(s, "RTX"), strings.HasPrefix(s, "NVR"), strings.HasPrefix(s, "RTV"), strings.HasPrefix(s, "RT"),
|
||||
strings.HasPrefix(s, "SRT"), strings.HasPrefix(s, "FWX"), strings.HasPrefix(s, "YSL-V810"):
|
||||
h = strings.ToLower(s)
|
||||
case strings.HasPrefix(s, "Rev."):
|
||||
if _, err := version.NewVersion(strings.TrimPrefix(s, "Rev.")); err == nil {
|
||||
v = strings.TrimPrefix(s, "Rev.")
|
||||
}
|
||||
}
|
||||
}
|
||||
if h != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:yamaha:%s:-:*:*:*:*:*:*:*", h))
|
||||
if v != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:yamaha:%s:%s:*:*:*:*:*:*:*", h, v))
|
||||
}
|
||||
}
|
||||
case "NEC":
|
||||
var h, v string
|
||||
for _, s := range strings.Split(result.SysDescr0, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
switch {
|
||||
case strings.HasPrefix(s, "IX Series "):
|
||||
h = strings.ToLower(strings.TrimSuffix(strings.TrimPrefix(s, "IX Series "), " (magellan-sec) Software"))
|
||||
case strings.HasPrefix(s, "Version "):
|
||||
if _, err := version.NewVersion(strings.TrimSpace(strings.TrimPrefix(s, "Version "))); err == nil {
|
||||
v = strings.TrimSpace(strings.TrimPrefix(s, "Version "))
|
||||
}
|
||||
}
|
||||
}
|
||||
if h != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:nec:%s:-:*:*:*:*:*:*:*", h))
|
||||
if v != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:nec:%s:%s:*:*:*:*:*:*:*", h, v))
|
||||
}
|
||||
}
|
||||
case "Palo Alto Networks":
|
||||
if t, ok := result.EntPhysicalTables[1]; ok {
|
||||
if t.EntPhysicalName != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:h:paloaltonetworks:%s:-:*:*:*:*:*:*:*", strings.ToLower(t.EntPhysicalName)))
|
||||
}
|
||||
if t.EntPhysicalSoftwareRev != "" {
|
||||
cpes = append(cpes, fmt.Sprintf("cpe:2.3:o:paloaltonetworks:pan-os:%s:*:*:*:*:*:*:*", t.EntPhysicalSoftwareRev))
|
||||
}
|
||||
}
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
|
||||
return util.Unique(cpes)
|
||||
}
|
||||
|
||||
func detectVendor(r snmp.Result) string {
|
||||
if t, ok := r.EntPhysicalTables[1]; ok {
|
||||
switch t.EntPhysicalMfgName {
|
||||
case "Cisco":
|
||||
return "Cisco"
|
||||
case "Juniper Networks":
|
||||
return "Juniper Networks"
|
||||
case "Arista Networks":
|
||||
return "Arista Networks"
|
||||
case "Fortinet":
|
||||
return "Fortinet"
|
||||
case "YAMAHA":
|
||||
return "YAMAHA"
|
||||
case "NEC":
|
||||
return "NEC"
|
||||
case "Palo Alto Networks":
|
||||
return "Palo Alto Networks"
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(r.SysDescr0, "Cisco"):
|
||||
return "Cisco"
|
||||
case strings.Contains(r.SysDescr0, "Juniper Networks"),
|
||||
strings.Contains(r.SysDescr0, "SSG5"), strings.Contains(r.SysDescr0, "SSG20"), strings.Contains(r.SysDescr0, "SSG140"),
|
||||
strings.Contains(r.SysDescr0, "SSG320"), strings.Contains(r.SysDescr0, "SSG350"), strings.Contains(r.SysDescr0, "SSG520"),
|
||||
strings.Contains(r.SysDescr0, "SSG550"):
|
||||
return "Juniper Networks"
|
||||
case strings.Contains(r.SysDescr0, "Arista Networks"):
|
||||
return "Arista Networks"
|
||||
case strings.Contains(r.SysDescr0, "Fortinet"), strings.Contains(r.SysDescr0, "FortiGate"):
|
||||
return "Fortinet"
|
||||
case strings.Contains(r.SysDescr0, "YAMAHA"),
|
||||
strings.Contains(r.SysDescr0, "RTX810"), strings.Contains(r.SysDescr0, "RTX830"),
|
||||
strings.Contains(r.SysDescr0, "RTX1000"), strings.Contains(r.SysDescr0, "RTX1100"),
|
||||
strings.Contains(r.SysDescr0, "RTX1200"), strings.Contains(r.SysDescr0, "RTX1210"), strings.Contains(r.SysDescr0, "RTX1220"),
|
||||
strings.Contains(r.SysDescr0, "RTX1300"), strings.Contains(r.SysDescr0, "RTX1500"), strings.Contains(r.SysDescr0, "RTX2000"),
|
||||
strings.Contains(r.SysDescr0, "RTX3000"), strings.Contains(r.SysDescr0, "RTX3500"), strings.Contains(r.SysDescr0, "RTX5000"),
|
||||
strings.Contains(r.SysDescr0, "NVR500"), strings.Contains(r.SysDescr0, "NVR510"), strings.Contains(r.SysDescr0, "NVR700W"),
|
||||
strings.Contains(r.SysDescr0, "RTV01"), strings.Contains(r.SysDescr0, "RTV700"),
|
||||
strings.Contains(r.SysDescr0, "RT105i"), strings.Contains(r.SysDescr0, "RT105p"), strings.Contains(r.SysDescr0, "RT105e"),
|
||||
strings.Contains(r.SysDescr0, "RT107e"), strings.Contains(r.SysDescr0, "RT250i"), strings.Contains(r.SysDescr0, "RT300i"),
|
||||
strings.Contains(r.SysDescr0, "SRT100"),
|
||||
strings.Contains(r.SysDescr0, "FWX100"),
|
||||
strings.Contains(r.SysDescr0, "YSL-V810"):
|
||||
return "YAMAHA"
|
||||
case strings.Contains(r.SysDescr0, "NEC"):
|
||||
return "NEC"
|
||||
case strings.Contains(r.SysDescr0, "Palo Alto Networks"):
|
||||
return "Palo Alto Networks"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
244
contrib/snmp2cpe/pkg/cpe/cpe_test.go
Normal file
244
contrib/snmp2cpe/pkg/cpe/cpe_test.go
Normal file
@@ -0,0 +1,244 @@
|
||||
package cpe_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/cpe"
|
||||
"github.com/future-architect/vuls/contrib/snmp2cpe/pkg/snmp"
|
||||
)
|
||||
|
||||
func TestConvert(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args snmp.Result
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "Cisco NX-OS Version 7.1(4)N1(1)",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Cisco NX-OS(tm) n6000, Software (n6000-uk9), Version 7.1(4)N1(1), RELEASE SOFTWARE Copyright (c) 2002-2012 by Cisco Systems, Inc. Device Manager Version 6.0(2)N1(1),Compiled 9/2/2016 10:00:00",
|
||||
},
|
||||
want: []string{"cpe:2.3:o:cisco:nx-os:7.1(4)n1(1):*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOS Version 15.1(4)M3",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco IOS Software, 2800 Software (C2800NM-ADVENTERPRISEK9-M), Version 15.1(4)M3, RELEASE SOFTWARE (fc1)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2011 by Cisco Systems, Inc.
|
||||
Compiled Tue 06-Dec-11 16:21 by prod_rel_team`,
|
||||
},
|
||||
want: []string{"cpe:2.3:o:cisco:ios:15.1(4)m3:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOS Version 15.1(4)M4",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco IOS Software, C181X Software (C181X-ADVENTERPRISEK9-M), Version 15.1(4)M4, RELEASE SOFTWARE (fc1)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2012 by Cisco Systems, Inc.
|
||||
Compiled Tue 20-Mar-12 23:34 by prod_rel_team`,
|
||||
},
|
||||
want: []string{"cpe:2.3:o:cisco:ios:15.1(4)m4:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOS Vresion 15.5(3)M on Cisco 892J-K9-V02",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco IOS Software, C890 Software (C890-UNIVERSALK9-M), Version 15.5(3)M, RELEASE SOFTWARE (fc1)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2015 by Cisco Systems, Inc.
|
||||
Compiled Thu 23-Jul-15 03:08 by prod_rel_team`,
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Cisco",
|
||||
EntPhysicalName: "892",
|
||||
EntPhysicalSoftwareRev: "15.5(3)M, RELEASE SOFTWARE (fc1)",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:cisco:892:-:*:*:*:*:*:*:*", "cpe:2.3:o:cisco:ios:15.5(3)m:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOS Version 15.4(3)M5 on Cisco C892FSP-K9-V02",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco IOS Software, C800 Software (C800-UNIVERSALK9-M), Version 15.4(3)M5, RELEASE SOFTWARE (fc1)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2016 by Cisco Systems, Inc.
|
||||
Compiled Tue 09-Feb-16 06:15 by prod_rel_team`,
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Cisco",
|
||||
EntPhysicalName: "C892FSP-K9",
|
||||
EntPhysicalSoftwareRev: "15.4(3)M5, RELEASE SOFTWARE (fc1)",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:cisco:c892fsp-k9:-:*:*:*:*:*:*:*", "cpe:2.3:o:cisco:ios:15.4(3)m5:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOS Version 12.2(17d)SXB11",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco Internetwork Operating System Software IOS (tm) s72033_rp Software (s72033_rp-JK9SV-M), Version 12.2(17d)SXB11, RELEASE SOFTWARE (fc1)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2005 by cisco Systems, Inc.`,
|
||||
},
|
||||
want: []string{"cpe:2.3:o:cisco:ios:12.2(17d)sxb11:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOX-XE Version 16.12.4",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco IOS Software [Gibraltar], Catalyst L3 Switch Software (CAT9K_LITE_IOSXE), Version 16.12.4, RELEASE SOFTWARE (fc5)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2020 by Cisco Systems, Inc.
|
||||
Compiled Thu 09-Jul-20 19:31 by m`,
|
||||
},
|
||||
want: []string{"cpe:2.3:o:cisco:ios_xe:16.12.4:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Cisco IOX-XE Version 03.06.07.E",
|
||||
args: snmp.Result{
|
||||
SysDescr0: `Cisco IOS Software, IOS-XE Software, Catalyst 4500 L3 Switch Software (cat4500es8-UNIVERSALK9-M), Version 03.06.07.E RELEASE SOFTWARE (fc3)
|
||||
Technical Support: http://www.cisco.com/techsupport
|
||||
Copyright (c) 1986-2017 by Cisco Systems, Inc.
|
||||
Compiled Wed`,
|
||||
},
|
||||
want: []string{"cpe:2.3:o:cisco:ios_xe:03.06.07.e:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Juniper SSG-5-SH-BT",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "SSG5-ISDN version 6.3.0r14.0 (SN: 0000000000000001, Firewall+VPN)",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:juniper:ssg5-isdn:-:*:*:*:*:*:*:*", "cpe:2.3:o:juniper:screenos:6.3.0r14.0:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "JUNOS 20.4R3-S4.8 on Juniper MX240",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Juniper Networks, Inc. mx240 internet router, kernel JUNOS 20.4R3-S4.8, Build date: 2022-08-16 20:42:11 UTC Copyright (c) 1996-2022 Juniper Networks, Inc.",
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Juniper Networks",
|
||||
EntPhysicalName: "CHAS-BP3-MX240-S",
|
||||
EntPhysicalSoftwareRev: "20.4R3-S4.8",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:juniper:mx240:-:*:*:*:*:*:*:*", "cpe:2.3:o:juniper:junos:20.4r3-s4.8:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "JUNOS 12.1X46-D65.4 on Juniper SRX220H",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Juniper Networks, Inc. srx220h internet router, kernel JUNOS 12.1X46-D65.4 #0: 2016-12-30 01:34:30 UTC builder@quoarth.juniper.net:/volume/build/junos/12.1/service/12.1X46-D65.4/obj-octeon/junos/bsd/kernels/JSRXNLE/kernel Build date: 2016-12-30 02:59",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:juniper:srx220h:-:*:*:*:*:*:*:*", "cpe:2.3:o:juniper:junos:12.1x46-d65.4:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "JUNOS 12.3X48-D30.7 on Juniper SRX220H2",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Juniper Networks, Inc. srx220h2 internet router, kernel JUNOS 12.3X48-D30.7, Build date: 2016-04-29 00:01:04 UTC Copyright (c) 1996-2016 Juniper Networks, Inc.",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:juniper:srx220h2:-:*:*:*:*:*:*:*", "cpe:2.3:o:juniper:junos:12.3x48-d30.7:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "JUNOS 20.4R3-S4.8 on Juniper SRX4600",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Juniper Networks, Inc. srx4600 internet router, kernel JUNOS 20.4R3-S4.8, Build date: 2022-08-16 20:42:11 UTC Copyright (c) 1996-2022 Juniper Networks, Inc.",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:juniper:srx4600:-:*:*:*:*:*:*:*", "cpe:2.3:o:juniper:junos:20.4r3-s4.8:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "cpe:2.3:o:juniper:junos:20.4:r2-s2.2:*:*:*:*:*:*",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Juniper Networks, Inc. ex4300-32f Ethernet Switch, kernel JUNOS 20.4R3-S4.8, Build date: 2022-08-16 21:10:45 UTC Copyright (c) 1996-2022 Juniper Networks, Inc.",
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Juniper Networks",
|
||||
EntPhysicalName: "",
|
||||
EntPhysicalSoftwareRev: "20.4R3-S4.8",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:juniper:ex4300-32f:-:*:*:*:*:*:*:*", "cpe:2.3:o:juniper:junos:20.4r3-s4.8:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Arista Networks EOS version 4.28.4M on DCS-7050TX-64",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Arista Networks EOS version 4.28.4M running on an Arista Networks DCS-7050TX-64",
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Arista Networks",
|
||||
EntPhysicalName: "",
|
||||
EntPhysicalSoftwareRev: "4.28.4M",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:/h:arista:dcs-7050tx-64:-:*:*:*:*:*:*:*", "cpe:2.3:o:arista:eos:4.28.4m:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "FortiGate-50E",
|
||||
args: snmp.Result{
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Fortinet",
|
||||
EntPhysicalName: "FGT_50E",
|
||||
EntPhysicalSoftwareRev: "FortiGate-50E v5.4.6,build1165b1165,171018 (GA)",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:fortinet:fortigate-50e:-:*:*:*:*:*:*:*", "cpe:2.3:o:fortinet:fortios:5.4.6:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "FortiGate-60F",
|
||||
args: snmp.Result{
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Fortinet",
|
||||
EntPhysicalName: "FGT_60F",
|
||||
EntPhysicalSoftwareRev: "FortiGate-60F v6.4.11,build2030,221031 (GA.M)",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:fortinet:fortigate-60f:-:*:*:*:*:*:*:*", "cpe:2.3:o:fortinet:fortios:6.4.11:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "YAMAHA RTX1000",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "RTX1000 Rev.8.01.29 (Fri Apr 15 11:50:44 2011)",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:yamaha:rtx1000:-:*:*:*:*:*:*:*", "cpe:2.3:o:yamaha:rtx1000:8.01.29:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "YAMAHA RTX810",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "RTX810 Rev.11.01.34 (Tue Nov 26 18:39:12 2019)",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:yamaha:rtx810:-:*:*:*:*:*:*:*", "cpe:2.3:o:yamaha:rtx810:11.01.34:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "NEC IX2105",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "NEC Portable Internetwork Core Operating System Software, IX Series IX2105 (magellan-sec) Software, Version 8.8.22, RELEASE SOFTWARE, Compiled Jul 04-Wed-2012 14:18:46 JST #2, IX2105",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:nec:ix2105:-:*:*:*:*:*:*:*", "cpe:2.3:o:nec:ix2105:8.8.22:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "NEC IX2235",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "NEC Portable Internetwork Core Operating System Software, IX Series IX2235 (magellan-sec) Software, Version 10.6.21, RELEASE SOFTWARE, Compiled Dec 15-Fri-YYYY HH:MM:SS JST #2, IX2235",
|
||||
},
|
||||
want: []string{"cpe:2.3:h:nec:ix2235:-:*:*:*:*:*:*:*", "cpe:2.3:o:nec:ix2235:10.6.21:*:*:*:*:*:*:*"},
|
||||
},
|
||||
{
|
||||
name: "Palo Alto Networks PAN-OS 10.0.0 on PA-220",
|
||||
args: snmp.Result{
|
||||
SysDescr0: "Palo Alto Networks PA-220 series firewall",
|
||||
EntPhysicalTables: map[int]snmp.EntPhysicalTable{1: {
|
||||
EntPhysicalMfgName: "Palo Alto Networks",
|
||||
EntPhysicalName: "PA-220",
|
||||
EntPhysicalSoftwareRev: "10.0.0",
|
||||
}},
|
||||
},
|
||||
want: []string{"cpe:2.3:h:paloaltonetworks:pa-220:-:*:*:*:*:*:*:*", "cpe:2.3:o:paloaltonetworks:pan-os:10.0.0:*:*:*:*:*:*:*"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
opts := []cmp.Option{
|
||||
cmpopts.SortSlices(func(i, j string) bool {
|
||||
return i < j
|
||||
}),
|
||||
}
|
||||
if diff := cmp.Diff(cpe.Convert(tt.args), tt.want, opts...); diff != "" {
|
||||
t.Errorf("Convert() value is mismatch (-got +want):%s\n", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
131
contrib/snmp2cpe/pkg/snmp/snmp.go
Normal file
131
contrib/snmp2cpe/pkg/snmp/snmp.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package snmp
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gosnmp/gosnmp"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
community string
|
||||
debug bool
|
||||
}
|
||||
|
||||
// Option ...
|
||||
type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
||||
type communityOption string
|
||||
|
||||
func (c communityOption) apply(opts *options) {
|
||||
opts.community = string(c)
|
||||
}
|
||||
|
||||
// WithCommunity ...
|
||||
func WithCommunity(c string) Option {
|
||||
return communityOption(c)
|
||||
}
|
||||
|
||||
type debugOption bool
|
||||
|
||||
func (d debugOption) apply(opts *options) {
|
||||
opts.debug = bool(d)
|
||||
}
|
||||
|
||||
// WithDebug ...
|
||||
func WithDebug(d bool) Option {
|
||||
return debugOption(d)
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func Get(version gosnmp.SnmpVersion, ipaddr string, opts ...Option) (Result, error) {
|
||||
var options options
|
||||
for _, o := range opts {
|
||||
o.apply(&options)
|
||||
}
|
||||
|
||||
r := Result{SysDescr0: "", EntPhysicalTables: map[int]EntPhysicalTable{}}
|
||||
|
||||
params := &gosnmp.GoSNMP{
|
||||
Target: ipaddr,
|
||||
Port: 161,
|
||||
Version: version,
|
||||
Timeout: time.Duration(2) * time.Second,
|
||||
Retries: 3,
|
||||
ExponentialTimeout: true,
|
||||
MaxOids: gosnmp.MaxOids,
|
||||
}
|
||||
|
||||
switch version {
|
||||
case gosnmp.Version1, gosnmp.Version2c:
|
||||
params.Community = options.community
|
||||
case gosnmp.Version3:
|
||||
return Result{}, errors.New("not implemented")
|
||||
}
|
||||
|
||||
if err := params.Connect(); err != nil {
|
||||
return Result{}, errors.Wrap(err, "failed to connect")
|
||||
}
|
||||
defer params.Conn.Close()
|
||||
|
||||
for _, oid := range []string{"1.3.6.1.2.1.1.1.0", "1.3.6.1.2.1.47.1.1.1.1.12.1", "1.3.6.1.2.1.47.1.1.1.1.7.1", "1.3.6.1.2.1.47.1.1.1.1.10.1"} {
|
||||
resp, err := params.Get([]string{oid})
|
||||
if err != nil {
|
||||
return Result{}, errors.Wrap(err, "send SNMP GET request")
|
||||
}
|
||||
for _, v := range resp.Variables {
|
||||
if options.debug {
|
||||
switch v.Type {
|
||||
case gosnmp.OctetString:
|
||||
log.Printf("DEBUG: %s -> %s", v.Name, string(v.Value.([]byte)))
|
||||
default:
|
||||
log.Printf("DEBUG: %s -> %v", v.Name, v.Value)
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case v.Name == ".1.3.6.1.2.1.1.1.0":
|
||||
if v.Type == gosnmp.OctetString {
|
||||
r.SysDescr0 = string(v.Value.([]byte))
|
||||
}
|
||||
case strings.HasPrefix(v.Name, ".1.3.6.1.2.1.47.1.1.1.1.12."):
|
||||
i, err := strconv.Atoi(strings.TrimPrefix(v.Name, ".1.3.6.1.2.1.47.1.1.1.1.12."))
|
||||
if err != nil {
|
||||
return Result{}, errors.Wrap(err, "failed to get index")
|
||||
}
|
||||
if v.Type == gosnmp.OctetString {
|
||||
b := r.EntPhysicalTables[i]
|
||||
b.EntPhysicalMfgName = string(v.Value.([]byte))
|
||||
r.EntPhysicalTables[i] = b
|
||||
}
|
||||
case strings.HasPrefix(v.Name, ".1.3.6.1.2.1.47.1.1.1.1.7."):
|
||||
i, err := strconv.Atoi(strings.TrimPrefix(v.Name, ".1.3.6.1.2.1.47.1.1.1.1.7."))
|
||||
if err != nil {
|
||||
return Result{}, errors.Wrap(err, "failed to get index")
|
||||
}
|
||||
if v.Type == gosnmp.OctetString {
|
||||
b := r.EntPhysicalTables[i]
|
||||
b.EntPhysicalName = string(v.Value.([]byte))
|
||||
r.EntPhysicalTables[i] = b
|
||||
}
|
||||
case strings.HasPrefix(v.Name, ".1.3.6.1.2.1.47.1.1.1.1.10."):
|
||||
i, err := strconv.Atoi(strings.TrimPrefix(v.Name, ".1.3.6.1.2.1.47.1.1.1.1.10."))
|
||||
if err != nil {
|
||||
return Result{}, errors.Wrap(err, "failed to get index")
|
||||
}
|
||||
if v.Type == gosnmp.OctetString {
|
||||
b := r.EntPhysicalTables[i]
|
||||
b.EntPhysicalSoftwareRev = string(v.Value.([]byte))
|
||||
r.EntPhysicalTables[i] = b
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
14
contrib/snmp2cpe/pkg/snmp/types.go
Normal file
14
contrib/snmp2cpe/pkg/snmp/types.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package snmp
|
||||
|
||||
// Result ...
|
||||
type Result struct {
|
||||
SysDescr0 string `json:"sysDescr0,omitempty"`
|
||||
EntPhysicalTables map[int]EntPhysicalTable `json:"entPhysicalTables,omitempty"`
|
||||
}
|
||||
|
||||
// EntPhysicalTable ...
|
||||
type EntPhysicalTable struct {
|
||||
EntPhysicalMfgName string `json:"entPhysicalMfgName,omitempty"`
|
||||
EntPhysicalName string `json:"entPhysicalName,omitempty"`
|
||||
EntPhysicalSoftwareRev string `json:"entPhysicalSoftwareRev,omitempty"`
|
||||
}
|
||||
12
contrib/snmp2cpe/pkg/util/util.go
Normal file
12
contrib/snmp2cpe/pkg/util/util.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package util
|
||||
|
||||
import "golang.org/x/exp/maps"
|
||||
|
||||
// Unique return unique elements
|
||||
func Unique[T comparable](s []T) []T {
|
||||
m := map[T]struct{}{}
|
||||
for _, v := range s {
|
||||
m[v] = struct{}{}
|
||||
}
|
||||
return maps.Keys(m)
|
||||
}
|
||||
Reference in New Issue
Block a user