main.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright (c) 2017 Arista Networks, Inc.
  2. // Use of this source code is governed by the Apache License 2.0
  3. // that can be found in the COPYING file.
  4. package main
  5. import (
  6. "context"
  7. "crypto/tls"
  8. "flag"
  9. "fmt"
  10. "net/http"
  11. "os"
  12. "strings"
  13. "time"
  14. "notabug.org/themusicgod1/glog"
  15. "notabug.org/themusicgod1/goarista/gnmi"
  16. "notabug.org/themusicgod1/splunk-hec-go"
  17. pb "github.com/openconfig/gnmi/proto/gnmi"
  18. )
  19. func exitWithError(s string) {
  20. fmt.Fprintln(os.Stderr, s)
  21. os.Exit(1)
  22. }
  23. func main() {
  24. // gNMI options
  25. cfg := &gnmi.Config{}
  26. flag.StringVar(&cfg.Addr, "addr", "localhost", "gNMI gRPC server `address`")
  27. flag.StringVar(&cfg.CAFile, "cafile", "", "Path to server TLS certificate file")
  28. flag.StringVar(&cfg.CertFile, "certfile", "", "Path to client TLS certificate file")
  29. flag.StringVar(&cfg.KeyFile, "keyfile", "", "Path to client TLS private key file")
  30. flag.StringVar(&cfg.Username, "username", "", "Username to authenticate with")
  31. flag.StringVar(&cfg.Password, "password", "", "Password to authenticate with")
  32. flag.BoolVar(&cfg.TLS, "tls", false, "Enable TLS")
  33. subscribePaths := flag.String("paths", "/", "Comma-separated list of paths to subscribe to")
  34. // Splunk options
  35. splunkURLs := flag.String("splunkurls", "https://localhost:8088",
  36. "Comma-separated list of URLs of the Splunk servers")
  37. splunkToken := flag.String("splunktoken", "", "Token to connect to the Splunk servers")
  38. splunkIndex := flag.String("splunkindex", "", "Index for the data in Splunk")
  39. flag.Parse()
  40. // gNMI connection
  41. ctx := gnmi.NewContext(context.Background(), cfg)
  42. // Store the address without the port so it can be used as the host in the Splunk event.
  43. addr := cfg.Addr
  44. client, err := gnmi.Dial(cfg)
  45. if err != nil {
  46. glog.Fatal(err)
  47. }
  48. // Splunk connection
  49. urls := strings.Split(*splunkURLs, ",")
  50. cluster := hec.NewCluster(urls, *splunkToken)
  51. cluster.SetHTTPClient(&http.Client{
  52. Transport: &http.Transport{
  53. // TODO: add flags for TLS
  54. TLSClientConfig: &tls.Config{
  55. // TODO: add flag to enable TLS
  56. InsecureSkipVerify: true,
  57. },
  58. },
  59. })
  60. // gNMI subscription
  61. respChan := make(chan *pb.SubscribeResponse)
  62. errChan := make(chan error)
  63. defer close(respChan)
  64. defer close(errChan)
  65. paths := strings.Split(*subscribePaths, ",")
  66. go gnmi.Subscribe(ctx, client, gnmi.SplitPaths(paths), respChan, errChan)
  67. // Forward subscribe responses to Splunk
  68. for {
  69. select {
  70. // We got a subscribe response
  71. case resp := <-respChan:
  72. response := resp.GetResponse()
  73. update, ok := response.(*pb.SubscribeResponse_Update)
  74. if !ok {
  75. continue
  76. }
  77. // Convert the response into a map[string]interface{}
  78. notification, err := gnmi.NotificationToMap(update.Update)
  79. if err != nil {
  80. exitWithError(err.Error())
  81. }
  82. // Build the Splunk event
  83. path := notification["path"].(string)
  84. delete(notification, "path")
  85. timestamp := notification["timestamp"].(int64)
  86. delete(notification, "timestamp")
  87. // Should this be configurable?
  88. sourceType := "openconfig"
  89. event := &hec.Event{
  90. Host: &addr,
  91. Index: splunkIndex,
  92. Source: &path,
  93. SourceType: &sourceType,
  94. Event: notification,
  95. }
  96. event.SetTime(time.Unix(timestamp/1e9, timestamp%1e9))
  97. // Write the event to Splunk
  98. if err := cluster.WriteEvent(event); err != nil {
  99. exitWithError("failed to write event: " + err.Error())
  100. }
  101. // We got an error
  102. case err := <-errChan:
  103. exitWithError(err.Error())
  104. }
  105. }
  106. }